00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "avformat.h"
00029
00030 static const char AMR_header [] = "#!AMR\n";
00031 static const char AMRWB_header [] = "#!AMR-WB\n";
00032
00033 #if CONFIG_AMR_MUXER
00034 static int amr_write_header(AVFormatContext *s)
00035 {
00036 AVIOContext *pb = s->pb;
00037 AVCodecContext *enc = s->streams[0]->codec;
00038
00039 s->priv_data = NULL;
00040
00041 if (enc->codec_id == CODEC_ID_AMR_NB)
00042 {
00043 avio_write(pb, AMR_header, sizeof(AMR_header) - 1);
00044 }
00045 else if(enc->codec_id == CODEC_ID_AMR_WB)
00046 {
00047 avio_write(pb, AMRWB_header, sizeof(AMRWB_header) - 1);
00048 }
00049 else
00050 {
00051 return -1;
00052 }
00053 avio_flush(pb);
00054 return 0;
00055 }
00056
00057 static int amr_write_packet(AVFormatContext *s, AVPacket *pkt)
00058 {
00059 avio_write(s->pb, pkt->data, pkt->size);
00060 avio_flush(s->pb);
00061 return 0;
00062 }
00063 #endif
00064
00065 static int amr_probe(AVProbeData *p)
00066 {
00067
00068
00069
00070
00071 if(memcmp(p->buf,AMR_header,5)==0)
00072 return AVPROBE_SCORE_MAX;
00073 else
00074 return 0;
00075 }
00076
00077
00078 static int amr_read_header(AVFormatContext *s,
00079 AVFormatParameters *ap)
00080 {
00081 AVIOContext *pb = s->pb;
00082 AVStream *st;
00083 uint8_t header[9];
00084
00085 avio_read(pb, header, 6);
00086
00087 st = av_new_stream(s, 0);
00088 if (!st)
00089 {
00090 return AVERROR(ENOMEM);
00091 }
00092 if(memcmp(header,AMR_header,6)!=0)
00093 {
00094 avio_read(pb, header+6, 3);
00095 if(memcmp(header,AMRWB_header,9)!=0)
00096 {
00097 return -1;
00098 }
00099
00100 st->codec->codec_tag = MKTAG('s', 'a', 'w', 'b');
00101 st->codec->codec_id = CODEC_ID_AMR_WB;
00102 st->codec->sample_rate = 16000;
00103 st->codec->frame_size = 320;
00104 }
00105 else
00106 {
00107 st->codec->codec_tag = MKTAG('s', 'a', 'm', 'r');
00108 st->codec->codec_id = CODEC_ID_AMR_NB;
00109 st->codec->sample_rate = 8000;
00110 st->codec->frame_size = 160;
00111 }
00112 st->codec->channels = 1;
00113 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00114 av_set_pts_info(st, 64, 1, st->codec->sample_rate);
00115
00116 return 0;
00117 }
00118
00119 static int amr_read_packet(AVFormatContext *s,
00120 AVPacket *pkt)
00121 {
00122 AVCodecContext *enc = s->streams[0]->codec;
00123 int read, size = 0, toc, mode;
00124 int64_t pos = avio_tell(s->pb);
00125
00126 if (url_feof(s->pb))
00127 {
00128 return AVERROR(EIO);
00129 }
00130
00131
00132 toc=avio_r8(s->pb);
00133 mode = (toc >> 3) & 0x0F;
00134
00135 if (enc->codec_id == CODEC_ID_AMR_NB)
00136 {
00137 static const uint8_t packed_size[16] = {12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0};
00138
00139 size=packed_size[mode]+1;
00140 }
00141 else if(enc->codec_id == CODEC_ID_AMR_WB)
00142 {
00143 static uint8_t packed_size[16] = {18, 24, 33, 37, 41, 47, 51, 59, 61, 6, 6, 0, 0, 0, 1, 1};
00144
00145 size=packed_size[mode];
00146 }
00147 else
00148 {
00149 assert(0);
00150 }
00151
00152 if ( (size==0) || av_new_packet(pkt, size))
00153 {
00154 return AVERROR(EIO);
00155 }
00156
00157
00158 s->streams[0]->codec->bit_rate = size*8*50;
00159
00160 pkt->stream_index = 0;
00161 pkt->pos = pos;
00162 pkt->data[0]=toc;
00163 pkt->duration= enc->codec_id == CODEC_ID_AMR_NB ? 160 : 320;
00164 read = avio_read(s->pb, pkt->data+1, size-1);
00165
00166 if (read != size-1)
00167 {
00168 av_free_packet(pkt);
00169 return AVERROR(EIO);
00170 }
00171
00172 return 0;
00173 }
00174
00175 #if CONFIG_AMR_DEMUXER
00176 AVInputFormat ff_amr_demuxer = {
00177 "amr",
00178 NULL_IF_CONFIG_SMALL("3GPP AMR file format"),
00179 0,
00180 amr_probe,
00181 amr_read_header,
00182 amr_read_packet,
00183 NULL,
00184 .flags = AVFMT_GENERIC_INDEX,
00185 };
00186 #endif
00187
00188 #if CONFIG_AMR_MUXER
00189 AVOutputFormat ff_amr_muxer = {
00190 "amr",
00191 NULL_IF_CONFIG_SMALL("3GPP AMR file format"),
00192 "audio/amr",
00193 "amr",
00194 0,
00195 CODEC_ID_AMR_NB,
00196 CODEC_ID_NONE,
00197 amr_write_header,
00198 amr_write_packet,
00199 };
00200 #endif