Libav 0.7.1
|
00001 /* 00002 * amr file format 00003 * Copyright (c) 2001 ffmpeg project 00004 * 00005 * This file is part of Libav. 00006 * 00007 * Libav 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 * Libav 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 Libav; 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 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); /* magic number */ 00044 } 00045 else if(enc->codec_id == CODEC_ID_AMR_WB) 00046 { 00047 avio_write(pb, AMRWB_header, sizeof(AMRWB_header) - 1); /* magic number */ 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 /* CONFIG_AMR_MUXER */ 00064 00065 static int amr_probe(AVProbeData *p) 00066 { 00067 //Only check for "#!AMR" which could be amr-wb, amr-nb. 00068 //This will also trigger multichannel files: "#!AMR_MC1.0\n" and 00069 //"#!AMR-WB_MC1.0\n" (not supported) 00070 00071 if(memcmp(p->buf,AMR_header,5)==0) 00072 return AVPROBE_SCORE_MAX; 00073 else 00074 return 0; 00075 } 00076 00077 /* amr input */ 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 (s->pb->eof_reached) 00127 { 00128 return AVERROR(EIO); 00129 } 00130 00131 //FIXME this is wrong, this should rather be in a AVParset 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 /* Both AMR formats have 50 frames per second */ 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, /*priv_data_size*/ 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