Commit d663a1fd authored by Michael Niedermayer's avatar Michael Niedermayer

AMR-WB support by (Johannes Carlsson <joca at rixmail dot se>)

Originally committed as revision 2311 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent cd1f22f9
...@@ -102,6 +102,7 @@ SLIBSUF=".so" ...@@ -102,6 +102,7 @@ SLIBSUF=".so"
EXESUF="" EXESUF=""
risky="yes" risky="yes"
amr_nb="no" amr_nb="no"
amr_wb="no"
amr_nb_fixed="no" amr_nb_fixed="no"
sunmlib="no" sunmlib="no"
...@@ -850,6 +851,7 @@ fi ...@@ -850,6 +851,7 @@ fi
echo "Sun medialib support" $sunmlib echo "Sun medialib support" $sunmlib
echo "AMR-NB float support" $amr_nb echo "AMR-NB float support" $amr_nb
echo "AMR-NB fixed support" $amr_nb_fixed echo "AMR-NB fixed support" $amr_nb_fixed
echo "AMR-WB float support" $amr_wb
echo "Creating config.mak and config.h" echo "Creating config.mak and config.h"
...@@ -1137,6 +1139,17 @@ if test "$source_path_used" = "yes" ; then ...@@ -1137,6 +1139,17 @@ if test "$source_path_used" = "yes" ; then
fi fi
echo "SRC_PATH=$source_path" >> config.mak echo "SRC_PATH=$source_path" >> config.mak
if test "$amr_wb" = "yes" ; then
echo "#define AMR_WB 1" >> $TMPH
echo "AMR_WB=yes" >> config.mak
echo
echo "AMR WB FLOAT NOTICE ! Make sure you have downloaded TS26.204"
echo "V5.1.0 from "
echo "http://www.3gpp.org/ftp/Specs/archive/26_series/26.204/26204-510.zip"
echo "and extracted the source to libavcodec/amrwb_float"
echo
fi
if test "$amr_nb" = "yes" ; then if test "$amr_nb" = "yes" ; then
echo "#define AMR_NB 1" >> $TMPH echo "#define AMR_NB 1" >> $TMPH
echo "AMR_NB=yes" >> config.mak echo "AMR_NB=yes" >> config.mak
......
...@@ -716,6 +716,8 @@ solutions. ...@@ -716,6 +716,8 @@ solutions.
@tab Real 28800 bit/s codec @tab Real 28800 bit/s codec
@item AMR-NB @tab X @tab X @item AMR-NB @tab X @tab X
@tab supported through an external library @tab supported through an external library
@item AMR-WB @tab X @tab X
@tab supported through an external library
@item DV audio @tab @tab X @item DV audio @tab @tab X
@item Id RoQ DPCM @tab @tab X @item Id RoQ DPCM @tab @tab X
@tab used in Quake III, Jedi Knight 2, other computer games @tab used in Quake III, Jedi Knight 2, other computer games
......
...@@ -31,6 +31,15 @@ CLEANAMR=cleanamrfloat ...@@ -31,6 +31,15 @@ CLEANAMR=cleanamrfloat
endif endif
endif endif
ifeq ($(AMR_WB),yes)
OBJS+= amr.o amrwb_float/dec_acelp.o amrwb_float/dec_dtx.o amrwb_float/dec_gain.o \
amrwb_float/dec_if.o amrwb_float/dec_lpc.o amrwb_float/dec_main.o \
amrwb_float/dec_rom.o amrwb_float/dec_util.o amrwb_float/enc_acelp.o \
amrwb_float/enc_dtx.o amrwb_float/enc_gain.o amrwb_float/enc_if.o \
amrwb_float/enc_lpc.o amrwb_float/enc_main.o amrwb_float/enc_rom.o \
amrwb_float/enc_util.o amrwb_float/if_rom.o
endif
CLEANAMRWB=cleanamrwbfloat
ASM_OBJS= ASM_OBJS=
# codecs which are patented in some non free countries like the us # codecs which are patented in some non free countries like the us
...@@ -202,6 +211,9 @@ cleanamr: ...@@ -202,6 +211,9 @@ cleanamr:
cleanamrfloat: cleanamrfloat:
rm -f amr_float/*.o rm -f amr_float/*.o
cleanamrwbfloat:
$(MAKE) -C amrwb_float -f makefile.gcc clean
# api example program # api example program
apiexample: apiexample.c $(LIB) apiexample: apiexample.c $(LIB)
$(CC) $(CFLAGS) -o $@ $< $(LIB) $(EXTRALIBS) -lm $(CC) $(CFLAGS) -o $@ $< $(LIB) $(EXTRALIBS) -lm
......
...@@ -138,6 +138,12 @@ void avcodec_register_all(void) ...@@ -138,6 +138,12 @@ void avcodec_register_all(void)
register_avcodec(&amr_nb_decoder); register_avcodec(&amr_nb_decoder);
register_avcodec(&amr_nb_encoder); register_avcodec(&amr_nb_encoder);
#endif /* AMR_NB */ #endif /* AMR_NB */
#ifdef AMR_WB
register_avcodec(&amr_wb_decoder);
register_avcodec(&amr_wb_encoder);
#endif /* AMR_WB */
/* pcm codecs */ /* pcm codecs */
#define PCM_CODEC(id, name) \ #define PCM_CODEC(id, name) \
......
...@@ -17,31 +17,42 @@ ...@@ -17,31 +17,42 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
/* /*
This code implements amr-nb audio encoder/decoder through external reference This code implements amr-nb and amr-wb audio encoder/decoder through external reference
code from www.3gpp.org. The licence of the code from 3gpp is unclear so you code from www.3gpp.org. The licence of the code from 3gpp is unclear so you
have to download the code separately. Two versions exists: One fixed-point have to download the code separately. Two versions exists: One fixed-point
and one with floats. For some reason the float-encoder is significant faster and one with floats. For some reason the float-encoder is significant faster
atleast on a P4 1.5GHz (0.9s instead of 9.9s on a 30s audio clip at MR102). atleast on a P4 1.5GHz (0.9s instead of 9.9s on a 30s audio clip at MR102).
Both float and fixed point is supported for amr-nb, but only float for
amr-wb.
--AMR-NB--
The fixed-point (TS26.073) can be downloaded from: The fixed-point (TS26.073) can be downloaded from:
http://www.3gpp.org/ftp/Specs/latest/Rel-5/26_series/26073-510.zip http://www.3gpp.org/ftp/Specs/archive/26_series/26.073/26073-510.zip
Extract the soure into ffmpeg/libavcodec/amr Extract the soure into ffmpeg/libavcodec/amr
To use the float version run "./configure" with "--enable-amr-nb-fixed" To use the fixed version run "./configure" with "--enable-amr-nb-fixed"
The float version (default) can be downloaded from: The float version (default) can be downloaded from:
http://www.3gpp.org/ftp/Specs/latest/Rel-5/26_series/26104-510.zip http://www.3gpp.org/ftp/Specs/archive/26_series/26.104/26104-510.zip
Extract the soure into ffmpeg/libavcodec/amr_float Extract the soure into ffmpeg/libavcodec/amr_float
The specification for amr-nb can be found in TS 26.071 The specification for amr-nb can be found in TS 26.071
(http://www.3gpp.org/ftp/Specs/html-info/26071.htm) and some other (http://www.3gpp.org/ftp/Specs/html-info/26071.htm) and some other
info at http://www.3gpp.org/ftp/Specs/html-info/26-series.htm info at http://www.3gpp.org/ftp/Specs/html-info/26-series.htm
In the future support for AMR-WB might also be included here. --AMR-WB--
Reference code exist in TS26.173 and TS 26.204. The reference code can be downloaded from:
http://www.3gpp.org/ftp/Specs/archive/26_series/26.204/26204-510.zip
It should be extracted to "libavcodec/amrwb_float". Enable it with
"--enable-amr-wb".
The specification for amr-wb can be downloaded from:
http://www.3gpp.org/ftp/Specs/archive/26_series/26.171/26171-500.zip
If someone want to use the fixed point version it can be downloaded
from: http://www.3gpp.org/ftp/Specs/archive/26_series/26.173/26173-571.zip
*/ */
#define DEBUG
//#define AMR_NB_FIXED
#include "../config.h" #include "../config.h"
#include "avcodec.h" #include "avcodec.h"
...@@ -86,7 +97,7 @@ static enum Mode getBitrateMode(int bitrate) ...@@ -86,7 +97,7 @@ static enum Mode getBitrateMode(int bitrate)
}; };
int i; int i;
for(i=0;i<sizeof(rates);i++) for(i=0;i<8;i++)
{ {
if(rates[i].startrate<=bitrate && rates[i].stoprate>=bitrate) if(rates[i].startrate<=bitrate && rates[i].stoprate>=bitrate)
{ {
...@@ -148,17 +159,19 @@ static int amr_nb_encode_init(AVCodecContext * avctx) ...@@ -148,17 +159,19 @@ static int amr_nb_encode_init(AVCodecContext * avctx)
if(avctx->sample_rate!=8000) if(avctx->sample_rate!=8000)
{ {
#ifdef DEBUG if(avctx->debug)
printf("Only 8000Hz sample rate supported\n"); {
#endif fprintf(stderr, "Only 8000Hz sample rate supported\n");
}
return -1; return -1;
} }
if(avctx->channels!=1) if(avctx->channels!=1)
{ {
#ifdef DEBUG if(avctx->debug)
printf("Only mono supported\n"); {
#endif fprintf(stderr, "Only mono supported\n");
}
return -1; return -1;
} }
...@@ -167,9 +180,10 @@ static int amr_nb_encode_init(AVCodecContext * avctx) ...@@ -167,9 +180,10 @@ static int amr_nb_encode_init(AVCodecContext * avctx)
if(Speech_Encode_Frame_init(&s->enstate, 0, "encoder") || sid_sync_init (&s->sidstate)) if(Speech_Encode_Frame_init(&s->enstate, 0, "encoder") || sid_sync_init (&s->sidstate))
{ {
#ifdef DEBUG if(avctx->debug)
printf("Speech_Encode_Frame_init error\n"); {
#endif fprintf(stderr, "Speech_Encode_Frame_init error\n");
}
return -1; return -1;
} }
...@@ -343,17 +357,19 @@ static int amr_nb_encode_init(AVCodecContext * avctx) ...@@ -343,17 +357,19 @@ static int amr_nb_encode_init(AVCodecContext * avctx)
if(avctx->sample_rate!=8000) if(avctx->sample_rate!=8000)
{ {
#ifdef DEBUG if(avctx->debug)
printf("Only 8000Hz sample rate supported\n"); {
#endif fprintf(stderr, "Only 8000Hz sample rate supported\n");
}
return -1; return -1;
} }
if(avctx->channels!=1) if(avctx->channels!=1)
{ {
#ifdef DEBUG if(avctx->debug)
printf("Only mono supported\n"); {
#endif fprintf(stderr, "Only mono supported\n");
}
return -1; return -1;
} }
...@@ -363,7 +379,10 @@ static int amr_nb_encode_init(AVCodecContext * avctx) ...@@ -363,7 +379,10 @@ static int amr_nb_encode_init(AVCodecContext * avctx)
s->enstate=Encoder_Interface_init(0); s->enstate=Encoder_Interface_init(0);
if(!s->enstate) if(!s->enstate)
{ {
printf("Encoder_Interface_init error\n"); if(avctx->debug)
{
fprintf(stderr, "Encoder_Interface_init error\n");
}
return -1; return -1;
} }
...@@ -458,3 +477,176 @@ AVCodec amr_nb_encoder = ...@@ -458,3 +477,176 @@ AVCodec amr_nb_encoder =
amr_nb_encode_close, amr_nb_encode_close,
NULL, NULL,
}; };
/* -----------AMR wideband ------------*/
#ifdef AMR_WB
#ifdef _TYPEDEF_H
//To avoid duplicate typedefs from typdef in amr-nb
#define typedef_h
#endif
#include "amrwb_float/enc_if.h"
#include "amrwb_float/dec_if.h"
/* Common code for fixed and float version*/
typedef struct AMRWB_bitrates
{
int startrate;
int stoprate;
int mode;
} AMRWB_bitrates;
static int getWBBitrateMode(int bitrate)
{
/* Adjusted so that all bitrates can be used from commandline where
only a multiple of 1000 can be specified*/
AMRWB_bitrates rates[]={ {0,7999,0}, //6.6kHz
{8000,9999,1},//8.85
{10000,13000,2},//12.65
{13001,14999,3},//14.25
{15000,17000,4},//15.85
{17001,18000,5},//18.25
{18001,22000,6},//19.85
{22001,23000,7},//23.05
{23001,24000,8},//23.85
};
int i;
for(i=0;i<9;i++)
{
if(rates[i].startrate<=bitrate && rates[i].stoprate>=bitrate)
{
return(rates[i].mode);
}
}
/*Return highest possible*/
return(8);
}
typedef struct AMRWBContext {
int frameCount;
void *state;
int mode;
Word16 allow_dtx;
} AMRWBContext;
static int amr_wb_encode_init(AVCodecContext * avctx)
{
AMRWBContext *s = (AMRWBContext*)avctx->priv_data;
s->frameCount=0;
if(avctx->sample_rate!=16000)
{
if(avctx->debug)
{
fprintf(stderr, "Only 16000Hz sample rate supported\n");
}
return -1;
}
if(avctx->channels!=1)
{
if(avctx->debug)
{
fprintf(stderr, "Only mono supported\n");
}
return -1;
}
avctx->frame_size=320;
avctx->coded_frame= avcodec_alloc_frame();
s->state = E_IF_init();
s->mode=getWBBitrateMode(avctx->bit_rate);
s->allow_dtx=0;
return 0;
}
static int amr_wb_encode_close(AVCodecContext * avctx)
{
AMRWBContext *s = (AMRWBContext*) avctx->priv_data;
E_IF_exit(s->state);
av_freep(&avctx->coded_frame);
s->frameCount++;
return 0;
}
static int amr_wb_encode_frame(AVCodecContext *avctx,
unsigned char *frame/*out*/, int buf_size, void *data/*in*/)
{
AMRWBContext *s = (AMRWBContext*) avctx->priv_data;
int size = E_IF_encode(s->state, s->mode, data, frame, s->allow_dtx);
return size;
}
static int amr_wb_decode_init(AVCodecContext * avctx)
{
AMRWBContext *s = (AMRWBContext *)avctx->priv_data;
s->frameCount=0;
s->state = D_IF_init();
return 0;
}
extern const UWord8 block_size[];
static int amr_wb_decode_frame(AVCodecContext * avctx,
void *data, int *data_size,
uint8_t * buf, int buf_size)
{
AMRWBContext *s = (AMRWBContext*)avctx->priv_data;
uint8_t*amrData=buf;
int offset=0;
int mode;
int packet_size;
*data_size=0;
while(offset<buf_size)
{
s->frameCount++;
mode = (Word16)((amrData[offset] >> 3) & 0x0F);
packet_size = block_size[mode];
D_IF_decode( s->state, &amrData[offset], data+*data_size, _good_frame);
*data_size+=320*2;
offset+=packet_size;
}
return buf_size;
}
static int amr_wb_decode_close(AVCodecContext * avctx)
{
AMRWBContext *s = (AMRWBContext *)avctx->priv_data;
D_IF_exit(s->state);
return 0;
}
AVCodec amr_wb_decoder =
{
"amr_wb",
CODEC_TYPE_AUDIO,
CODEC_ID_AMR_WB,
sizeof(AMRWBContext),
amr_wb_decode_init,
NULL,
amr_wb_decode_close,
amr_wb_decode_frame,
};
AVCodec amr_wb_encoder =
{
"amr_wb",
CODEC_TYPE_AUDIO,
CODEC_ID_AMR_WB,
sizeof(AMRWBContext),
amr_wb_encode_init,
amr_wb_encode_frame,
amr_wb_encode_close,
NULL,
};
#endif //AMR_WB
...@@ -95,6 +95,8 @@ enum CodecID { ...@@ -95,6 +95,8 @@ enum CodecID {
/* AMR */ /* AMR */
CODEC_ID_AMR_NB, CODEC_ID_AMR_NB,
CODEC_ID_AMR_WB,
/* RealAudio codecs*/ /* RealAudio codecs*/
CODEC_ID_RA_144, CODEC_ID_RA_144,
CODEC_ID_RA_288, CODEC_ID_RA_288,
...@@ -1403,6 +1405,8 @@ extern AVCodec indeo3_decoder; ...@@ -1403,6 +1405,8 @@ extern AVCodec indeo3_decoder;
extern AVCodec vp3_decoder; extern AVCodec vp3_decoder;
extern AVCodec amr_nb_decoder; extern AVCodec amr_nb_decoder;
extern AVCodec amr_nb_encoder; extern AVCodec amr_nb_encoder;
extern AVCodec amr_wb_encoder;
extern AVCodec amr_wb_decoder;
extern AVCodec aac_decoder; extern AVCodec aac_decoder;
extern AVCodec mpeg4aac_decoder; extern AVCodec mpeg4aac_decoder;
extern AVCodec asv1_decoder; extern AVCodec asv1_decoder;
......
...@@ -21,7 +21,7 @@ ifeq ($(CONFIG_RISKY),yes) ...@@ -21,7 +21,7 @@ ifeq ($(CONFIG_RISKY),yes)
OBJS+= asf.o OBJS+= asf.o
endif endif
ifeq ($(AMR_NB),yes) ifeq ($(AMR_NB),yes) | ifeq ($(AMR_NB_FIXED),yes) | ifeq ($(AMR_WB),yes)
OBJS+= amr.o OBJS+= amr.o
endif endif
......
...@@ -57,7 +57,7 @@ void av_register_all(void) ...@@ -57,7 +57,7 @@ void av_register_all(void)
ipmovie_init(); ipmovie_init();
wc3_init(); wc3_init();
#ifdef AMR_NB #if defined(AMR_NB) || defined(AMR_NB_FIXED) || defined(AMR_WB)
amr_init(); amr_init();
#endif #endif
yuv4mpeg_init(); yuv4mpeg_init();
......
...@@ -20,34 +20,34 @@ ...@@ -20,34 +20,34 @@
/* /*
Write and read amr data according to RFC3267, http://www.ietf.org/rfc/rfc3267.txt?number=3267 Write and read amr data according to RFC3267, http://www.ietf.org/rfc/rfc3267.txt?number=3267
Only amr narrowband (not amr-wb) is supported for now. Only mono files are supported.
*/ */
#include "avformat.h" #include "avformat.h"
#include "avi.h"
static const unsigned char AMR_header [] = "#!AMR\n"; static const unsigned char AMR_header [] = "#!AMR\n";
static const unsigned char AMRWB_header [] = "#!AMR-WB\n";
/* AMR_FILE header */
static int put_amr_header(ByteIOContext *pb, AVCodecContext *enc)
{
put_tag(pb, AMR_header); /* magic number */
return 0;
}
static int amr_write_header(AVFormatContext *s) static int amr_write_header(AVFormatContext *s)
{ {
ByteIOContext *pb = &s->pb; ByteIOContext *pb = &s->pb;
AVCodecContext *enc = &s->streams[0]->codec;
s->priv_data = NULL; s->priv_data = NULL;
/* format header */ if (enc->codec_id == CODEC_ID_AMR_NB)
if (put_amr_header(pb, &s->streams[0]->codec) < 0) { {
return -1; put_tag(pb, AMR_header); /* magic number */
}
else if(enc->codec_id == CODEC_ID_AMR_WB)
{
put_tag(pb, AMRWB_header); /* magic number */
}
else
{
//This is an error!
} }
put_flush_packet(pb); put_flush_packet(pb);
return 0; return 0;
} }
...@@ -66,10 +66,13 @@ static int amr_write_trailer(AVFormatContext *s) ...@@ -66,10 +66,13 @@ static int amr_write_trailer(AVFormatContext *s)
static int amr_probe(AVProbeData *p) static int amr_probe(AVProbeData *p)
{ {
/* check file header */ //Only check for "#!AMR" which could be amr-wb, amr-nb.
if (p->buf_size < 6) //This will also trigger multichannel files: "#!AMR_MC1.0\n" and
//"#!AMR-WB_MC1.0\n" (not supported)
if (p->buf_size < 5)
return 0; return 0;
if(memcmp(p->buf,AMR_header,6)==0) if(memcmp(p->buf,AMR_header,5)==0)
return AVPROBE_SCORE_MAX; return AVPROBE_SCORE_MAX;
else else
return 0; return 0;
...@@ -81,24 +84,44 @@ static int amr_read_header(AVFormatContext *s, ...@@ -81,24 +84,44 @@ static int amr_read_header(AVFormatContext *s,
{ {
ByteIOContext *pb = &s->pb; ByteIOContext *pb = &s->pb;
AVStream *st; AVStream *st;
uint8_t header[6]; uint8_t header[9];
get_buffer(pb, header, 6); get_buffer(pb, header, 6);
if(memcmp(header,AMR_header,6)!=0) if(memcmp(header,AMR_header,6)!=0)
{
get_buffer(pb, header+6, 3);
if(memcmp(header,AMRWB_header,9)!=0)
{ {
return -1; return -1;
} }
st = av_new_stream(s, 0);
if (!st)
{
return AVERROR_NOMEM;
}
st->codec.codec_type = CODEC_TYPE_AUDIO;
st->codec.codec_tag = CODEC_ID_AMR_WB;
st->codec.codec_id = CODEC_ID_AMR_WB;
st->codec.channels = 1;
st->codec.sample_rate = 16000;
}
else
{
st = av_new_stream(s, 0); st = av_new_stream(s, 0);
if (!st) if (!st)
{
return AVERROR_NOMEM; return AVERROR_NOMEM;
}
st->codec.codec_type = CODEC_TYPE_AUDIO; st->codec.codec_type = CODEC_TYPE_AUDIO;
st->codec.codec_tag = CODEC_ID_AMR_NB; st->codec.codec_tag = CODEC_ID_AMR_NB;
st->codec.codec_id = CODEC_ID_AMR_NB; st->codec.codec_id = CODEC_ID_AMR_NB;
st->codec.channels = 1; st->codec.channels = 1;
st->codec.sample_rate = 8000; st->codec.sample_rate = 8000;
}
return 0; return 0;
} }
...@@ -107,26 +130,30 @@ static int amr_read_header(AVFormatContext *s, ...@@ -107,26 +130,30 @@ static int amr_read_header(AVFormatContext *s,
static int amr_read_packet(AVFormatContext *s, static int amr_read_packet(AVFormatContext *s,
AVPacket *pkt) AVPacket *pkt)
{ {
static uint16_t packed_size[16] = {12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0}; AVCodecContext *enc = &s->streams[0]->codec;
if (enc->codec_id == CODEC_ID_AMR_NB)
{
const static uint8_t packed_size[16] = {12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0};
uint8_t toc, q, ft; uint8_t toc, q, ft;
int read; int read;
int size; int size;
if (url_feof(&s->pb)) if (url_feof(&s->pb))
{
return -EIO; return -EIO;
}
toc=0;
toc=get_byte(&s->pb); toc=get_byte(&s->pb);
q = (toc >> 2) & 0x01; q = (toc >> 2) & 0x01;
ft = (toc >> 3) & 0x0F; ft = (toc >> 3) & 0x0F;
size=packed_size[ft]; size=packed_size[ft];
//printf("amr_read_packet size=%d\n",size);
if (av_new_packet(pkt, size+1)) if (av_new_packet(pkt, size+1))
{
return -EIO; return -EIO;
}
pkt->stream_index = 0; pkt->stream_index = 0;
pkt->data[0]=toc; pkt->data[0]=toc;
...@@ -140,6 +167,45 @@ static int amr_read_packet(AVFormatContext *s, ...@@ -140,6 +167,45 @@ static int amr_read_packet(AVFormatContext *s,
} }
return 0; return 0;
}
else if(enc->codec_id == CODEC_ID_AMR_WB)
{
static uint8_t packed_size[16] = {18, 24, 33, 37, 41, 47, 51, 59, 61, 6, 6, 0, 0, 0, 1, 1};
uint8_t toc, mode;
int read;
int size;
if (url_feof(&s->pb))
{
return -EIO;
}
toc=get_byte(&s->pb);
mode = (uint8_t)((toc >> 3) & 0x0F);
size = packed_size[mode];
if ( (size==0) || av_new_packet(pkt, size))
{
return -EIO;
}
pkt->stream_index = 0;
pkt->data[0]=toc;
read = get_buffer(&s->pb, pkt->data+1, size-1);
if (read != (size-1))
{
av_free_packet(pkt);
return -EIO;
}
return 0;
}
else
{
return -EIO;
}
} }
static int amr_read_close(AVFormatContext *s) static int amr_read_close(AVFormatContext *s)
...@@ -150,7 +216,7 @@ static int amr_read_close(AVFormatContext *s) ...@@ -150,7 +216,7 @@ static int amr_read_close(AVFormatContext *s)
static AVInputFormat amr_iformat = { static AVInputFormat amr_iformat = {
"amr", "amr",
"3gpp amr file format", "3gpp amr file format",
0, 0, /*priv_data_size*/
amr_probe, amr_probe,
amr_read_header, amr_read_header,
amr_read_packet, amr_read_packet,
......
...@@ -121,6 +121,7 @@ static const CodecTag mov_audio_tags[] = { ...@@ -121,6 +121,7 @@ static const CodecTag mov_audio_tags[] = {
{ CODEC_ID_AAC, MKTAG('m', 'p', '4', 'a') }, /* MPEG 4 AAC or audio ? */ { CODEC_ID_AAC, MKTAG('m', 'p', '4', 'a') }, /* MPEG 4 AAC or audio ? */
/* The standard for mpeg4 audio is still not normalised AFAIK anyway */ /* The standard for mpeg4 audio is still not normalised AFAIK anyway */
{ CODEC_ID_AMR_NB, MKTAG('s', 'a', 'm', 'r') }, /* AMR-NB 3gp */ { CODEC_ID_AMR_NB, MKTAG('s', 'a', 'm', 'r') }, /* AMR-NB 3gp */
{ CODEC_ID_AMR_WB, MKTAG('s', 'a', 'w', 'b') }, /* AMR-WB 3gp */
{ CODEC_ID_NONE, 0 }, { CODEC_ID_NONE, 0 },
}; };
...@@ -850,10 +851,10 @@ static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) ...@@ -850,10 +851,10 @@ static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
#endif #endif
} else { } else {
st->codec.codec_id = codec_get_id(mov_audio_tags, format); st->codec.codec_id = codec_get_id(mov_audio_tags, format);
if(st->codec.codec_id==CODEC_ID_AMR_NB) //from TS26.244 if(st->codec.codec_id==CODEC_ID_AMR_NB || st->codec.codec_id==CODEC_ID_AMR_WB) //from TS26.244
{ {
#ifdef DEBUG #ifdef DEBUG
printf("AMR-NB audio identified!!\n"); printf("AMR-NB or AMR-WB audio identified!!\n");
#endif #endif
get_be32(pb);get_be32(pb); //Reserved_8 get_be32(pb);get_be32(pb); //Reserved_8
get_be16(pb);//Reserved_2 get_be16(pb);//Reserved_2
...@@ -864,40 +865,25 @@ static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) ...@@ -864,40 +865,25 @@ static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
//AMRSpecificBox.(10 bytes) //AMRSpecificBox.(10 bytes)
#ifdef DEBUG
int damr_size=
#endif
get_be32(pb); //size get_be32(pb); //size
#ifdef DEBUG
int damr_type=
#endif
get_be32(pb); //type=='damr' get_be32(pb); //type=='damr'
#ifdef DEBUG
int damr_vendor=
#endif
get_be32(pb); //vendor get_be32(pb); //vendor
get_byte(pb); //decoder version get_byte(pb); //decoder version
get_be16(pb); //mode_set get_be16(pb); //mode_set
get_byte(pb); //mode_change_period get_byte(pb); //mode_change_period
get_byte(pb); //frames_per_sample get_byte(pb); //frames_per_sample
#ifdef DEBUG
printf("Audio: damr_type=%c%c%c%c damr_size=%d damr_vendor=%c%c%c%c\n",
(damr_type >> 24) & 0xff,
(damr_type >> 16) & 0xff,
(damr_type >> 8) & 0xff,
(damr_type >> 0) & 0xff,
damr_size,
(damr_vendor >> 24) & 0xff,
(damr_vendor >> 16) & 0xff,
(damr_vendor >> 8) & 0xff,
(damr_vendor >> 0) & 0xff
);
#endif
st->duration = AV_NOPTS_VALUE;//Not possible to get from this info, must count number of AMR frames st->duration = AV_NOPTS_VALUE;//Not possible to get from this info, must count number of AMR frames
if(st->codec.codec_id==CODEC_ID_AMR_NB)
{
st->codec.sample_rate=8000; st->codec.sample_rate=8000;
st->codec.channels=1; st->codec.channels=1;
}
else //AMR-WB
{
st->codec.sample_rate=16000;
st->codec.channels=1;
}
st->codec.bits_per_sample=16; st->codec.bits_per_sample=16;
st->codec.bit_rate=0; /*It is not possible to tell this before we have st->codec.bit_rate=0; /*It is not possible to tell this before we have
an audio frame and even then every frame can be different*/ an audio frame and even then every frame can be different*/
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment