00001 /* 00002 * amr file format 00003 * Copyright (c) 2001 ffmpeg project 00004 * 00005 * This file is part of FFmpeg. 00006 * 00007 * FFmpeg is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * FFmpeg is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with FFmpeg; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00022 /* 00023 Write and read amr data according to RFC3267, http://www.ietf.org/rfc/rfc3267.txt?number=3267 00024 00025 Only mono files are supported. 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); /* magic number */ 00045 } 00046 else if(enc->codec_id == CODEC_ID_AMR_WB) 00047 { 00048 avio_write(pb, AMRWB_header, sizeof(AMRWB_header) - 1); /* magic number */ 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 /* CONFIG_AMR_MUXER */ 00065 00066 static int amr_probe(AVProbeData *p) 00067 { 00068 //Only check for "#!AMR" which could be amr-wb, amr-nb. 00069 //This will also trigger multichannel files: "#!AMR_MC1.0\n" and 00070 //"#!AMR-WB_MC1.0\n" (not supported) 00071 00072 if(memcmp(p->buf,AMR_header,5)==0) 00073 return AVPROBE_SCORE_MAX; 00074 else 00075 return 0; 00076 } 00077 00078 /* amr input */ 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 //FIXME this is wrong, this should rather be in a AVParset 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 /* Both AMR formats have 50 frames per second */ 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