Libav
|
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 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 ByteIOContext *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 put_tag(pb, AMR_header); /* magic number */ 00044 } 00045 else if(enc->codec_id == CODEC_ID_AMR_WB) 00046 { 00047 put_tag(pb, AMRWB_header); /* magic number */ 00048 } 00049 else 00050 { 00051 return -1; 00052 } 00053 put_flush_packet(pb); 00054 return 0; 00055 } 00056 00057 static int amr_write_packet(AVFormatContext *s, AVPacket *pkt) 00058 { 00059 put_buffer(s->pb, pkt->data, pkt->size); 00060 put_flush_packet(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 ByteIOContext *pb = s->pb; 00082 AVStream *st; 00083 uint8_t header[9]; 00084 00085 get_buffer(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 get_buffer(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 } 00104 else 00105 { 00106 st->codec->codec_tag = MKTAG('s', 'a', 'm', 'r'); 00107 st->codec->codec_id = CODEC_ID_AMR_NB; 00108 st->codec->sample_rate = 8000; 00109 } 00110 st->codec->channels = 1; 00111 st->codec->codec_type = AVMEDIA_TYPE_AUDIO; 00112 av_set_pts_info(st, 64, 1, st->codec->sample_rate); 00113 00114 return 0; 00115 } 00116 00117 static int amr_read_packet(AVFormatContext *s, 00118 AVPacket *pkt) 00119 { 00120 AVCodecContext *enc = s->streams[0]->codec; 00121 int read, size = 0, toc, mode; 00122 00123 if (url_feof(s->pb)) 00124 { 00125 return AVERROR(EIO); 00126 } 00127 00128 //FIXME this is wrong, this should rather be in a AVParset 00129 toc=get_byte(s->pb); 00130 mode = (toc >> 3) & 0x0F; 00131 00132 if (enc->codec_id == CODEC_ID_AMR_NB) 00133 { 00134 static const uint8_t packed_size[16] = {12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0}; 00135 00136 size=packed_size[mode]+1; 00137 } 00138 else if(enc->codec_id == CODEC_ID_AMR_WB) 00139 { 00140 static uint8_t packed_size[16] = {18, 24, 33, 37, 41, 47, 51, 59, 61, 6, 6, 0, 0, 0, 1, 1}; 00141 00142 size=packed_size[mode]; 00143 } 00144 else 00145 { 00146 assert(0); 00147 } 00148 00149 if ( (size==0) || av_new_packet(pkt, size)) 00150 { 00151 return AVERROR(EIO); 00152 } 00153 00154 pkt->stream_index = 0; 00155 pkt->pos= url_ftell(s->pb); 00156 pkt->data[0]=toc; 00157 pkt->duration= enc->codec_id == CODEC_ID_AMR_NB ? 160 : 320; 00158 read = get_buffer(s->pb, pkt->data+1, size-1); 00159 00160 if (read != size-1) 00161 { 00162 av_free_packet(pkt); 00163 return AVERROR(EIO); 00164 } 00165 00166 return 0; 00167 } 00168 00169 #if CONFIG_AMR_DEMUXER 00170 AVInputFormat amr_demuxer = { 00171 "amr", 00172 NULL_IF_CONFIG_SMALL("3GPP AMR file format"), 00173 0, /*priv_data_size*/ 00174 amr_probe, 00175 amr_read_header, 00176 amr_read_packet, 00177 NULL, 00178 }; 00179 #endif 00180 00181 #if CONFIG_AMR_MUXER 00182 AVOutputFormat amr_muxer = { 00183 "amr", 00184 NULL_IF_CONFIG_SMALL("3GPP AMR file format"), 00185 "audio/amr", 00186 "amr", 00187 0, 00188 CODEC_ID_AMR_NB, 00189 CODEC_ID_NONE, 00190 amr_write_header, 00191 amr_write_packet, 00192 }; 00193 #endif