[FFmpeg-devel] [PATCH] WebM mux/demux

David Conrad lessen42
Wed May 19 21:14:19 CEST 2010


On May 19, 2010, at 2:51 PM, James Zern wrote:

> Related thread: '[PATCH] VP8 de/encode via libvpx'
> VP8 and associated WebM container made public today [1].
> 
> The attached adds WebM de/muxing to matroska.
> For both some extra ifdef's/checks were added to only allow VP8/vorbis
> as that is the current supported configuration in web browsers. If
> these are too busy in this respect they be cleaned up.

Yes, the only #ifdef should be around the AVOutputFormat.

> +    if (!strcmp("webm", s->oformat->name)) {
> +        mkv->max_cluster_size = 500*1024*1024;   // 500 MB
> +        mkv->max_cluster_pts = 30000;            // 30 seconds
> +    } else {

Why? Seeking can only seek to a cluster, then do a linear scan to find the needed packet, and 500 MB makes that incredibly inefficient.

> +static int mkv_copy_packet(MatroskaMuxContext *mkv, const AVPacket *pkt)
> +{
> +    uint8_t *data = mkv->cur_audio_pkt.data;
> +    mkv->cur_audio_pkt = *pkt;
> +    mkv->cur_audio_pkt.data = av_fast_realloc(data, &mkv->audio_buffer_size, pkt->size);
> +    if (mkv->cur_audio_pkt.data == NULL)
> +        return AVERROR(ENOMEM);
> +
> +    memcpy(mkv->cur_audio_pkt.data, pkt->data, pkt->size);
> +    mkv->cur_audio_pkt.size = pkt->size;
> +    return 0;
> +}

> +
> +static int mkv_write_packet2(AVFormatContext *s, AVPacket *pkt)
> +{

webm and mkv shouldn't use separate write_packets, the interleaving changes should be done for mkv too. Maybe call the current mkv_write_packet mkv_write_packet_internal and move all cluster handling to the outer one.

> +    MatroskaMuxContext *mkv = s->priv_data;
> +    ByteIOContext *pb = s->pb;
> +    AVCodecContext *codec = s->streams[pkt->stream_index]->codec;
> +    int keyframe = !!(pkt->flags & PKT_FLAG_KEY);
> +    int ret = 0;
> +
> +    if (codec->codec_type == AVMEDIA_TYPE_VIDEO && keyframe && mkv->cluster_pos) {
> +        // Start a new cluster when we get a key frame
> +        int64_t ts = mkv->tracks[pkt->stream_index].write_dts ? pkt->dts : pkt->pts;
>  
> +        av_log(s, AV_LOG_DEBUG, "Starting new cluster at offset %" PRIu64
> +          " bytes, pts %" PRIu64 "\n", url_ftell(pb), ts);
> +
> +        end_ebml_master(pb, mkv->cluster);
> +        mkv->cluster_pos = 0;
> +        if (mkv->dyn_bc)
> +            mkv_flush_dynbuf(s);
> +    }

There should be a minimum cluster size in addition to starting on keyframes.



More information about the ffmpeg-devel mailing list