Message ID | TYAPR01MB4271A2510D241D1E863565A6C1CA0@TYAPR01MB4271.jpnprd01.prod.outlook.com |
---|---|
State | Superseded |
Headers | show |
Series | [FFmpeg-devel,v4] libavformat/movenc: Add support for HEVC in .3gp | expand |
Context | Check | Description |
---|---|---|
andriy/x86_make | success | Make finished |
andriy/x86_make_fate | success | Make fate finished |
andriy/PPC64_make | success | Make finished |
andriy/PPC64_make_fate | success | Make fate finished |
> 2020年12月11日 下午1:58,hisunzhenliang@outlook.com 写道: > > From: SunZhenliang <hisunzhenliang@outlook.com> > > Just add HEVC's tag in 3gp tag list and it works to support HEVC in > 3gp files. > > Signed-off-by: SunZhenliang <hisunzhenliang@outlook.com> > --- > libavformat/movenc.c | 29 +++++++++++++++++++++-------- > 1 file changed, 21 insertions(+), 8 deletions(-) > > diff --git a/libavformat/movenc.c b/libavformat/movenc.c > index 18fa3f9b5e..daf33b634f 100644 > --- a/libavformat/movenc.c > +++ b/libavformat/movenc.c > @@ -4923,7 +4923,7 @@ static int mov_write_mdat_tag(AVIOContext *pb, MOVMuxContext *mov) > } > > static void mov_write_ftyp_tag_internal(AVIOContext *pb, AVFormatContext *s, > - int has_h264, int has_video, int write_minor) > + int has_h2645, int has_video, int write_minor) > { > MOVMuxContext *mov = s->priv_data; > int minor = 0x200; > @@ -4931,11 +4931,11 @@ static void mov_write_ftyp_tag_internal(AVIOContext *pb, AVFormatContext *s, > if (mov->major_brand && strlen(mov->major_brand) >= 4) > ffio_wfourcc(pb, mov->major_brand); > else if (mov->mode == MODE_3GP) { > - ffio_wfourcc(pb, has_h264 ? "3gp6" : "3gp4"); > - minor = has_h264 ? 0x100 : 0x200; > + ffio_wfourcc(pb, has_h2645 ? "3gp6" : "3gp4"); > + minor = has_h2645 ? 0x100 : 0x200; > } else if (mov->mode & MODE_3G2) { > - ffio_wfourcc(pb, has_h264 ? "3g2b" : "3g2a"); > - minor = has_h264 ? 0x20000 : 0x10000; > + ffio_wfourcc(pb, has_h2645 ? "3g2b" : "3g2a"); > + minor = has_h2645 ? 0x20000 : 0x10000; > } else if (mov->mode == MODE_PSP) > ffio_wfourcc(pb, "MSNV"); > else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_FRAGMENT && > @@ -4964,7 +4964,8 @@ static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s) > { > MOVMuxContext *mov = s->priv_data; > int64_t pos = avio_tell(pb); > - int has_h264 = 0, has_av1 = 0, has_video = 0; > + int has_h264 = 0, has_h265 = 0, has_av1 = 0, has_video = 0; > + uint32_t h265_codec_tag = 0; > int i; > > for (i = 0; i < s->nb_streams; i++) { > @@ -4975,6 +4976,10 @@ static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s) > has_video = 1; > if (st->codecpar->codec_id == AV_CODEC_ID_H264) > has_h264 = 1; > + if (st->codecpar->codec_id == AV_CODEC_ID_H265){ pay attention about the code style > + has_h265 = 1; > + h265_codec_tag = st->codecpar->codec_tag; > + } > if (st->codecpar->codec_id == AV_CODEC_ID_AV1) > has_av1 = 1; > } > @@ -4983,9 +4988,9 @@ static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s) > ffio_wfourcc(pb, "ftyp"); > > // Write major brand > - mov_write_ftyp_tag_internal(pb, s, has_h264, has_video, 1); > + mov_write_ftyp_tag_internal(pb, s, has_h264 || has_h265 , has_video, 1); > // Write the major brand as the first compatible brand as well > - mov_write_ftyp_tag_internal(pb, s, has_h264, has_video, 0); > + mov_write_ftyp_tag_internal(pb, s, has_h264 || has_h265, has_video, 0); > > // Write compatible brands, ensuring that we don't write the major brand as a > // compatible brand a second time. > @@ -5018,6 +5023,12 @@ static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s) > ffio_wfourcc(pb, "iso2"); > if (has_h264) > ffio_wfourcc(pb, "avc1"); > + if (has_h265){ Ditto > + if (h265_codec_tag == MKTAG('h','e','v','1')) > + ffio_wfourcc(pb, "hev1"); > + else > + ffio_wfourcc(pb, "hvc1"); > + } > } > } > > @@ -7103,6 +7114,8 @@ static int mov_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) > static const AVCodecTag codec_3gp_tags[] = { > { AV_CODEC_ID_H263, MKTAG('s','2','6','3') }, > { AV_CODEC_ID_H264, MKTAG('a','v','c','1') }, > + { AV_CODEC_ID_HEVC, MKTAG('h','e','v','1') }, > + { AV_CODEC_ID_HEVC, MKTAG('h','v','c','1') }, > { AV_CODEC_ID_MPEG4, MKTAG('m','p','4','v') }, > { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') }, > { AV_CODEC_ID_AMR_NB, MKTAG('s','a','m','r') }, > -- > 2.20.1 > > _______________________________________________ > 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". Other part lgtm. Thanks Steven Liu
On 11-12-2020 11:28 am, hisunzhenliang@outlook.com wrote: > From: SunZhenliang <hisunzhenliang@outlook.com> > > Just add HEVC's tag in 3gp tag list and it works to support HEVC in > 3gp files. > > Signed-off-by: SunZhenliang <hisunzhenliang@outlook.com> > --- > libavformat/movenc.c | 29 +++++++++++++++++++++-------- > 1 file changed, 21 insertions(+), 8 deletions(-) > > diff --git a/libavformat/movenc.c b/libavformat/movenc.c > index 18fa3f9b5e..daf33b634f 100644 > --- a/libavformat/movenc.c > +++ b/libavformat/movenc.c > @@ -4923,7 +4923,7 @@ static int mov_write_mdat_tag(AVIOContext *pb, MOVMuxContext *mov) > } > > static void mov_write_ftyp_tag_internal(AVIOContext *pb, AVFormatContext *s, > - int has_h264, int has_video, int write_minor) > + int has_h2645, int has_video, int write_minor) > { > MOVMuxContext *mov = s->priv_data; > int minor = 0x200; > @@ -4931,11 +4931,11 @@ static void mov_write_ftyp_tag_internal(AVIOContext *pb, AVFormatContext *s, > if (mov->major_brand && strlen(mov->major_brand) >= 4) > ffio_wfourcc(pb, mov->major_brand); > else if (mov->mode == MODE_3GP) { > - ffio_wfourcc(pb, has_h264 ? "3gp6" : "3gp4"); > - minor = has_h264 ? 0x100 : 0x200; > + ffio_wfourcc(pb, has_h2645 ? "3gp6" : "3gp4"); > + minor = has_h2645 ? 0x100 : 0x200; > } else if (mov->mode & MODE_3G2) { > - ffio_wfourcc(pb, has_h264 ? "3g2b" : "3g2a"); > - minor = has_h264 ? 0x20000 : 0x10000; > + ffio_wfourcc(pb, has_h2645 ? "3g2b" : "3g2a"); > + minor = has_h2645 ? 0x20000 : 0x10000; > } else if (mov->mode == MODE_PSP) > ffio_wfourcc(pb, "MSNV"); > else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_FRAGMENT && > @@ -4964,7 +4964,8 @@ static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s) > { > MOVMuxContext *mov = s->priv_data; > int64_t pos = avio_tell(pb); > - int has_h264 = 0, has_av1 = 0, has_video = 0; > + int has_h264 = 0, has_h265 = 0, has_av1 = 0, has_video = 0; > + uint32_t h265_codec_tag = 0; > int i; > > for (i = 0; i < s->nb_streams; i++) { > @@ -4975,6 +4976,10 @@ static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s) > has_video = 1; > if (st->codecpar->codec_id == AV_CODEC_ID_H264) > has_h264 = 1; > + if (st->codecpar->codec_id == AV_CODEC_ID_H265){ > + has_h265 = 1; > + h265_codec_tag = st->codecpar->codec_tag; > + } > if (st->codecpar->codec_id == AV_CODEC_ID_AV1) > has_av1 = 1; > } > @@ -4983,9 +4988,9 @@ static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s) > ffio_wfourcc(pb, "ftyp"); > > // Write major brand > - mov_write_ftyp_tag_internal(pb, s, has_h264, has_video, 1); > + mov_write_ftyp_tag_internal(pb, s, has_h264 || has_h265 , has_video, 1); > // Write the major brand as the first compatible brand as well > - mov_write_ftyp_tag_internal(pb, s, has_h264, has_video, 0); > + mov_write_ftyp_tag_internal(pb, s, has_h264 || has_h265, has_video, 0); > > // Write compatible brands, ensuring that we don't write the major brand as a > // compatible brand a second time. > @@ -5018,6 +5023,12 @@ static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s) > ffio_wfourcc(pb, "iso2"); > if (has_h264) > ffio_wfourcc(pb, "avc1"); > + if (has_h265){ > + if (h265_codec_tag == MKTAG('h','e','v','1')) > + ffio_wfourcc(pb, "hev1"); > + else > + ffio_wfourcc(pb, "hvc1"); > + } One final note: add a comment here that these major brands need to be verified. > } > } > > @@ -7103,6 +7114,8 @@ static int mov_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) > static const AVCodecTag codec_3gp_tags[] = { > { AV_CODEC_ID_H263, MKTAG('s','2','6','3') }, > { AV_CODEC_ID_H264, MKTAG('a','v','c','1') }, > + { AV_CODEC_ID_HEVC, MKTAG('h','e','v','1') }, > + { AV_CODEC_ID_HEVC, MKTAG('h','v','c','1') }, > { AV_CODEC_ID_MPEG4, MKTAG('m','p','4','v') }, > { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') }, > { AV_CODEC_ID_AMR_NB, MKTAG('s','a','m','r') }, Regards, Gyan
On Fri, Dec 11, 2020 at 11:51 AM Gyan Doshi <ffmpeg@gyani.pro> wrote: > > > > On 11-12-2020 11:28 am, hisunzhenliang@outlook.com wrote: > > From: SunZhenliang <hisunzhenliang@outlook.com> > > > > Just add HEVC's tag in 3gp tag list and it works to support HEVC in > > 3gp files. > > > > Signed-off-by: SunZhenliang <hisunzhenliang@outlook.com> > > --- > > libavformat/movenc.c | 29 +++++++++++++++++++++-------- > > 1 file changed, 21 insertions(+), 8 deletions(-) > > > > diff --git a/libavformat/movenc.c b/libavformat/movenc.c > > index 18fa3f9b5e..daf33b634f 100644 > > --- a/libavformat/movenc.c > > +++ b/libavformat/movenc.c > > @@ -4923,7 +4923,7 @@ static int mov_write_mdat_tag(AVIOContext *pb, MOVMuxContext *mov) > > } > > > > static void mov_write_ftyp_tag_internal(AVIOContext *pb, AVFormatContext *s, > > - int has_h264, int has_video, int write_minor) > > + int has_h2645, int has_video, int write_minor) > > { > > MOVMuxContext *mov = s->priv_data; > > int minor = 0x200; > > @@ -4931,11 +4931,11 @@ static void mov_write_ftyp_tag_internal(AVIOContext *pb, AVFormatContext *s, > > if (mov->major_brand && strlen(mov->major_brand) >= 4) > > ffio_wfourcc(pb, mov->major_brand); > > else if (mov->mode == MODE_3GP) { > > - ffio_wfourcc(pb, has_h264 ? "3gp6" : "3gp4"); > > - minor = has_h264 ? 0x100 : 0x200; > > + ffio_wfourcc(pb, has_h2645 ? "3gp6" : "3gp4"); > > + minor = has_h2645 ? 0x100 : 0x200; > > } else if (mov->mode & MODE_3G2) { > > - ffio_wfourcc(pb, has_h264 ? "3g2b" : "3g2a"); > > - minor = has_h264 ? 0x20000 : 0x10000; > > + ffio_wfourcc(pb, has_h2645 ? "3g2b" : "3g2a"); > > + minor = has_h2645 ? 0x20000 : 0x10000; > > } else if (mov->mode == MODE_PSP) > > ffio_wfourcc(pb, "MSNV"); > > else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_FRAGMENT && > > @@ -4964,7 +4964,8 @@ static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s) > > { > > MOVMuxContext *mov = s->priv_data; > > int64_t pos = avio_tell(pb); > > - int has_h264 = 0, has_av1 = 0, has_video = 0; > > + int has_h264 = 0, has_h265 = 0, has_av1 = 0, has_video = 0; > > + uint32_t h265_codec_tag = 0; > > int i; > > > > for (i = 0; i < s->nb_streams; i++) { > > @@ -4975,6 +4976,10 @@ static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s) > > has_video = 1; > > if (st->codecpar->codec_id == AV_CODEC_ID_H264) > > has_h264 = 1; > > + if (st->codecpar->codec_id == AV_CODEC_ID_H265){ > > + has_h265 = 1; > > + h265_codec_tag = st->codecpar->codec_tag; > > + } > > if (st->codecpar->codec_id == AV_CODEC_ID_AV1) > > has_av1 = 1; > > } > > @@ -4983,9 +4988,9 @@ static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s) > > ffio_wfourcc(pb, "ftyp"); > > > > // Write major brand > > - mov_write_ftyp_tag_internal(pb, s, has_h264, has_video, 1); > > + mov_write_ftyp_tag_internal(pb, s, has_h264 || has_h265 , has_video, 1); > > // Write the major brand as the first compatible brand as well > > - mov_write_ftyp_tag_internal(pb, s, has_h264, has_video, 0); > > + mov_write_ftyp_tag_internal(pb, s, has_h264 || has_h265, has_video, 0); > > > > // Write compatible brands, ensuring that we don't write the major brand as a > > // compatible brand a second time. > > @@ -5018,6 +5023,12 @@ static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s) > > ffio_wfourcc(pb, "iso2"); > > if (has_h264) > > ffio_wfourcc(pb, "avc1"); > > + if (has_h265){ > > + if (h265_codec_tag == MKTAG('h','e','v','1')) > > + ffio_wfourcc(pb, "hev1"); > > + else > > + ffio_wfourcc(pb, "hvc1"); > > + } > > One final note: add a comment here that these major brands need to be > verified. > I have the 2016 version of 14496-15 (FDIS with HEVC added) on hand, and it only speaks of the AVC file format, not HEVC file format. And for AVC it only mentions avc1, so if similar logic is required for brands: 1. It'd be separate from the 3GPP enablement patch, since it'd be fixing our HEVC mappings in general (if the brand is required, it's required for all mp4-likes, although technically the spec does say "AVC content may be used in an MPEG-4 context; in a file with extension “.mp4”, the major brand may be ‘avc1’."). 2. But - at least looking at the 14496-15 document available to me - there is no definition of a major brand for HEVC since "8.4.1 HEVC video stream definition" does not make any mention of it. Although this might just be an old version of the spec, unfortunately newer versions are not publicly available. Jan
I think there two files: 3GPP TS 26.244 V16.1.0 (2020-09) and ISO/IEC 14496-15 2019: "Information technology – Coding of audio-visual objects – Part 15: Carriage of NAL unit structured video in the ISO base media file format" states the major brands of HEVC. https://www.etsi.org/deliver/etsi_ts/126200_126299/126244/16.01.00_60/ts_126244v160100p.pdf Regards, SunZhenliang
On Fri, Dec 11, 2020 at 3:27 PM Sun Zhenliang <hisunzhenliang@outlook.com> wrote: > > I think there two files: 3GPP TS 26.244 V16.1.0 (2020-09) > and ISO/IEC 14496-15 2019: "Information technology – Coding > of audio-visual objects – Part 15: Carriage of NAL unit structured > video in the ISO base media file format" states the major brands of HEVC. > > > https://www.etsi.org/deliver/etsi_ts/126200_126299/126244/16.01.00_60/ts_126244v160100p.pdf > > Regards, > SunZhenliang > Yes, I have now found a January, 2019 draft of 14496-15 and its area around the HEVC bits is (mostly) the same. In other words, while I can find the reference towards AVC file format's brands, I cannot find such for HEVC. Also if you look at the MP4 registration authority, they actually don't have hev1 or hvc1 as registered brands. Can you please point towards the chapter number in 14496-15 where the HEVC brands are defined? Jan
In 14496-15 2019 5.4.1"AVC file type and identification" and 8.4"HEVC video stream definition" , I think the Entry Box types 'hvc1' 'hev1',could be considered as brands of HEVC. I just think AVC uses its Entry as major brand, maybe it works same to HEVC. Regards, SunZhenliang
diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 18fa3f9b5e..daf33b634f 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -4923,7 +4923,7 @@ static int mov_write_mdat_tag(AVIOContext *pb, MOVMuxContext *mov) } static void mov_write_ftyp_tag_internal(AVIOContext *pb, AVFormatContext *s, - int has_h264, int has_video, int write_minor) + int has_h2645, int has_video, int write_minor) { MOVMuxContext *mov = s->priv_data; int minor = 0x200; @@ -4931,11 +4931,11 @@ static void mov_write_ftyp_tag_internal(AVIOContext *pb, AVFormatContext *s, if (mov->major_brand && strlen(mov->major_brand) >= 4) ffio_wfourcc(pb, mov->major_brand); else if (mov->mode == MODE_3GP) { - ffio_wfourcc(pb, has_h264 ? "3gp6" : "3gp4"); - minor = has_h264 ? 0x100 : 0x200; + ffio_wfourcc(pb, has_h2645 ? "3gp6" : "3gp4"); + minor = has_h2645 ? 0x100 : 0x200; } else if (mov->mode & MODE_3G2) { - ffio_wfourcc(pb, has_h264 ? "3g2b" : "3g2a"); - minor = has_h264 ? 0x20000 : 0x10000; + ffio_wfourcc(pb, has_h2645 ? "3g2b" : "3g2a"); + minor = has_h2645 ? 0x20000 : 0x10000; } else if (mov->mode == MODE_PSP) ffio_wfourcc(pb, "MSNV"); else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_FRAGMENT && @@ -4964,7 +4964,8 @@ static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s) { MOVMuxContext *mov = s->priv_data; int64_t pos = avio_tell(pb); - int has_h264 = 0, has_av1 = 0, has_video = 0; + int has_h264 = 0, has_h265 = 0, has_av1 = 0, has_video = 0; + uint32_t h265_codec_tag = 0; int i; for (i = 0; i < s->nb_streams; i++) { @@ -4975,6 +4976,10 @@ static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s) has_video = 1; if (st->codecpar->codec_id == AV_CODEC_ID_H264) has_h264 = 1; + if (st->codecpar->codec_id == AV_CODEC_ID_H265){ + has_h265 = 1; + h265_codec_tag = st->codecpar->codec_tag; + } if (st->codecpar->codec_id == AV_CODEC_ID_AV1) has_av1 = 1; } @@ -4983,9 +4988,9 @@ static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s) ffio_wfourcc(pb, "ftyp"); // Write major brand - mov_write_ftyp_tag_internal(pb, s, has_h264, has_video, 1); + mov_write_ftyp_tag_internal(pb, s, has_h264 || has_h265 , has_video, 1); // Write the major brand as the first compatible brand as well - mov_write_ftyp_tag_internal(pb, s, has_h264, has_video, 0); + mov_write_ftyp_tag_internal(pb, s, has_h264 || has_h265, has_video, 0); // Write compatible brands, ensuring that we don't write the major brand as a // compatible brand a second time. @@ -5018,6 +5023,12 @@ static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s) ffio_wfourcc(pb, "iso2"); if (has_h264) ffio_wfourcc(pb, "avc1"); + if (has_h265){ + if (h265_codec_tag == MKTAG('h','e','v','1')) + ffio_wfourcc(pb, "hev1"); + else + ffio_wfourcc(pb, "hvc1"); + } } } @@ -7103,6 +7114,8 @@ static int mov_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) static const AVCodecTag codec_3gp_tags[] = { { AV_CODEC_ID_H263, MKTAG('s','2','6','3') }, { AV_CODEC_ID_H264, MKTAG('a','v','c','1') }, + { AV_CODEC_ID_HEVC, MKTAG('h','e','v','1') }, + { AV_CODEC_ID_HEVC, MKTAG('h','v','c','1') }, { AV_CODEC_ID_MPEG4, MKTAG('m','p','4','v') }, { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') }, { AV_CODEC_ID_AMR_NB, MKTAG('s','a','m','r') },