diff mbox series

[FFmpeg-devel,1/2] avformat/flvenc: Add support for HEVC over flv in muxer

Message ID 20230406121241.86114-1-lq@chinaffmpeg.org
State New
Headers show
Series [FFmpeg-devel,1/2] avformat/flvenc: Add support for HEVC over flv in muxer | expand

Checks

Context Check Description
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished

Commit Message

Steven Liu April 6, 2023, 12:12 p.m. UTC
Implements HEVC according to enhanced RTMP spec found at
https://github.com/veovera/enhanced-rtmp

And it has beed supported by OBS, Simple Realtime Server.
And the Enhancing FLV documentation Contributors include
Jean-Baptiste Kempf (FFmpeg, VideoLAN).
So this should be support by ffmpeg too.

Signed-off-by: Steven Liu <lq@chinaffmpeg.org>
---
 libavformat/flv.h    | 16 ++++++++++++++
 libavformat/flvenc.c | 50 +++++++++++++++++++++++++++++++++-----------
 2 files changed, 54 insertions(+), 12 deletions(-)

Comments

Lance Wang April 6, 2023, 2:44 p.m. UTC | #1
On Thu, Apr 6, 2023 at 8:14 PM Steven Liu <lq@chinaffmpeg.org> wrote:

> Implements HEVC according to enhanced RTMP spec found at
> https://github.com/veovera/enhanced-rtmp
>
>
I think It's document or draft and not specs, I haven't heard any
information for the
veovera software organization. So before implementation, please prove it's
recognized authority.  Please see rfc2026.



> And it has beed supported by OBS, Simple Realtime Server.
> And the Enhancing FLV documentation Contributors include
> Jean-Baptiste Kempf (FFmpeg, VideoLAN).
> So this should be support by ffmpeg too.
>
> Signed-off-by: Steven Liu <lq@chinaffmpeg.org>
> ---
>  libavformat/flv.h    | 16 ++++++++++++++
>  libavformat/flvenc.c | 50 +++++++++++++++++++++++++++++++++-----------
>  2 files changed, 54 insertions(+), 12 deletions(-)
>
> diff --git a/libavformat/flv.h b/libavformat/flv.h
> index 3571b90279..44d3b04ff9 100644
> --- a/libavformat/flv.h
> +++ b/libavformat/flv.h
> @@ -35,6 +35,12 @@
>
>  #define FLV_VIDEO_FRAMETYPE_OFFSET   4
>
> +/* Extended VideoTagHeader
> + * defined in reference link:
> + *
> https://github.com/veovera/enhanced-rtmp/blob/main/enhanced-rtmp-v1.pdf
> + * */
> +#define FLV_IS_EX_HEADER          0x80
> +
>  /* bitmasks to isolate specific values */
>  #define FLV_AUDIO_CHANNEL_MASK    0x01
>  #define FLV_AUDIO_SAMPLESIZE_MASK 0x02
> @@ -110,6 +116,16 @@ enum {
>      FLV_CODECID_H264    = 7,
>      FLV_CODECID_REALH263= 8,
>      FLV_CODECID_MPEG4   = 9,
> +    FLV_CODECID_HEVC    = 10,
> +};
> +
> +enum {
> +    PacketTypeSequenceStart         = 0,
> +    PacketTypeCodedFrames           = 1,
> +    PacketTypeSequenceEnd           = 2,
> +    PacketTypeCodedFramesX          = 3,
> +    PacketTypeMetadata              = 4,
> +    PacketTypeMPEG2TSSequenceStart  = 5,
>  };
>
>  enum {
> diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c
> index 64ea554dad..15a0f573f3 100644
> --- a/libavformat/flvenc.c
> +++ b/libavformat/flvenc.c
> @@ -28,6 +28,7 @@
>  #include "libavcodec/mpeg4audio.h"
>  #include "avio.h"
>  #include "avc.h"
> +#include "hevc.h"
>  #include "avformat.h"
>  #include "flv.h"
>  #include "internal.h"
> @@ -46,6 +47,7 @@ static const AVCodecTag flv_video_codec_ids[] = {
>      { AV_CODEC_ID_VP6,      FLV_CODECID_VP6 },
>      { AV_CODEC_ID_VP6A,     FLV_CODECID_VP6A },
>      { AV_CODEC_ID_H264,     FLV_CODECID_H264 },
> +    { AV_CODEC_ID_HEVC,     FLV_CODECID_HEVC },
>      { AV_CODEC_ID_NONE,     0 }
>  };
>
> @@ -492,7 +494,7 @@ static void flv_write_codec_header(AVFormatContext* s,
> AVCodecParameters* par, i
>      FLVContext *flv = s->priv_data;
>
>      if (par->codec_id == AV_CODEC_ID_AAC || par->codec_id ==
> AV_CODEC_ID_H264
> -            || par->codec_id == AV_CODEC_ID_MPEG4) {
> +            || par->codec_id == AV_CODEC_ID_MPEG4 || par->codec_id ==
> AV_CODEC_ID_HEVC) {
>          int64_t pos;
>          avio_w8(pb,
>                  par->codec_type == AVMEDIA_TYPE_VIDEO ?
> @@ -535,10 +537,19 @@ static void flv_write_codec_header(AVFormatContext*
> s, AVCodecParameters* par, i
>              }
>              avio_write(pb, par->extradata, par->extradata_size);
>          } else {
> -            avio_w8(pb, par->codec_tag | FLV_FRAME_KEY); // flags
> -            avio_w8(pb, 0); // AVC sequence header
> -            avio_wb24(pb, 0); // composition time
> -            ff_isom_write_avcc(pb, par->extradata, par->extradata_size);
> +            if (par->codec_id == AV_CODEC_ID_HEVC) {
> +                avio_w8(pb, FLV_IS_EX_HEADER | PacketTypeSequenceStart);
> // ExVideoTagHeader mode with PacketTypeSequenceStart
> +                avio_write(pb, "hvc1", 4);
> +            } else {
> +                avio_w8(pb, par->codec_tag | FLV_FRAME_KEY); // flags
> +                avio_w8(pb, 0); // AVC sequence header
> +                avio_wb24(pb, 0); // composition time
> +            }
> +
> +            if (par->codec_id == AV_CODEC_ID_HEVC)
> +                ff_isom_write_hvcc(pb, par->extradata,
> par->extradata_size, 0);
> +            else
> +                ff_isom_write_avcc(pb, par->extradata,
> par->extradata_size);
>          }
>          data_size = avio_tell(pb) - pos;
>          avio_seek(pb, -data_size - 10, SEEK_CUR);
> @@ -628,7 +639,8 @@ static int flv_init(struct AVFormatContext *s)
>                  return unsupported_codec(s, "Video", par->codec_id);
>
>              if (par->codec_id == AV_CODEC_ID_MPEG4 ||
> -                par->codec_id == AV_CODEC_ID_H263) {
> +                par->codec_id == AV_CODEC_ID_H263 ||
> +                par->codec_id == AV_CODEC_ID_HEVC) {
>                  int error = s->strict_std_compliance >
> FF_COMPLIANCE_UNOFFICIAL;
>                  av_log(s, error ? AV_LOG_ERROR : AV_LOG_WARNING,
>                         "Codec %s is not supported in the official FLV
> specification,\n", avcodec_get_name(par->codec_id));
> @@ -784,8 +796,11 @@ end:
>          for (i = 0; i < s->nb_streams; i++) {
>              AVCodecParameters *par = s->streams[i]->codecpar;
>              FLVStreamContext *sc = s->streams[i]->priv_data;
> -            if (par->codec_type == AVMEDIA_TYPE_VIDEO &&
> -                    (par->codec_id == AV_CODEC_ID_H264 || par->codec_id
> == AV_CODEC_ID_MPEG4))
> +            if (par->codec_id == AV_CODEC_ID_HEVC) {
> +                avio_w8(pb, 0x82);
> +                avio_write(pb, "hvc1", 4);
> +            } else if (par->codec_type == AVMEDIA_TYPE_VIDEO &&
> +                    (par->codec_id == AV_CODEC_ID_H264 || par->codec_id
> == AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC))
>                  put_eos_tag(pb, sc->last_ts, par->codec_id);
>          }
>      }
> @@ -836,13 +851,13 @@ static int flv_write_packet(AVFormatContext *s,
> AVPacket *pkt)
>      if (par->codec_id == AV_CODEC_ID_VP6F || par->codec_id ==
> AV_CODEC_ID_VP6A ||
>          par->codec_id == AV_CODEC_ID_VP6  || par->codec_id ==
> AV_CODEC_ID_AAC)
>          flags_size = 2;
> -    else if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id ==
> AV_CODEC_ID_MPEG4)
> +    else if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id ==
> AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC)
>          flags_size = 5;
>      else
>          flags_size = 1;
>
>      if (par->codec_id == AV_CODEC_ID_AAC || par->codec_id ==
> AV_CODEC_ID_H264
> -            || par->codec_id == AV_CODEC_ID_MPEG4) {
> +            || par->codec_id == AV_CODEC_ID_MPEG4 || par->codec_id ==
> AV_CODEC_ID_HEVC) {
>          size_t side_size;
>          uint8_t *side = av_packet_get_side_data(pkt,
> AV_PKT_DATA_NEW_EXTRADATA, &side_size);
>          if (side && side_size > 0 && (side_size != par->extradata_size ||
> memcmp(side, par->extradata, side_size))) {
> @@ -862,7 +877,7 @@ static int flv_write_packet(AVFormatContext *s,
> AVPacket *pkt)
>                 "Packets are not in the proper order with respect to
> DTS\n");
>          return AVERROR(EINVAL);
>      }
> -    if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id ==
> AV_CODEC_ID_MPEG4) {
> +    if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id ==
> AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC) {
>          if (pkt->pts == AV_NOPTS_VALUE) {
>              av_log(s, AV_LOG_ERROR, "Packet is missing PTS\n");
>              return AVERROR(EINVAL);
> @@ -907,6 +922,10 @@ static int flv_write_packet(AVFormatContext *s,
> AVPacket *pkt)
>          if (par->extradata_size > 0 && *(uint8_t*)par->extradata != 1)
>              if ((ret = ff_avc_parse_nal_units_buf(pkt->data, &data,
> &size)) < 0)
>                  return ret;
> +    } else if (par->codec_id == AV_CODEC_ID_HEVC) {
> +        if (par->extradata_size > 0 && *(uint8_t*)par->extradata != 1)
> +            if ((ret = ff_hevc_annexb2mp4_buf(pkt->data, &data, &size, 0,
> NULL)) < 0)
> +                return ret;
>      } else if (par->codec_id == AV_CODEC_ID_AAC && pkt->size > 2 &&
>                 (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) {
>          if (!s->streams[pkt->stream_index]->nb_frames) {
> @@ -968,7 +987,12 @@ static int flv_write_packet(AVFormatContext *s,
> AVPacket *pkt)
>          avio_wb32(pb, data_size + 11);
>      } else {
>          av_assert1(flags>=0);
> -        avio_w8(pb,flags);
> +        if (par->codec_id == AV_CODEC_ID_HEVC) {
> +            avio_w8(pb, FLV_IS_EX_HEADER | PacketTypeCodedFrames); //
> ExVideoTagHeader mode with PacketTypeCodedFrames
> +            avio_write(pb, "hvc1", 4);
> +        } else {
> +            avio_w8(pb, flags);
> +        }
>          if (par->codec_id == AV_CODEC_ID_VP6)
>              avio_w8(pb,0);
>          if (par->codec_id == AV_CODEC_ID_VP6F || par->codec_id ==
> AV_CODEC_ID_VP6A) {
> @@ -982,6 +1006,8 @@ static int flv_write_packet(AVFormatContext *s,
> AVPacket *pkt)
>          else if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id ==
> AV_CODEC_ID_MPEG4) {
>              avio_w8(pb, 1); // AVC NALU
>              avio_wb24(pb, pkt->pts - pkt->dts);
> +        } else if (par->codec_id == AV_CODEC_ID_HEVC) {
> +            avio_wb24(pb, pkt->pts - pkt->dts);
>          }
>
>          avio_write(pb, data ? data : pkt->data, size);
> --
> 2.40.0
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>
Gyan Doshi April 6, 2023, 3:10 p.m. UTC | #2
On 2023-04-06 08:14 pm, Lance Wang wrote:
> On Thu, Apr 6, 2023 at 8:14 PM Steven Liu <lq@chinaffmpeg.org> wrote:
>
>> Implements HEVC according to enhanced RTMP spec found at
>> https://github.com/veovera/enhanced-rtmp
>>
>>
> I think It's document or draft and not specs, I haven't heard any
> information for the
> veovera software organization. So before implementation, please prove it's
> recognized authority.  Please see rfc2026.

Their Github readme claims

"Additionally, Veovera has welcomed new members to the organization 
including Adobe, Google and Veriskope."

I didn't find any public corroboration by these companies.

However,  one of the authors is cited as having OBS affiliation and they 
have indeed merged support:
https://www.phoronix.com/news/OBS-Studio-AV1-HEVC-RTMP

Since they claim jbk as a member, ping him.

Regards,
Gyan
Jean-Baptiste Kempf April 6, 2023, 3:32 p.m. UTC | #3
On Thu, 6 Apr 2023, at 17:10, Gyan Doshi wrote:
> On 2023-04-06 08:14 pm, Lance Wang wrote:
>> On Thu, Apr 6, 2023 at 8:14 PM Steven Liu <lq@chinaffmpeg.org> wrote:
>>
>>> Implements HEVC according to enhanced RTMP spec found at
>>> https://github.com/veovera/enhanced-rtmp
>>>
>>>
>> I think It's document or draft and not specs, I haven't heard any
>> information for the
>> veovera software organization. So before implementation, please prove it's
>> recognized authority.  Please see rfc2026.
>
> Their Github readme claims
>
> "Additionally, Veovera has welcomed new members to the organization 
> including Adobe, Google and Veriskope."
>
> I didn't find any public corroboration by these companies.

Technically, Veovera is the one doing the maintenance of Flash Media Server, given by Adobe.
So it's so far, the best authority on flv and RTMP.

But for me, all those are still drafts, and therefore need to wait a bit.

Also, audio extension is coming too. (Same system for FourCC)

jb
Jan Ekström April 6, 2023, 5:03 p.m. UTC | #4
On Thu, Apr 6, 2023 at 6:11 PM Gyan Doshi <ffmpeg@gyani.pro> wrote:
>
>
>
> On 2023-04-06 08:14 pm, Lance Wang wrote:
> > On Thu, Apr 6, 2023 at 8:14 PM Steven Liu <lq@chinaffmpeg.org> wrote:
> >
> >> Implements HEVC according to enhanced RTMP spec found at
> >> https://github.com/veovera/enhanced-rtmp
> >>
> >>
> > I think It's document or draft and not specs, I haven't heard any
> > information for the
> > veovera software organization. So before implementation, please prove it's
> > recognized authority.  Please see rfc2026.
>
> Their Github readme claims
>
> "Additionally, Veovera has welcomed new members to the organization
> including Adobe, Google and Veriskope."
>
> I didn't find any public corroboration by these companies.
>

Yea, it seems like this was mostly done in the background (classic
corporations being corporations), but I think the most direct way to
notice that Google at least has acknowledged this extension is because
Youtube now seems to support AV1 live stream ingest via RTMP with
these extensions.

Jan
Neal Gompa April 11, 2023, 8:56 a.m. UTC | #5
On Thu, Apr 6, 2023 at 1:03 PM Jan Ekström <jeebjp@gmail.com> wrote:
>
> On Thu, Apr 6, 2023 at 6:11 PM Gyan Doshi <ffmpeg@gyani.pro> wrote:
> >
> >
> >
> > On 2023-04-06 08:14 pm, Lance Wang wrote:
> > > On Thu, Apr 6, 2023 at 8:14 PM Steven Liu <lq@chinaffmpeg.org> wrote:
> > >
> > >> Implements HEVC according to enhanced RTMP spec found at
> > >> https://github.com/veovera/enhanced-rtmp
> > >>
> > >>
> > > I think It's document or draft and not specs, I haven't heard any
> > > information for the
> > > veovera software organization. So before implementation, please prove it's
> > > recognized authority.  Please see rfc2026.
> >
> > Their Github readme claims
> >
> > "Additionally, Veovera has welcomed new members to the organization
> > including Adobe, Google and Veriskope."
> >
> > I didn't find any public corroboration by these companies.
> >
>
> Yea, it seems like this was mostly done in the background (classic
> corporations being corporations), but I think the most direct way to
> notice that Google at least has acknowledged this extension is because
> Youtube now seems to support AV1 live stream ingest via RTMP with
> these extensions.
>

Notably though, these patches don't implement that, though. :(
Steven Liu April 11, 2023, 9:24 a.m. UTC | #6
Neal Gompa <ngompa13@gmail.com> 于2023年4月11日周二 16:57写道:
>
> On Thu, Apr 6, 2023 at 1:03 PM Jan Ekström <jeebjp@gmail.com> wrote:
> >
> > On Thu, Apr 6, 2023 at 6:11 PM Gyan Doshi <ffmpeg@gyani.pro> wrote:
> > >
> > >
> > >
> > > On 2023-04-06 08:14 pm, Lance Wang wrote:
> > > > On Thu, Apr 6, 2023 at 8:14 PM Steven Liu <lq@chinaffmpeg.org> wrote:
> > > >
> > > >> Implements HEVC according to enhanced RTMP spec found at
> > > >> https://github.com/veovera/enhanced-rtmp
> > > >>
> > > >>
> > > > I think It's document or draft and not specs, I haven't heard any
> > > > information for the
> > > > veovera software organization. So before implementation, please prove it's
> > > > recognized authority.  Please see rfc2026.
> > >
> > > Their Github readme claims
> > >
> > > "Additionally, Veovera has welcomed new members to the organization
> > > including Adobe, Google and Veriskope."
> > >
> > > I didn't find any public corroboration by these companies.
> > >
> >
> > Yea, it seems like this was mostly done in the background (classic
> > corporations being corporations), but I think the most direct way to
> > notice that Google at least has acknowledged this extension is because
> > Youtube now seems to support AV1 live stream ingest via RTMP with
> > these extensions.
> >
>
> Notably though, these patches don't implement that, though. :(
This is first step, if this patchset can be merge is means that the
av1,vp9 can be accpected too. :D

>
>
>
> --
> 真実はいつも一つ!/ Always, there's only one truth!
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
Neal Gompa April 12, 2023, 1:26 a.m. UTC | #7
On Tue, Apr 11, 2023 at 5:25 AM Steven Liu <lingjiujianke@gmail.com> wrote:
>
> Neal Gompa <ngompa13@gmail.com> 于2023年4月11日周二 16:57写道:
> >
> > On Thu, Apr 6, 2023 at 1:03 PM Jan Ekström <jeebjp@gmail.com> wrote:
> > >
> > > On Thu, Apr 6, 2023 at 6:11 PM Gyan Doshi <ffmpeg@gyani.pro> wrote:
> > > >
> > > >
> > > >
> > > > On 2023-04-06 08:14 pm, Lance Wang wrote:
> > > > > On Thu, Apr 6, 2023 at 8:14 PM Steven Liu <lq@chinaffmpeg.org> wrote:
> > > > >
> > > > >> Implements HEVC according to enhanced RTMP spec found at
> > > > >> https://github.com/veovera/enhanced-rtmp
> > > > >>
> > > > >>
> > > > > I think It's document or draft and not specs, I haven't heard any
> > > > > information for the
> > > > > veovera software organization. So before implementation, please prove it's
> > > > > recognized authority.  Please see rfc2026.
> > > >
> > > > Their Github readme claims
> > > >
> > > > "Additionally, Veovera has welcomed new members to the organization
> > > > including Adobe, Google and Veriskope."
> > > >
> > > > I didn't find any public corroboration by these companies.
> > > >
> > >
> > > Yea, it seems like this was mostly done in the background (classic
> > > corporations being corporations), but I think the most direct way to
> > > notice that Google at least has acknowledged this extension is because
> > > Youtube now seems to support AV1 live stream ingest via RTMP with
> > > these extensions.
> > >
> >
> > Notably though, these patches don't implement that, though. :(
> This is first step, if this patchset can be merge is means that the
> av1,vp9 can be accpected too. :D
>

Could you submit a complete version when you respin v4? The only
endpoint I can reasonably test is YouTube, so not having AV1 support
makes it difficult for me to try it out...
Steven Liu April 12, 2023, 3:10 a.m. UTC | #8
Neal Gompa <ngompa13@gmail.com> 于2023年4月12日周三 09:27写道:
>
> On Tue, Apr 11, 2023 at 5:25 AM Steven Liu <lingjiujianke@gmail.com> wrote:
> >
> > Neal Gompa <ngompa13@gmail.com> 于2023年4月11日周二 16:57写道:
> > >
> > > On Thu, Apr 6, 2023 at 1:03 PM Jan Ekström <jeebjp@gmail.com> wrote:
> > > >
> > > > On Thu, Apr 6, 2023 at 6:11 PM Gyan Doshi <ffmpeg@gyani.pro> wrote:
> > > > >
> > > > >
> > > > >
> > > > > On 2023-04-06 08:14 pm, Lance Wang wrote:
> > > > > > On Thu, Apr 6, 2023 at 8:14 PM Steven Liu <lq@chinaffmpeg.org> wrote:
> > > > > >
> > > > > >> Implements HEVC according to enhanced RTMP spec found at
> > > > > >> https://github.com/veovera/enhanced-rtmp
> > > > > >>
> > > > > >>
> > > > > > I think It's document or draft and not specs, I haven't heard any
> > > > > > information for the
> > > > > > veovera software organization. So before implementation, please prove it's
> > > > > > recognized authority.  Please see rfc2026.
> > > > >
> > > > > Their Github readme claims
> > > > >
> > > > > "Additionally, Veovera has welcomed new members to the organization
> > > > > including Adobe, Google and Veriskope."
> > > > >
> > > > > I didn't find any public corroboration by these companies.
> > > > >
> > > >
> > > > Yea, it seems like this was mostly done in the background (classic
> > > > corporations being corporations), but I think the most direct way to
> > > > notice that Google at least has acknowledged this extension is because
> > > > Youtube now seems to support AV1 live stream ingest via RTMP with
> > > > these extensions.
> > > >
> > >
> > > Notably though, these patches don't implement that, though. :(
> > This is first step, if this patchset can be merge is means that the
> > av1,vp9 can be accpected too. :D
> >
>
> Could you submit a complete version when you respin v4? The only
> endpoint I can reasonably test is YouTube, so not having AV1 support
> makes it difficult for me to try it out...
you can test it by ossrs :D
I think i can submit new patchset after this patchset be merged :D
>
>
>
> --
> 真実はいつも一つ!/ Always, there's only one truth!
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
Steven Liu April 12, 2023, 4:32 a.m. UTC | #9
Neal Gompa <ngompa13@gmail.com> 于2023年4月12日周三 09:27写道:
> Could you submit a complete version when you respin v4? The only
> endpoint I can reasonably test is YouTube, so not having AV1 support
> makes it difficult for me to try it out...
Try this patchset please.
https://patchwork.ffmpeg.org/project/ffmpeg/list/?series=8723
>
Steven Liu April 12, 2023, 4:42 a.m. UTC | #10
Steven Liu <lingjiujianke@gmail.com> 于2023年4月12日周三 12:32写道:
>
> Neal Gompa <ngompa13@gmail.com> 于2023年4月12日周三 09:27写道:
> > Could you submit a complete version when you respin v4? The only
> > endpoint I can reasonably test is YouTube, so not having AV1 support
> > makes it difficult for me to try it out...
> Try this patchset please.
> https://patchwork.ffmpeg.org/project/ffmpeg/list/?series=8723
Ignore this patchset, i resubmit a v5 fix compiling error at the third patch
You can try the v5 version.


Thanks
Steven
diff mbox series

Patch

diff --git a/libavformat/flv.h b/libavformat/flv.h
index 3571b90279..44d3b04ff9 100644
--- a/libavformat/flv.h
+++ b/libavformat/flv.h
@@ -35,6 +35,12 @@ 
 
 #define FLV_VIDEO_FRAMETYPE_OFFSET   4
 
+/* Extended VideoTagHeader
+ * defined in reference link:
+ * https://github.com/veovera/enhanced-rtmp/blob/main/enhanced-rtmp-v1.pdf
+ * */
+#define FLV_IS_EX_HEADER          0x80
+
 /* bitmasks to isolate specific values */
 #define FLV_AUDIO_CHANNEL_MASK    0x01
 #define FLV_AUDIO_SAMPLESIZE_MASK 0x02
@@ -110,6 +116,16 @@  enum {
     FLV_CODECID_H264    = 7,
     FLV_CODECID_REALH263= 8,
     FLV_CODECID_MPEG4   = 9,
+    FLV_CODECID_HEVC    = 10,
+};
+
+enum {
+    PacketTypeSequenceStart         = 0,
+    PacketTypeCodedFrames           = 1,
+    PacketTypeSequenceEnd           = 2,
+    PacketTypeCodedFramesX          = 3,
+    PacketTypeMetadata              = 4,
+    PacketTypeMPEG2TSSequenceStart  = 5,
 };
 
 enum {
diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c
index 64ea554dad..15a0f573f3 100644
--- a/libavformat/flvenc.c
+++ b/libavformat/flvenc.c
@@ -28,6 +28,7 @@ 
 #include "libavcodec/mpeg4audio.h"
 #include "avio.h"
 #include "avc.h"
+#include "hevc.h"
 #include "avformat.h"
 #include "flv.h"
 #include "internal.h"
@@ -46,6 +47,7 @@  static const AVCodecTag flv_video_codec_ids[] = {
     { AV_CODEC_ID_VP6,      FLV_CODECID_VP6 },
     { AV_CODEC_ID_VP6A,     FLV_CODECID_VP6A },
     { AV_CODEC_ID_H264,     FLV_CODECID_H264 },
+    { AV_CODEC_ID_HEVC,     FLV_CODECID_HEVC },
     { AV_CODEC_ID_NONE,     0 }
 };
 
@@ -492,7 +494,7 @@  static void flv_write_codec_header(AVFormatContext* s, AVCodecParameters* par, i
     FLVContext *flv = s->priv_data;
 
     if (par->codec_id == AV_CODEC_ID_AAC || par->codec_id == AV_CODEC_ID_H264
-            || par->codec_id == AV_CODEC_ID_MPEG4) {
+            || par->codec_id == AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC) {
         int64_t pos;
         avio_w8(pb,
                 par->codec_type == AVMEDIA_TYPE_VIDEO ?
@@ -535,10 +537,19 @@  static void flv_write_codec_header(AVFormatContext* s, AVCodecParameters* par, i
             }
             avio_write(pb, par->extradata, par->extradata_size);
         } else {
-            avio_w8(pb, par->codec_tag | FLV_FRAME_KEY); // flags
-            avio_w8(pb, 0); // AVC sequence header
-            avio_wb24(pb, 0); // composition time
-            ff_isom_write_avcc(pb, par->extradata, par->extradata_size);
+            if (par->codec_id == AV_CODEC_ID_HEVC) {
+                avio_w8(pb, FLV_IS_EX_HEADER | PacketTypeSequenceStart); // ExVideoTagHeader mode with PacketTypeSequenceStart
+                avio_write(pb, "hvc1", 4);
+            } else {
+                avio_w8(pb, par->codec_tag | FLV_FRAME_KEY); // flags
+                avio_w8(pb, 0); // AVC sequence header
+                avio_wb24(pb, 0); // composition time
+            }
+
+            if (par->codec_id == AV_CODEC_ID_HEVC)
+                ff_isom_write_hvcc(pb, par->extradata, par->extradata_size, 0);
+            else
+                ff_isom_write_avcc(pb, par->extradata, par->extradata_size);
         }
         data_size = avio_tell(pb) - pos;
         avio_seek(pb, -data_size - 10, SEEK_CUR);
@@ -628,7 +639,8 @@  static int flv_init(struct AVFormatContext *s)
                 return unsupported_codec(s, "Video", par->codec_id);
 
             if (par->codec_id == AV_CODEC_ID_MPEG4 ||
-                par->codec_id == AV_CODEC_ID_H263) {
+                par->codec_id == AV_CODEC_ID_H263 ||
+                par->codec_id == AV_CODEC_ID_HEVC) {
                 int error = s->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL;
                 av_log(s, error ? AV_LOG_ERROR : AV_LOG_WARNING,
                        "Codec %s is not supported in the official FLV specification,\n", avcodec_get_name(par->codec_id));
@@ -784,8 +796,11 @@  end:
         for (i = 0; i < s->nb_streams; i++) {
             AVCodecParameters *par = s->streams[i]->codecpar;
             FLVStreamContext *sc = s->streams[i]->priv_data;
-            if (par->codec_type == AVMEDIA_TYPE_VIDEO &&
-                    (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4))
+            if (par->codec_id == AV_CODEC_ID_HEVC) {
+                avio_w8(pb, 0x82);
+                avio_write(pb, "hvc1", 4);
+            } else if (par->codec_type == AVMEDIA_TYPE_VIDEO &&
+                    (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC))
                 put_eos_tag(pb, sc->last_ts, par->codec_id);
         }
     }
@@ -836,13 +851,13 @@  static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)
     if (par->codec_id == AV_CODEC_ID_VP6F || par->codec_id == AV_CODEC_ID_VP6A ||
         par->codec_id == AV_CODEC_ID_VP6  || par->codec_id == AV_CODEC_ID_AAC)
         flags_size = 2;
-    else if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4)
+    else if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC)
         flags_size = 5;
     else
         flags_size = 1;
 
     if (par->codec_id == AV_CODEC_ID_AAC || par->codec_id == AV_CODEC_ID_H264
-            || par->codec_id == AV_CODEC_ID_MPEG4) {
+            || par->codec_id == AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC) {
         size_t side_size;
         uint8_t *side = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size);
         if (side && side_size > 0 && (side_size != par->extradata_size || memcmp(side, par->extradata, side_size))) {
@@ -862,7 +877,7 @@  static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)
                "Packets are not in the proper order with respect to DTS\n");
         return AVERROR(EINVAL);
     }
-    if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4) {
+    if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4 || par->codec_id == AV_CODEC_ID_HEVC) {
         if (pkt->pts == AV_NOPTS_VALUE) {
             av_log(s, AV_LOG_ERROR, "Packet is missing PTS\n");
             return AVERROR(EINVAL);
@@ -907,6 +922,10 @@  static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)
         if (par->extradata_size > 0 && *(uint8_t*)par->extradata != 1)
             if ((ret = ff_avc_parse_nal_units_buf(pkt->data, &data, &size)) < 0)
                 return ret;
+    } else if (par->codec_id == AV_CODEC_ID_HEVC) {
+        if (par->extradata_size > 0 && *(uint8_t*)par->extradata != 1)
+            if ((ret = ff_hevc_annexb2mp4_buf(pkt->data, &data, &size, 0, NULL)) < 0)
+                return ret;
     } else if (par->codec_id == AV_CODEC_ID_AAC && pkt->size > 2 &&
                (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) {
         if (!s->streams[pkt->stream_index]->nb_frames) {
@@ -968,7 +987,12 @@  static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)
         avio_wb32(pb, data_size + 11);
     } else {
         av_assert1(flags>=0);
-        avio_w8(pb,flags);
+        if (par->codec_id == AV_CODEC_ID_HEVC) {
+            avio_w8(pb, FLV_IS_EX_HEADER | PacketTypeCodedFrames); // ExVideoTagHeader mode with PacketTypeCodedFrames
+            avio_write(pb, "hvc1", 4);
+        } else {
+            avio_w8(pb, flags);
+        }
         if (par->codec_id == AV_CODEC_ID_VP6)
             avio_w8(pb,0);
         if (par->codec_id == AV_CODEC_ID_VP6F || par->codec_id == AV_CODEC_ID_VP6A) {
@@ -982,6 +1006,8 @@  static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)
         else if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4) {
             avio_w8(pb, 1); // AVC NALU
             avio_wb24(pb, pkt->pts - pkt->dts);
+        } else if (par->codec_id == AV_CODEC_ID_HEVC) {
+            avio_wb24(pb, pkt->pts - pkt->dts);
         }
 
         avio_write(pb, data ? data : pkt->data, size);