libavformat/ivfenc.c
326851b9
 /*
  * Copyright (c) 2010 Reimar Döffinger
  *
  * This file is part of FFmpeg.
  *
  * FFmpeg is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  *
  * FFmpeg is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with FFmpeg; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 #include "avformat.h"
2e6636aa
 #include "internal.h"
326851b9
 #include "libavutil/intreadwrite.h"
 
3a18d3fa
 typedef struct IVFEncContext {
     unsigned frame_cnt;
     uint64_t last_pts, sum_delta_pts;
 } IVFEncContext;
 
326851b9
 static int ivf_write_header(AVFormatContext *s)
 {
9200514a
     AVCodecParameters *par;
ae628ec1
     AVIOContext *pb = s->pb;
326851b9
 
     if (s->nb_streams != 1) {
         av_log(s, AV_LOG_ERROR, "Format supports only exactly one video stream\n");
         return AVERROR(EINVAL);
     }
9200514a
     par = s->streams[0]->codecpar;
6f69f7a8
     if (par->codec_type != AVMEDIA_TYPE_VIDEO ||
         !(par->codec_id == AV_CODEC_ID_VP8 || par->codec_id == AV_CODEC_ID_VP9)) {
dea377fc
         av_log(s, AV_LOG_ERROR, "Currently only VP8 and VP9 are supported!\n");
326851b9
         return AVERROR(EINVAL);
     }
77eb5504
     avio_write(pb, "DKIF", 4);
     avio_wl16(pb, 0); // version
     avio_wl16(pb, 32); // header length
6f69f7a8
     avio_wl32(pb, par->codec_tag ? par->codec_tag : par->codec_id == AV_CODEC_ID_VP9 ? AV_RL32("VP90") : AV_RL32("VP80"));
9200514a
     avio_wl16(pb, par->width);
     avio_wl16(pb, par->height);
77eb5504
     avio_wl32(pb, s->streams[0]->time_base.den);
     avio_wl32(pb, s->streams[0]->time_base.num);
3a18d3fa
     avio_wl64(pb, 0xFFFFFFFFFFFFFFFFULL);
326851b9
 
     return 0;
 }
 
 static int ivf_write_packet(AVFormatContext *s, AVPacket *pkt)
 {
ae628ec1
     AVIOContext *pb = s->pb;
3a18d3fa
     IVFEncContext *ctx = s->priv_data;
 
77eb5504
     avio_wl32(pb, pkt->size);
     avio_wl64(pb, pkt->pts);
     avio_write(pb, pkt->data, pkt->size);
3a18d3fa
     if (ctx->frame_cnt)
         ctx->sum_delta_pts += pkt->pts - ctx->last_pts;
     ctx->frame_cnt++;
     ctx->last_pts = pkt->pts;
 
     return 0;
 }
 
 static int ivf_write_trailer(AVFormatContext *s)
 {
     AVIOContext *pb = s->pb;
5c8467a0
     IVFEncContext *ctx = s->priv_data;
 
4de591e6
     if ((pb->seekable & AVIO_SEEKABLE_NORMAL) && ctx->frame_cnt > 1) {
3a18d3fa
         size_t end = avio_tell(pb);
 
         avio_seek(pb, 24, SEEK_SET);
         avio_wl64(pb, ctx->frame_cnt * ctx->sum_delta_pts / (ctx->frame_cnt - 1));
         avio_seek(pb, end, SEEK_SET);
     }
326851b9
 
     return 0;
 }
 
2e6636aa
 static int ivf_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt)
 {
     int ret = 1;
     AVStream *st = s->streams[pkt->stream_index];
 
6f69f7a8
     if (st->codecpar->codec_id == AV_CODEC_ID_VP9)
2e6636aa
         ret = ff_stream_add_bitstream_filter(st, "vp9_superframe", NULL);
 
     return ret;
 }
 
09317e3e
 static const AVCodecTag codec_ivf_tags[] = {
     { AV_CODEC_ID_VP8,  MKTAG('V', 'P', '8', '0') },
     { AV_CODEC_ID_VP9,  MKTAG('V', 'P', '9', '0') },
     { AV_CODEC_ID_NONE, 0 }
 };
 
c6610a21
 AVOutputFormat ff_ivf_muxer = {
3a18d3fa
     .priv_data_size = sizeof(IVFEncContext),
20234a4b
     .name         = "ivf",
     .long_name    = NULL_IF_CONFIG_SMALL("On2 IVF"),
     .extensions   = "ivf",
36ef5369
     .audio_codec  = AV_CODEC_ID_NONE,
     .video_codec  = AV_CODEC_ID_VP8,
326851b9
     .write_header = ivf_write_header,
     .write_packet = ivf_write_packet,
3a18d3fa
     .write_trailer = ivf_write_trailer,
2e6636aa
     .check_bitstream = ivf_check_bitstream,
09317e3e
     .codec_tag    = (const AVCodecTag* const []){ codec_ivf_tags, 0 },
326851b9
 };