• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavcodec/libgsm.c

Go to the documentation of this file.
00001 /*
00002  * Interface to libgsm for gsm encoding/decoding
00003  * Copyright (c) 2005 Alban Bedel <albeu@free.fr>
00004  * Copyright (c) 2006, 2007 Michel Bardiaux <mbardiaux@mediaxim.be>
00005  *
00006  * This file is part of FFmpeg.
00007  *
00008  * FFmpeg is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Lesser General Public
00010  * License as published by the Free Software Foundation; either
00011  * version 2.1 of the License, or (at your option) any later version.
00012  *
00013  * FFmpeg is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * Lesser General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public
00019  * License along with FFmpeg; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00021  */
00022 
00028 // The idiosyncrasies of GSM-in-WAV are explained at http://kbs.cs.tu-berlin.de/~jutta/toast.html
00029 
00030 #include "avcodec.h"
00031 #include <gsm/gsm.h>
00032 
00033 // gsm.h misses some essential constants
00034 #define GSM_BLOCK_SIZE 33
00035 #define GSM_MS_BLOCK_SIZE 65
00036 #define GSM_FRAME_SIZE 160
00037 
00038 static av_cold int libgsm_init(AVCodecContext *avctx) {
00039     if (avctx->channels > 1) {
00040         av_log(avctx, AV_LOG_ERROR, "Mono required for GSM, got %d channels\n",
00041                avctx->channels);
00042         return -1;
00043     }
00044 
00045     if(avctx->codec->decode){
00046         if(!avctx->channels)
00047             avctx->channels= 1;
00048 
00049         if(!avctx->sample_rate)
00050             avctx->sample_rate= 8000;
00051 
00052         avctx->sample_fmt = SAMPLE_FMT_S16;
00053     }else{
00054         if (avctx->sample_rate != 8000) {
00055             av_log(avctx, AV_LOG_ERROR, "Sample rate 8000Hz required for GSM, got %dHz\n",
00056                 avctx->sample_rate);
00057             if(avctx->strict_std_compliance > FF_COMPLIANCE_INOFFICIAL)
00058                 return -1;
00059         }
00060         if (avctx->bit_rate != 13000 /* Official */ &&
00061             avctx->bit_rate != 13200 /* Very common */ &&
00062             avctx->bit_rate != 0 /* Unknown; a.o. mov does not set bitrate when decoding */ ) {
00063             av_log(avctx, AV_LOG_ERROR, "Bitrate 13000bps required for GSM, got %dbps\n",
00064                 avctx->bit_rate);
00065             if(avctx->strict_std_compliance > FF_COMPLIANCE_INOFFICIAL)
00066                 return -1;
00067         }
00068     }
00069 
00070     avctx->priv_data = gsm_create();
00071 
00072     switch(avctx->codec_id) {
00073     case CODEC_ID_GSM:
00074         avctx->frame_size = GSM_FRAME_SIZE;
00075         avctx->block_align = GSM_BLOCK_SIZE;
00076         break;
00077     case CODEC_ID_GSM_MS: {
00078         int one = 1;
00079         gsm_option(avctx->priv_data, GSM_OPT_WAV49, &one);
00080         avctx->frame_size = 2*GSM_FRAME_SIZE;
00081         avctx->block_align = GSM_MS_BLOCK_SIZE;
00082         }
00083     }
00084 
00085     avctx->coded_frame= avcodec_alloc_frame();
00086     avctx->coded_frame->key_frame= 1;
00087 
00088     return 0;
00089 }
00090 
00091 static av_cold int libgsm_close(AVCodecContext *avctx) {
00092     av_freep(&avctx->coded_frame);
00093     gsm_destroy(avctx->priv_data);
00094     avctx->priv_data = NULL;
00095     return 0;
00096 }
00097 
00098 static int libgsm_encode_frame(AVCodecContext *avctx,
00099                                unsigned char *frame, int buf_size, void *data) {
00100     // we need a full block
00101     if(buf_size < avctx->block_align) return 0;
00102 
00103     switch(avctx->codec_id) {
00104     case CODEC_ID_GSM:
00105         gsm_encode(avctx->priv_data,data,frame);
00106         break;
00107     case CODEC_ID_GSM_MS:
00108         gsm_encode(avctx->priv_data,data,frame);
00109         gsm_encode(avctx->priv_data,((short*)data)+GSM_FRAME_SIZE,frame+32);
00110     }
00111     return avctx->block_align;
00112 }
00113 
00114 
00115 AVCodec libgsm_encoder = {
00116     "libgsm",
00117     AVMEDIA_TYPE_AUDIO,
00118     CODEC_ID_GSM,
00119     0,
00120     libgsm_init,
00121     libgsm_encode_frame,
00122     libgsm_close,
00123     .sample_fmts = (const enum SampleFormat[]){SAMPLE_FMT_S16,SAMPLE_FMT_NONE},
00124     .long_name = NULL_IF_CONFIG_SMALL("libgsm GSM"),
00125 };
00126 
00127 AVCodec libgsm_ms_encoder = {
00128     "libgsm_ms",
00129     AVMEDIA_TYPE_AUDIO,
00130     CODEC_ID_GSM_MS,
00131     0,
00132     libgsm_init,
00133     libgsm_encode_frame,
00134     libgsm_close,
00135     .sample_fmts = (const enum SampleFormat[]){SAMPLE_FMT_S16,SAMPLE_FMT_NONE},
00136     .long_name = NULL_IF_CONFIG_SMALL("libgsm GSM Microsoft variant"),
00137 };
00138 
00139 static int libgsm_decode_frame(AVCodecContext *avctx,
00140                                void *data, int *data_size,
00141                                AVPacket *avpkt) {
00142     const uint8_t *buf = avpkt->data;
00143     int buf_size = avpkt->size;
00144     *data_size = 0; /* In case of error */
00145     if(buf_size < avctx->block_align) return -1;
00146     switch(avctx->codec_id) {
00147     case CODEC_ID_GSM:
00148         if(gsm_decode(avctx->priv_data,buf,data)) return -1;
00149         *data_size = GSM_FRAME_SIZE*sizeof(int16_t);
00150         break;
00151     case CODEC_ID_GSM_MS:
00152         if(gsm_decode(avctx->priv_data,buf,data) ||
00153            gsm_decode(avctx->priv_data,buf+33,((int16_t*)data)+GSM_FRAME_SIZE)) return -1;
00154         *data_size = GSM_FRAME_SIZE*sizeof(int16_t)*2;
00155     }
00156     return avctx->block_align;
00157 }
00158 
00159 AVCodec libgsm_decoder = {
00160     "libgsm",
00161     AVMEDIA_TYPE_AUDIO,
00162     CODEC_ID_GSM,
00163     0,
00164     libgsm_init,
00165     NULL,
00166     libgsm_close,
00167     libgsm_decode_frame,
00168     .long_name = NULL_IF_CONFIG_SMALL("libgsm GSM"),
00169 };
00170 
00171 AVCodec libgsm_ms_decoder = {
00172     "libgsm_ms",
00173     AVMEDIA_TYPE_AUDIO,
00174     CODEC_ID_GSM_MS,
00175     0,
00176     libgsm_init,
00177     NULL,
00178     libgsm_close,
00179     libgsm_decode_frame,
00180     .long_name = NULL_IF_CONFIG_SMALL("libgsm GSM Microsoft variant"),
00181 };

Generated on Fri Sep 16 2011 17:17:38 for FFmpeg by  doxygen 1.7.1