diff options
author | Carl Eugen Hoyos <cehoyos@ag.or.at> | 2011-08-01 00:30:56 +0200 |
---|---|---|
committer | Carl Eugen Hoyos <cehoyos@ag.or.at> | 2011-08-01 00:58:49 +0200 |
commit | 9b60b076fb9ab5b39997f3969ac769c03d6abeaf (patch) | |
tree | 707df0eb7d1cece3a88f342ecad5f955e41cffd6 | |
parent | c6e0332f3062efb00a8c577e11aee70821874b2e (diff) | |
download | ffmpeg-9b60b076fb9ab5b39997f3969ac769c03d6abeaf.tar.gz |
Support muxing MP1, MP2 and MP3 in caf.
-rw-r--r-- | libavformat/cafenc.c | 46 |
1 files changed, 43 insertions, 3 deletions
diff --git a/libavformat/cafenc.c b/libavformat/cafenc.c index 29b1d56a9d..1c77251604 100644 --- a/libavformat/cafenc.c +++ b/libavformat/cafenc.c @@ -28,6 +28,10 @@ typedef struct { int64_t data; + uint8_t *pkt_sizes; + int size_buffer_size; + int size_entries_used; + int packets; } CAFContext; static uint32_t codec_flags(enum CodecID codec_id) { @@ -133,9 +137,9 @@ static int caf_write_header(AVFormatContext *s) return AVERROR_INVALIDDATA; } - if (!enc->block_align) { - av_log(s, AV_LOG_ERROR, "muxing with unknown or variable packet size not yet supported\n"); - return AVERROR_PATCHWELCOME; + if (!enc->block_align && !pb->seekable) { + av_log(s, AV_LOG_ERROR, "Muxing variable packet size not supported on non seekable output\n"); + return AVERROR_INVALIDDATA; } ffio_wfourcc(pb, "caff"); //< mFileType @@ -169,13 +173,38 @@ static int caf_write_header(AVFormatContext *s) static int caf_write_packet(AVFormatContext *s, AVPacket *pkt) { + CAFContext *caf = s->priv_data; + avio_write(s->pb, pkt->data, pkt->size); + if (!s->streams[0]->codec->block_align) { + void *pkt_sizes = caf->pkt_sizes; + int i, alloc_size = caf->size_entries_used + 5; + if (alloc_size < 0) { + caf->pkt_sizes = NULL; + } else { + caf->pkt_sizes = av_fast_realloc(caf->pkt_sizes, + &caf->size_buffer_size, + alloc_size); + } + if (!caf->pkt_sizes) { + av_free(pkt_sizes); + return AVERROR(ENOMEM); + } + for (i = 4; i > 0; i--) { + unsigned top = pkt->size >> i * 7; + if (top) + caf->pkt_sizes[caf->size_entries_used++] = 128 | top; + } + caf->pkt_sizes[caf->size_entries_used++] = pkt->size & 127; + caf->packets++; + } return 0; } static int caf_write_trailer(AVFormatContext *s) { AVIOContext *pb = s->pb; + AVCodecContext *enc = s->streams[0]->codec; if (pb->seekable) { CAFContext *caf = s->priv_data; @@ -184,6 +213,17 @@ static int caf_write_trailer(AVFormatContext *s) avio_seek(pb, caf->data, SEEK_SET); avio_wb64(pb, file_size - caf->data - 8); avio_seek(pb, file_size, SEEK_SET); + if (!enc->block_align) { + ffio_wfourcc(pb, "pakt"); + avio_wb64(pb, caf->size_entries_used + 24); + avio_wb64(pb, caf->packets); ///< mNumberPackets + avio_wb64(pb, caf->packets * samples_per_packet(enc->codec_id, enc->channels)); ///< mNumberValidFrames + avio_wb32(pb, 0); ///< mPrimingFrames + avio_wb32(pb, 0); ///< mRemainderFrames + avio_write(pb, caf->pkt_sizes, caf->size_entries_used); + av_freep(&caf->pkt_sizes); + caf->size_buffer_size = 0; + } avio_flush(pb); } return 0; |