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