diff mbox

[FFmpeg-devel] avformat: add H264 and HEVC support in IVF muxer

Message ID 20180927191842.128159-1-alx.sukhanov@gmail.com
State Superseded
Headers show

Commit Message

alx.sukhanov@gmail.com Sept. 27, 2018, 7:18 p.m. UTC
From: Alex Sukhanov <asukhanov@google.com>

---
 libavformat/ivfenc.c | 37 ++++++++++++++++++++++++++++++++-----
 1 file changed, 32 insertions(+), 5 deletions(-)

Comments

Jan Ekström Sept. 27, 2018, 8:16 p.m. UTC | #1
On Thu, Sep 27, 2018 at 10:18 PM,  <alx.sukhanov@gmail.com> wrote:
> From: Alex Sukhanov <asukhanov@google.com>
>
> ---
>  libavformat/ivfenc.c | 37 ++++++++++++++++++++++++++++++++-----
>  1 file changed, 32 insertions(+), 5 deletions(-)
>
> diff --git a/libavformat/ivfenc.c b/libavformat/ivfenc.c
> index 66441a2a43..9ff7894b88 100644
> --- a/libavformat/ivfenc.c
> +++ b/libavformat/ivfenc.c
> @@ -38,17 +38,31 @@ static int ivf_write_header(AVFormatContext *s)
>      par = s->streams[0]->codecpar;
>      if (par->codec_type != AVMEDIA_TYPE_VIDEO ||
>          !(par->codec_id == AV_CODEC_ID_AV1 ||
> +          par->codec_id == AV_CODEC_ID_H264 ||

Misses HEVC if you're adding support for it as well (as noted in the
title of the patch).

>            par->codec_id == AV_CODEC_ID_VP8 ||
>            par->codec_id == AV_CODEC_ID_VP9)) {
> -        av_log(s, AV_LOG_ERROR, "Currently only VP8, VP9 and AV1 are supported!\n");
> +        av_log(s, AV_LOG_ERROR, "Currently only H264, VP8, VP9 and AV1 are supported!\n");

Ditto regarding HEVC.

>          return AVERROR(EINVAL);
>      }
>      avio_write(pb, "DKIF", 4);
>      avio_wl16(pb, 0); // version
>      avio_wl16(pb, 32); // header length
> -    avio_wl32(pb,
> -              par->codec_id == AV_CODEC_ID_VP9 ? AV_RL32("VP90") :
> -              par->codec_id == AV_CODEC_ID_VP8 ? AV_RL32("VP80") : AV_RL32("AV01"));
> +    switch (par->codec_id) {
> +      case AV_CODEC_ID_AV1:
> +        avio_wl32(pb, AV_RL32("AV01"));
> +        break;
> +      case AV_CODEC_ID_H264:
> +        avio_wl32(pb, AV_RL32("H264"));
> +        break;
> +      case AV_CODEC_ID_VP8:
> +        avio_wl32(pb, AV_RL32("VP80"));
> +        break;
> +      case AV_CODEC_ID_VP9:
> +        avio_wl32(pb, AV_RL32("VP90"));
> +        break;
> +      default:
> +        break;
> +    }

Ditto regarding HEVC.

>      avio_wl16(pb, par->width);
>      avio_wl16(pb, par->height);
>      avio_wl32(pb, s->streams[0]->time_base.den);
> @@ -95,8 +109,21 @@ static int ivf_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt)
>      int ret = 1;
>      AVStream *st = s->streams[pkt->stream_index];
>
> -    if (st->codecpar->codec_id == AV_CODEC_ID_VP9)
> +    if (st->codecpar->codec_id == AV_CODEC_ID_H264) {
> +        if (pkt->size >= 5 && AV_RB32(pkt->data) != 0x0000001 &&
> +                             (AV_RB24(pkt->data) != 0x000001 ||
> +                              (st->codecpar->extradata_size > 0 &&
> +                               st->codecpar->extradata[0] == 1)))
> +            ret = ff_stream_add_bitstream_filter(st, "h264_mp4toannexb", NULL);
> +    } else if (st->codecpar->codec_id == AV_CODEC_ID_HEVC) {
> +        if (pkt->size >= 5 && AV_RB32(pkt->data) != 0x0000001 &&
> +                             (AV_RB24(pkt->data) != 0x000001 ||
> +                              (st->codecpar->extradata_size > 0 &&
> +                               st->codecpar->extradata[0] == 1)))
> +            ret = ff_stream_add_bitstream_filter(st, "hevc_mp4toannexb", NULL);
> +    } else if (st->codecpar->codec_id == AV_CODEC_ID_VP9) {
>          ret = ff_stream_add_bitstream_filter(st, "vp9_superframe", NULL);
> +    }
>

There is an honest question mark above my head right now. So you use
AVC/HEVC in IVF? Which is Annex B inside of another very simplistic
"container" that doesn't even have random access point flags? Could
you explain what is the benefit this would produce for people as
opposed to just writing raw AVC/HEVC Annex B streams? Thanks.

Best regards,
Jan
Carl Eugen Hoyos Sept. 27, 2018, 9:14 p.m. UTC | #2
2018-09-27 22:16 GMT+02:00, Jan Ekström <jeebjp@gmail.com>:
> On Thu, Sep 27, 2018 at 10:18 PM,  <alx.sukhanov@gmail.com> wrote:
>> From: Alex Sukhanov <asukhanov@google.com>
>>
>> ---
>>  libavformat/ivfenc.c | 37 ++++++++++++++++++++++++++++++++-----
>>  1 file changed, 32 insertions(+), 5 deletions(-)
>>
>> diff --git a/libavformat/ivfenc.c b/libavformat/ivfenc.c
>> index 66441a2a43..9ff7894b88 100644
>> --- a/libavformat/ivfenc.c
>> +++ b/libavformat/ivfenc.c
>> @@ -38,17 +38,31 @@ static int ivf_write_header(AVFormatContext *s)
>>      par = s->streams[0]->codecpar;
>>      if (par->codec_type != AVMEDIA_TYPE_VIDEO ||
>>          !(par->codec_id == AV_CODEC_ID_AV1 ||
>> +          par->codec_id == AV_CODEC_ID_H264 ||
>
> Misses HEVC if you're adding support for it as well (as noted in the
> title of the patch).
>
>>            par->codec_id == AV_CODEC_ID_VP8 ||
>>            par->codec_id == AV_CODEC_ID_VP9)) {
>> -        av_log(s, AV_LOG_ERROR, "Currently only VP8, VP9 and AV1 are
>> supported!\n");
>> +        av_log(s, AV_LOG_ERROR, "Currently only H264, VP8, VP9 and AV1
>> are supported!\n");
>
> Ditto regarding HEVC.
>
>>          return AVERROR(EINVAL);
>>      }
>>      avio_write(pb, "DKIF", 4);
>>      avio_wl16(pb, 0); // version
>>      avio_wl16(pb, 32); // header length
>> -    avio_wl32(pb,
>> -              par->codec_id == AV_CODEC_ID_VP9 ? AV_RL32("VP90") :
>> -              par->codec_id == AV_CODEC_ID_VP8 ? AV_RL32("VP80") :
>> AV_RL32("AV01"));
>> +    switch (par->codec_id) {
>> +      case AV_CODEC_ID_AV1:
>> +        avio_wl32(pb, AV_RL32("AV01"));
>> +        break;
>> +      case AV_CODEC_ID_H264:
>> +        avio_wl32(pb, AV_RL32("H264"));
>> +        break;
>> +      case AV_CODEC_ID_VP8:
>> +        avio_wl32(pb, AV_RL32("VP80"));
>> +        break;
>> +      case AV_CODEC_ID_VP9:
>> +        avio_wl32(pb, AV_RL32("VP90"));
>> +        break;
>> +      default:
>> +        break;
>> +    }
>
> Ditto regarding HEVC.
>
>>      avio_wl16(pb, par->width);
>>      avio_wl16(pb, par->height);
>>      avio_wl32(pb, s->streams[0]->time_base.den);
>> @@ -95,8 +109,21 @@ static int ivf_check_bitstream(struct AVFormatContext
>> *s, const AVPacket *pkt)
>>      int ret = 1;
>>      AVStream *st = s->streams[pkt->stream_index];
>>
>> -    if (st->codecpar->codec_id == AV_CODEC_ID_VP9)
>> +    if (st->codecpar->codec_id == AV_CODEC_ID_H264) {
>> +        if (pkt->size >= 5 && AV_RB32(pkt->data) != 0x0000001 &&
>> +                             (AV_RB24(pkt->data) != 0x000001 ||
>> +                              (st->codecpar->extradata_size > 0 &&
>> +                               st->codecpar->extradata[0] == 1)))
>> +            ret = ff_stream_add_bitstream_filter(st, "h264_mp4toannexb",
>> NULL);
>> +    } else if (st->codecpar->codec_id == AV_CODEC_ID_HEVC) {
>> +        if (pkt->size >= 5 && AV_RB32(pkt->data) != 0x0000001 &&
>> +                             (AV_RB24(pkt->data) != 0x000001 ||
>> +                              (st->codecpar->extradata_size > 0 &&
>> +                               st->codecpar->extradata[0] == 1)))
>> +            ret = ff_stream_add_bitstream_filter(st, "hevc_mp4toannexb",
>> NULL);
>> +    } else if (st->codecpar->codec_id == AV_CODEC_ID_VP9) {
>>          ret = ff_stream_add_bitstream_filter(st, "vp9_superframe", NULL);
>> +    }
>>
>
> There is an honest question mark above my head right now. So you use
> AVC/HEVC in IVF? Which is Annex B inside of another very simplistic
> "container" that doesn't even have random access point flags? Could
> you explain what is the benefit this would produce for people as
> opposed to just writing raw AVC/HEVC Annex B streams?

If Google decided to specify it, I believe we should support it.
If we agree that it is a bad idea to write such files, we can
request an increased strictness level.

Carl Eugen
diff mbox

Patch

diff --git a/libavformat/ivfenc.c b/libavformat/ivfenc.c
index 66441a2a43..9ff7894b88 100644
--- a/libavformat/ivfenc.c
+++ b/libavformat/ivfenc.c
@@ -38,17 +38,31 @@  static int ivf_write_header(AVFormatContext *s)
     par = s->streams[0]->codecpar;
     if (par->codec_type != AVMEDIA_TYPE_VIDEO ||
         !(par->codec_id == AV_CODEC_ID_AV1 ||
+          par->codec_id == AV_CODEC_ID_H264 ||
           par->codec_id == AV_CODEC_ID_VP8 ||
           par->codec_id == AV_CODEC_ID_VP9)) {
-        av_log(s, AV_LOG_ERROR, "Currently only VP8, VP9 and AV1 are supported!\n");
+        av_log(s, AV_LOG_ERROR, "Currently only H264, VP8, VP9 and AV1 are supported!\n");
         return AVERROR(EINVAL);
     }
     avio_write(pb, "DKIF", 4);
     avio_wl16(pb, 0); // version
     avio_wl16(pb, 32); // header length
-    avio_wl32(pb,
-              par->codec_id == AV_CODEC_ID_VP9 ? AV_RL32("VP90") :
-              par->codec_id == AV_CODEC_ID_VP8 ? AV_RL32("VP80") : AV_RL32("AV01"));
+    switch (par->codec_id) {
+      case AV_CODEC_ID_AV1:
+        avio_wl32(pb, AV_RL32("AV01"));
+        break;
+      case AV_CODEC_ID_H264:
+        avio_wl32(pb, AV_RL32("H264"));
+        break;
+      case AV_CODEC_ID_VP8:
+        avio_wl32(pb, AV_RL32("VP80"));
+        break;
+      case AV_CODEC_ID_VP9:
+        avio_wl32(pb, AV_RL32("VP90"));
+        break;
+      default:
+        break;
+    }
     avio_wl16(pb, par->width);
     avio_wl16(pb, par->height);
     avio_wl32(pb, s->streams[0]->time_base.den);
@@ -95,8 +109,21 @@  static int ivf_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt)
     int ret = 1;
     AVStream *st = s->streams[pkt->stream_index];
 
-    if (st->codecpar->codec_id == AV_CODEC_ID_VP9)
+    if (st->codecpar->codec_id == AV_CODEC_ID_H264) {
+        if (pkt->size >= 5 && AV_RB32(pkt->data) != 0x0000001 &&
+                             (AV_RB24(pkt->data) != 0x000001 ||
+                              (st->codecpar->extradata_size > 0 &&
+                               st->codecpar->extradata[0] == 1)))
+            ret = ff_stream_add_bitstream_filter(st, "h264_mp4toannexb", NULL);
+    } else if (st->codecpar->codec_id == AV_CODEC_ID_HEVC) {
+        if (pkt->size >= 5 && AV_RB32(pkt->data) != 0x0000001 &&
+                             (AV_RB24(pkt->data) != 0x000001 ||
+                              (st->codecpar->extradata_size > 0 &&
+                               st->codecpar->extradata[0] == 1)))
+            ret = ff_stream_add_bitstream_filter(st, "hevc_mp4toannexb", NULL);
+    } else if (st->codecpar->codec_id == AV_CODEC_ID_VP9) {
         ret = ff_stream_add_bitstream_filter(st, "vp9_superframe", NULL);
+    }
 
     return ret;
 }