00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "avformat.h"
00023 #include "internal.h"
00024
00025 static const char mode20_header[] = "#!iLBC20\n";
00026 static const char mode30_header[] = "#!iLBC30\n";
00027
00028 static int ilbc_write_header(AVFormatContext *s)
00029 {
00030 AVIOContext *pb = s->pb;
00031 AVCodecContext *enc;
00032
00033 if (s->nb_streams != 1) {
00034 av_log(s, AV_LOG_ERROR, "Unsupported number of streams\n");
00035 return AVERROR(EINVAL);
00036 }
00037 enc = s->streams[0]->codec;
00038
00039 if (enc->codec_id != AV_CODEC_ID_ILBC) {
00040 av_log(s, AV_LOG_ERROR, "Unsupported codec\n");
00041 return AVERROR(EINVAL);
00042 }
00043
00044 if (enc->block_align == 50) {
00045 avio_write(pb, mode30_header, sizeof(mode30_header) - 1);
00046 } else if (enc->block_align == 38) {
00047 avio_write(pb, mode20_header, sizeof(mode20_header) - 1);
00048 } else {
00049 av_log(s, AV_LOG_ERROR, "Unsupported mode\n");
00050 return AVERROR(EINVAL);
00051 }
00052 avio_flush(pb);
00053 return 0;
00054 }
00055
00056 static int ilbc_write_packet(AVFormatContext *s, AVPacket *pkt)
00057 {
00058 avio_write(s->pb, pkt->data, pkt->size);
00059 avio_flush(s->pb);
00060 return 0;
00061 }
00062
00063 static int ilbc_probe(AVProbeData *p)
00064 {
00065
00066 if (!memcmp(p->buf, mode20_header, 6))
00067 return AVPROBE_SCORE_MAX;
00068 else
00069 return 0;
00070 }
00071
00072 static int ilbc_read_header(AVFormatContext *s)
00073 {
00074 AVIOContext *pb = s->pb;
00075 AVStream *st;
00076 uint8_t header[9];
00077
00078 avio_read(pb, header, 9);
00079
00080 st = avformat_new_stream(s, NULL);
00081 if (!st)
00082 return AVERROR(ENOMEM);
00083 st->codec->codec_id = AV_CODEC_ID_ILBC;
00084 st->codec->sample_rate = 8000;
00085 st->codec->channels = 1;
00086 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00087 st->start_time = 0;
00088 avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
00089 if (!memcmp(header, mode20_header, sizeof(mode20_header) - 1)) {
00090 st->codec->block_align = 38;
00091 st->codec->bit_rate = 15200;
00092 } else if (!memcmp(header, mode30_header, sizeof(mode30_header) - 1)) {
00093 st->codec->block_align = 50;
00094 st->codec->bit_rate = 13333;
00095 } else {
00096 av_log(s, AV_LOG_ERROR, "Unrecognized iLBC file header\n");
00097 return AVERROR_INVALIDDATA;
00098 }
00099
00100 return 0;
00101 }
00102
00103 static int ilbc_read_packet(AVFormatContext *s,
00104 AVPacket *pkt)
00105 {
00106 AVCodecContext *enc = s->streams[0]->codec;
00107 int ret;
00108
00109 if ((ret = av_new_packet(pkt, enc->block_align)) < 0)
00110 return ret;
00111
00112 pkt->stream_index = 0;
00113 pkt->pos = avio_tell(s->pb);
00114 pkt->duration = enc->block_align == 38 ? 160 : 240;
00115 if ((ret = avio_read(s->pb, pkt->data, enc->block_align)) != enc->block_align) {
00116 av_free_packet(pkt);
00117 return ret < 0 ? ret : AVERROR(EIO);
00118 }
00119
00120 return 0;
00121 }
00122
00123 AVInputFormat ff_ilbc_demuxer = {
00124 .name = "ilbc",
00125 .long_name = NULL_IF_CONFIG_SMALL("iLBC storage"),
00126 .read_probe = ilbc_probe,
00127 .read_header = ilbc_read_header,
00128 .read_packet = ilbc_read_packet,
00129 .flags = AVFMT_GENERIC_INDEX,
00130 };
00131
00132 AVOutputFormat ff_ilbc_muxer = {
00133 .name = "ilbc",
00134 .long_name = NULL_IF_CONFIG_SMALL("iLBC storage"),
00135 .mime_type = "audio/iLBC",
00136 .extensions = "lbc",
00137 .audio_codec = AV_CODEC_ID_ILBC,
00138 .write_header = ilbc_write_header,
00139 .write_packet = ilbc_write_packet,
00140 .flags = AVFMT_NOTIMESTAMPS,
00141 };