* qatar/master: (24 commits) flvdec: remove incomplete, disabled seeking code mem: add support for _aligned_malloc() as found on Windows lavc: Extend the documentation for avcodec_init_packet flvdec: remove incomplete, disabled seeking code http: replace atoll() with strtoll() mpegts: remove unused/incomplete/broken seeking code af_amix: allow float planar sample format as input af_amix: use AVFloatDSPContext.vector_fmac_scalar() float_dsp: add x86-optimized functions for vector_fmac_scalar() float_dsp: Move vector_fmac_scalar() from libavcodec to libavutil lavr: Add x86-optimized function for flt to s32 conversion lavr: Add x86-optimized function for flt to s16 conversion lavr: Add x86-optimized functions for s32 to flt conversion lavr: Add x86-optimized functions for s32 to s16 conversion lavr: Add x86-optimized functions for s16 to flt conversion lavr: Add x86-optimized function for s16 to s32 conversion rtpenc: Support packetizing iLBC rtpdec: Add a depacketizer for iLBC Implement the iLBC storage file format mov: Support muxing/demuxing iLBC ... Conflicts: Changelog configure libavcodec/avcodec.h libavcodec/dsputil.c libavcodec/version.h libavformat/movenc.c libavformat/mpegts.c libavformat/version.h libavutil/mem.c
Showing the changes to libavformat/ilbc.c (1 of 44 files). Show all
Unified · Split
| @@ -0,0 +1,141 @@ | ||
| 1 | +/* | |
| 2 | + * iLBC storage file format | |
| 3 | + * Copyright (c) 2012 Martin Storsjo | |
| 4 | + * | |
| 5 | + * This file is part of FFmpeg. | |
| 6 | + * | |
| 7 | + * FFmpeg is free software; you can redistribute it and/or | |
| 8 | + * modify it under the terms of the GNU Lesser General Public | |
| 9 | + * License as published by the Free Software Foundation; either | |
| 10 | + * version 2.1 of the License, or (at your option) any later version. | |
| 11 | + * | |
| 12 | + * FFmpeg is distributed in the hope that it will be useful, | |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 15 | + * Lesser General Public License for more details. | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU Lesser General Public | |
| 18 | + * License along with FFmpeg; if not, write to the Free Software | |
| 19 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
| 20 | + */ | |
| 21 | + | |
| 22 | +#include "avformat.h" | |
| 23 | +#include "internal.h" | |
| 24 | + | |
| 25 | +static const char mode20_header[] = "#!iLBC20\n"; | |
| 26 | +static const char mode30_header[] = "#!iLBC30\n"; | |
| 27 | + | |
| 28 | +static int ilbc_write_header(AVFormatContext *s) | |
| 29 | +{ | |
| 30 | + AVIOContext *pb = s->pb; | |
| 31 | + AVCodecContext *enc; | |
| 32 | + | |
| 33 | + if (s->nb_streams != 1) { | |
| 34 | + av_log(s, AV_LOG_ERROR, "Unsupported number of streams\n"); | |
| 35 | + return AVERROR(EINVAL); | |
| 36 | + } | |
| 37 | + enc = s->streams[0]->codec; | |
| 38 | + | |
| 39 | + if (enc->codec_id != CODEC_ID_ILBC) { | |
| 40 | + av_log(s, AV_LOG_ERROR, "Unsupported codec\n"); | |
| 41 | + return AVERROR(EINVAL); | |
| 42 | + } | |
| 43 | + | |
| 44 | + if (enc->block_align == 50) { | |
| 45 | + avio_write(pb, mode30_header, sizeof(mode30_header) - 1); | |
| 46 | + } else if (enc->block_align == 38) { | |
| 47 | + avio_write(pb, mode20_header, sizeof(mode20_header) - 1); | |
| 48 | + } else { | |
| 49 | + av_log(s, AV_LOG_ERROR, "Unsupported mode\n"); | |
| 50 | + return AVERROR(EINVAL); | |
| 51 | + } | |
| 52 | + avio_flush(pb); | |
| 53 | + return 0; | |
| 54 | +} | |
| 55 | + | |
| 56 | +static int ilbc_write_packet(AVFormatContext *s, AVPacket *pkt) | |
| 57 | +{ | |
| 58 | + avio_write(s->pb, pkt->data, pkt->size); | |
| 59 | + avio_flush(s->pb); | |
| 60 | + return 0; | |
| 61 | +} | |
| 62 | + | |
| 63 | +static int ilbc_probe(AVProbeData *p) | |
| 64 | +{ | |
| 65 | + // Only check for "#!iLBC" which matches both formats | |
| 66 | + if (!memcmp(p->buf, mode20_header, 6)) | |
| 67 | + return AVPROBE_SCORE_MAX; | |
| 68 | + else | |
| 69 | + return 0; | |
| 70 | +} | |
| 71 | + | |
| 72 | +static int ilbc_read_header(AVFormatContext *s) | |
| 73 | +{ | |
| 74 | + AVIOContext *pb = s->pb; | |
| 75 | + AVStream *st; | |
| 76 | + uint8_t header[9]; | |
| 77 | + | |
| 78 | + avio_read(pb, header, 9); | |
| 79 | + | |
| 80 | + st = avformat_new_stream(s, NULL); | |
| 81 | + if (!st) | |
| 82 | + return AVERROR(ENOMEM); | |
| 83 | + st->codec->codec_id = CODEC_ID_ILBC; | |
| 84 | + st->codec->sample_rate = 8000; | |
| 85 | + st->codec->channels = 1; | |
| 86 | + st->codec->codec_type = AVMEDIA_TYPE_AUDIO; | |
| 87 | + st->start_time = 0; | |
| 88 | + avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); | |
| 89 | + if (!memcmp(header, mode20_header, sizeof(mode20_header) - 1)) { | |
| 90 | + st->codec->block_align = 38; | |
| 91 | + st->codec->bit_rate = 15200; | |
| 92 | + } else if (!memcmp(header, mode30_header, sizeof(mode30_header) - 1)) { | |
| 93 | + st->codec->block_align = 50; | |
| 94 | + st->codec->bit_rate = 13333; | |
| 95 | + } else { | |
| 96 | + av_log(s, AV_LOG_ERROR, "Unrecognized iLBC file header\n"); | |
| 97 | + return AVERROR_INVALIDDATA; | |
| 98 | + } | |
| 99 | + | |
| 100 | + return 0; | |
| 101 | +} | |
| 102 | + | |
| 103 | +static int ilbc_read_packet(AVFormatContext *s, | |
| 104 | + AVPacket *pkt) | |
| 105 | +{ | |
| 106 | + AVCodecContext *enc = s->streams[0]->codec; | |
| 107 | + int ret; | |
| 108 | + | |
| 109 | + if ((ret = av_new_packet(pkt, enc->block_align)) < 0) | |
| 110 | + return ret; | |
| 111 | + | |
| 112 | + pkt->stream_index = 0; | |
| 113 | + pkt->pos = avio_tell(s->pb); | |
| 114 | + pkt->duration = enc->block_align == 38 ? 160 : 240; | |
| 115 | + if ((ret = avio_read(s->pb, pkt->data, enc->block_align)) != enc->block_align) { | |
| 116 | + av_free_packet(pkt); | |
| 117 | + return ret < 0 ? ret : AVERROR(EIO); | |
| 118 | + } | |
| 119 | + | |
| 120 | + return 0; | |
| 121 | +} | |
| 122 | + | |
| 123 | +AVInputFormat ff_ilbc_demuxer = { | |
| 124 | + .name = "ilbc", | |
| 125 | + .long_name = NULL_IF_CONFIG_SMALL("iLBC storage file format"), | |
| 126 | + .read_probe = ilbc_probe, | |
| 127 | + .read_header = ilbc_read_header, | |
| 128 | + .read_packet = ilbc_read_packet, | |
| 129 | + .flags = AVFMT_GENERIC_INDEX, | |
| 130 | +}; | |
| 131 | + | |
| 132 | +AVOutputFormat ff_ilbc_muxer = { | |
| 133 | + .name = "ilbc", | |
| 134 | + .long_name = NULL_IF_CONFIG_SMALL("iLBC storage file format"), | |
| 135 | + .mime_type = "audio/iLBC", | |
| 136 | + .extensions = "lbc", | |
| 137 | + .audio_codec = CODEC_ID_ILBC, | |
| 138 | + .write_header = ilbc_write_header, | |
| 139 | + .write_packet = ilbc_write_packet, | |
| 140 | + .flags = AVFMT_NOTIMESTAMPS, | |
| 141 | +}; | |