diff mbox series

[FFmpeg-devel] avcodec/videotoolboxenc: ignore encoded h264 SEI nalu by default

Message ID 20210215093304.33955-1-sharpbai@gmail.com
State New
Headers show
Series [FFmpeg-devel] avcodec/videotoolboxenc: ignore encoded h264 SEI nalu by default | expand

Checks

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

Commit Message

sharpbai Feb. 15, 2021, 9:33 a.m. UTC
Before macOS 11, the encoded h264 sample contains fixed SEI before
IDR frame, which the content is below

06 05 10 b9 ed b9 30 5d 21 4b 71 83 71 2c 10 a3
14 bb 29 80

The length of the encoded SEI nalu is 20 byte. According to
the ITU-T H.264 Recommendation section 7.3.2.3.1, the last byte
0x80 means type. Then there is no length byte, which make the
SEI nonstandard.

On macOS 11, the encoded h264 sample still contains fixed SEI before
IDR frame, which length is 5 bytes longer than before.

06 05 10 b9 ed b9 30 5d 21 4b 71 83 71 2c 10 a3
14 bb 29 80 00 00 03 00 01
            ^^ ^^ ^^ ^^ ^^

This time type the content of the SEI has type 0 payload but
invalid length payload data, which violates recommendation
appendix D.

Whether it is a bug or not, these SEI nalus should be erased to keep
the output bytestream not violating the standard. But we may
not come across the situration we do need these encoded SEI
nalu, so we just reserve a switch and set not to output by default.

Signed-off-by: sharpbai <sharpbai@gmail.com>
---
 libavcodec/videotoolboxenc.c | 51 +++++++++++++++++++++---------------
 1 file changed, 30 insertions(+), 21 deletions(-)

Comments

Andreas Rheinhardt Feb. 15, 2021, 12:51 p.m. UTC | #1
sharpbai:
> Before macOS 11, the encoded h264 sample contains fixed SEI before
> IDR frame, which the content is below
> 
> 06 05 10 b9 ed b9 30 5d 21 4b 71 83 71 2c 10 a3
> 14 bb 29 80
> 
> The length of the encoded SEI nalu is 20 byte. According to
> the ITU-T H.264 Recommendation section 7.3.2.3.1, the last byte
> 0x80 means type. Then there is no length byte, which make the
> SEI nonstandard.
> 
Wrong:
06: forbidden_zero_bit + nal_ref_idc + nal_unit_type (6 for SEI)
05: payload type 5 (user data unregistered) SEI message
10: length of this SEI message is 16
b9-29: the payload of this SEI message (the first 12 byte are an uuid,
the last are user_data_payload_byte)
80: rbsp_trailing_bits: the first bit is rbsp_stop_one_bit (equal to
one), the remaining bits are padding (with value zero)

You can use trace_headers to inspect this.

(Notice that one needs to know the length of the NAL unit in advance
before one can start parsing it; how one gets it depends upon the
framing. There are two common methods for this: Annex B and mp4. The
former works by using start codes 0x00 00 01 to mark the beginning of a
new NAL, the latter prefixes the length of the NAL units to the units.)

> On macOS 11, the encoded h264 sample still contains fixed SEI before
> IDR frame, which length is 5 bytes longer than before.
> 
> 06 05 10 b9 ed b9 30 5d 21 4b 71 83 71 2c 10 a3
> 14 bb 29 80 00 00 03 00 01
>             ^^ ^^ ^^ ^^ ^^

That looks as if there were a 00 00 00 01 startcode after the SEI that
some tool has tried to 0x03 escape. That is a bug. Can you share samples
containing these NAL units?

> 
> This time type the content of the SEI has type 0 payload but
> invalid length payload data, which violates recommendation
> appendix D.
> 
> Whether it is a bug or not, these SEI nalus should be erased to keep
> the output bytestream not violating the standard. But we may
> not come across the situration we do need these encoded SEI
> nalu, so we just reserve a switch and set not to output by default.
> 
> Signed-off-by: sharpbai <sharpbai@gmail.com>
> ---
>  libavcodec/videotoolboxenc.c | 51 +++++++++++++++++++++---------------
>  1 file changed, 30 insertions(+), 21 deletions(-)
> 
> diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c
> index cc08cf6a50..c240090f10 100644
> --- a/libavcodec/videotoolboxenc.c
> +++ b/libavcodec/videotoolboxenc.c
> @@ -221,6 +221,7 @@ typedef struct VTEncContext {
>  
>      int64_t allow_sw;
>      int64_t require_sw;
> +    int64_t ignore_internal_sei;
>  
>      bool flushing;
>      bool has_b_frames;
> @@ -1690,7 +1691,8 @@ static int copy_replace_length_codes(
>      CMSampleBufferRef sample_buffer,
>      ExtraSEI      *sei,
>      uint8_t       *dst_data,
> -    size_t        dst_size)
> +    size_t        dst_size,
> +    int           ignore_internal_sei)
>  {
>      size_t src_size = CMSampleBufferGetTotalSampleSize(sample_buffer);
>      size_t remaining_src_size = src_size;
> @@ -1707,8 +1709,8 @@ static int copy_replace_length_codes(
>      }
>  
>      while (remaining_src_size > 0) {
> -        size_t curr_src_len;
> -        size_t curr_dst_len;
> +        size_t curr_src_len = 0;
> +        size_t curr_dst_len = 0;
>          size_t box_len = 0;
>          size_t i;
>  
> @@ -1740,7 +1742,8 @@ static int copy_replace_length_codes(
>              box_len |= size_buf[i];
>          }
>  
> -        if (sei && !wrote_sei && is_post_sei_nal_type(nal_type)) {
> +        if (sei && !wrote_sei &&
> +                (ignore_internal_sei || is_post_sei_nal_type(nal_type))) {
>              //No SEI NAL unit - insert.
>              int wrote_bytes;
>  
> @@ -1775,27 +1778,30 @@ static int copy_replace_length_codes(
>          }
>  
>          curr_src_len = box_len + length_code_size;
> -        curr_dst_len = box_len + sizeof(start_code);
>  
> -        if (remaining_src_size < curr_src_len) {
> -            return AVERROR_BUFFER_TOO_SMALL;
> -        }
> +        if (!(ignore_internal_sei && nal_type == H264_NAL_SEI)) {
> +            curr_dst_len = box_len + sizeof(start_code);
>  
> -        if (remaining_dst_size < curr_dst_len) {
> -            return AVERROR_BUFFER_TOO_SMALL;
> -        }
> +            if (remaining_src_size < curr_src_len) {
> +                return AVERROR_BUFFER_TOO_SMALL;
> +            }
> +
> +            if (remaining_dst_size < curr_dst_len) {
> +                return AVERROR_BUFFER_TOO_SMALL;
> +            }
>  
> -        dst_box = dst_data + sizeof(start_code);
> +            dst_box = dst_data + sizeof(start_code);
>  
> -        memcpy(dst_data, start_code, sizeof(start_code));
> -        status = CMBlockBufferCopyDataBytes(block,
> -                                            src_offset + length_code_size,
> -                                            box_len,
> -                                            dst_box);
> +            memcpy(dst_data, start_code, sizeof(start_code));
> +            status = CMBlockBufferCopyDataBytes(block,
> +                                                src_offset + length_code_size,
> +                                                box_len,
> +                                                dst_box);
>  
> -        if (status) {
> -            av_log(avctx, AV_LOG_ERROR, "Cannot copy data: %d\n", status);
> -            return AVERROR_EXTERNAL;
> +            if (status) {
> +                av_log(avctx, AV_LOG_ERROR, "Cannot copy data: %d\n", status);
> +                return AVERROR_EXTERNAL;
> +            }
>          }
>  
>          if (sei && !wrote_sei && nal_type == H264_NAL_SEI) {
> @@ -1931,7 +1937,8 @@ static int vtenc_cm_to_avpacket(
>          sample_buffer,
>          sei,
>          pkt->data + header_size,
> -        pkt->size - header_size
> +        pkt->size - header_size,
> +        vtctx->ignore_internal_sei
>      );
>  
>      if (status) {
> @@ -2543,6 +2550,8 @@ static const enum AVPixelFormat hevc_pix_fmts[] = {
>          { .i64 = 0 }, 0, 1, VE }, \
>      { "require_sw", "Require software encoding", OFFSET(require_sw), AV_OPT_TYPE_BOOL, \
>          { .i64 = 0 }, 0, 1, VE }, \
> +    { "ignore_internal_sei", "Ignore SEI nalu generated by videotoolbox", OFFSET(ignore_internal_sei), AV_OPT_TYPE_BOOL, \
> +        { .i64 = 1 }, 0, 1, VE }, \
>      { "realtime", "Hint that encoding should happen in real-time if not faster (e.g. capturing from camera).", \
>          OFFSET(realtime), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, \
>      { "frames_before", "Other frames will come before the frames in this session. This helps smooth concatenation issues.", \
>
Rick Kern Feb. 15, 2021, 4:23 p.m. UTC | #2
On Mon, Feb 15, 2021 at 7:51 AM Andreas Rheinhardt <
andreas.rheinhardt@gmail.com> wrote:

> sharpbai:
> > Before macOS 11, the encoded h264 sample contains fixed SEI before
> > IDR frame, which the content is below
> >
> > 06 05 10 b9 ed b9 30 5d 21 4b 71 83 71 2c 10 a3
> > 14 bb 29 80
> >
> > The length of the encoded SEI nalu is 20 byte. According to
> > the ITU-T H.264 Recommendation section 7.3.2.3.1, the last byte
> > 0x80 means type. Then there is no length byte, which make the
> > SEI nonstandard.
> >
> Wrong:
> 06: forbidden_zero_bit + nal_ref_idc + nal_unit_type (6 for SEI)
> 05: payload type 5 (user data unregistered) SEI message
> 10: length of this SEI message is 16
> b9-29: the payload of this SEI message (the first 12 byte are an uuid,
> the last are user_data_payload_byte)
> 80: rbsp_trailing_bits: the first bit is rbsp_stop_one_bit (equal to
> one), the remaining bits are padding (with value zero)
>
> You can use trace_headers to inspect this.
>
> (Notice that one needs to know the length of the NAL unit in advance
> before one can start parsing it; how one gets it depends upon the
> framing. There are two common methods for this: Annex B and mp4. The
> former works by using start codes 0x00 00 01 to mark the beginning of a
> new NAL, the latter prefixes the length of the NAL units to the units.)
>
> > On macOS 11, the encoded h264 sample still contains fixed SEI before
> > IDR frame, which length is 5 bytes longer than before.
> >
> > 06 05 10 b9 ed b9 30 5d 21 4b 71 83 71 2c 10 a3
> > 14 bb 29 80 00 00 03 00 01
> >             ^^ ^^ ^^ ^^ ^^
>
> That looks as if there were a 00 00 00 01 startcode after the SEI that
> some tool has tried to 0x03 escape. That is a bug. Can you share samples
> containing these NAL units?
>
This file is inserting the emulation prevention byte 0x03. I can take a
look later today.


> >
> > This time type the content of the SEI has type 0 payload but
> > invalid length payload data, which violates recommendation
> > appendix D.
> >
> > Whether it is a bug or not, these SEI nalus should be erased to keep
> > the output bytestream not violating the standard. But we may
> > not come across the situration we do need these encoded SEI
> > nalu, so we just reserve a switch and set not to output by default.
> >
> > Signed-off-by: sharpbai <sharpbai@gmail.com>
> > ---
> >  libavcodec/videotoolboxenc.c | 51 +++++++++++++++++++++---------------
> >  1 file changed, 30 insertions(+), 21 deletions(-)
> >
> > diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c
> > index cc08cf6a50..c240090f10 100644
> > --- a/libavcodec/videotoolboxenc.c
> > +++ b/libavcodec/videotoolboxenc.c
> > @@ -221,6 +221,7 @@ typedef struct VTEncContext {
> >
> >      int64_t allow_sw;
> >      int64_t require_sw;
> > +    int64_t ignore_internal_sei;
> >
> >      bool flushing;
> >      bool has_b_frames;
> > @@ -1690,7 +1691,8 @@ static int copy_replace_length_codes(
> >      CMSampleBufferRef sample_buffer,
> >      ExtraSEI      *sei,
> >      uint8_t       *dst_data,
> > -    size_t        dst_size)
> > +    size_t        dst_size,
> > +    int           ignore_internal_sei)
> >  {
> >      size_t src_size = CMSampleBufferGetTotalSampleSize(sample_buffer);
> >      size_t remaining_src_size = src_size;
> > @@ -1707,8 +1709,8 @@ static int copy_replace_length_codes(
> >      }
> >
> >      while (remaining_src_size > 0) {
> > -        size_t curr_src_len;
> > -        size_t curr_dst_len;
> > +        size_t curr_src_len = 0;
> > +        size_t curr_dst_len = 0;
> >          size_t box_len = 0;
> >          size_t i;
> >
> > @@ -1740,7 +1742,8 @@ static int copy_replace_length_codes(
> >              box_len |= size_buf[i];
> >          }
> >
> > -        if (sei && !wrote_sei && is_post_sei_nal_type(nal_type)) {
> > +        if (sei && !wrote_sei &&
> > +                (ignore_internal_sei ||
> is_post_sei_nal_type(nal_type))) {
> >              //No SEI NAL unit - insert.
> >              int wrote_bytes;
> >
> > @@ -1775,27 +1778,30 @@ static int copy_replace_length_codes(
> >          }
> >
> >          curr_src_len = box_len + length_code_size;
> > -        curr_dst_len = box_len + sizeof(start_code);
> >
> > -        if (remaining_src_size < curr_src_len) {
> > -            return AVERROR_BUFFER_TOO_SMALL;
> > -        }
> > +        if (!(ignore_internal_sei && nal_type == H264_NAL_SEI)) {
> > +            curr_dst_len = box_len + sizeof(start_code);
> >
> > -        if (remaining_dst_size < curr_dst_len) {
> > -            return AVERROR_BUFFER_TOO_SMALL;
> > -        }
> > +            if (remaining_src_size < curr_src_len) {
> > +                return AVERROR_BUFFER_TOO_SMALL;
> > +            }
> > +
> > +            if (remaining_dst_size < curr_dst_len) {
> > +                return AVERROR_BUFFER_TOO_SMALL;
> > +            }
> >
> > -        dst_box = dst_data + sizeof(start_code);
> > +            dst_box = dst_data + sizeof(start_code);
> >
> > -        memcpy(dst_data, start_code, sizeof(start_code));
> > -        status = CMBlockBufferCopyDataBytes(block,
> > -                                            src_offset +
> length_code_size,
> > -                                            box_len,
> > -                                            dst_box);
> > +            memcpy(dst_data, start_code, sizeof(start_code));
> > +            status = CMBlockBufferCopyDataBytes(block,
> > +                                                src_offset +
> length_code_size,
> > +                                                box_len,
> > +                                                dst_box);
> >
> > -        if (status) {
> > -            av_log(avctx, AV_LOG_ERROR, "Cannot copy data: %d\n",
> status);
> > -            return AVERROR_EXTERNAL;
> > +            if (status) {
> > +                av_log(avctx, AV_LOG_ERROR, "Cannot copy data: %d\n",
> status);
> > +                return AVERROR_EXTERNAL;
> > +            }
> >          }
> >
> >          if (sei && !wrote_sei && nal_type == H264_NAL_SEI) {
> > @@ -1931,7 +1937,8 @@ static int vtenc_cm_to_avpacket(
> >          sample_buffer,
> >          sei,
> >          pkt->data + header_size,
> > -        pkt->size - header_size
> > +        pkt->size - header_size,
> > +        vtctx->ignore_internal_sei
> >      );
> >
> >      if (status) {
> > @@ -2543,6 +2550,8 @@ static const enum AVPixelFormat hevc_pix_fmts[] = {
> >          { .i64 = 0 }, 0, 1, VE }, \
> >      { "require_sw", "Require software encoding", OFFSET(require_sw),
> AV_OPT_TYPE_BOOL, \
> >          { .i64 = 0 }, 0, 1, VE }, \
> > +    { "ignore_internal_sei", "Ignore SEI nalu generated by
> videotoolbox", OFFSET(ignore_internal_sei), AV_OPT_TYPE_BOOL, \
> > +        { .i64 = 1 }, 0, 1, VE }, \
> >      { "realtime", "Hint that encoding should happen in real-time if not
> faster (e.g. capturing from camera).", \
> >          OFFSET(realtime), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, \
> >      { "frames_before", "Other frames will come before the frames in
> this session. This helps smooth concatenation issues.", \
> >
>
> _______________________________________________
> 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".
sharpbai Feb. 18, 2021, 10:09 p.m. UTC | #3
To Andreas Rheinhardt,

You are right. The last byte 0x80 is rbsp_trailing_bits.
Before macOS 11 there is no problem of the generated SEI.

To Rick Kern,

After macOS 11, the encoded SEI nalu length changes from 20
to 25, the following code should help you to confirm it.

Place these code to copy_replace_length_codes function,
after CMBlockBufferCopyDataBytes calling copy nalu data. 

```
            if (nal_type == 6) {
                char buf[1024] = {0};
                int index = 0;
                for(int i = 0; i < box_len; i++) {
                    index += sprintf(buf + index, "%.2x ", dst_box[i]);
                }
                av_log(avctx, AV_LOG_DEBUG, "Found sei nalu length: %zu value: %s\n", box_len, buf);
            } else {
                av_log(avctx, AV_LOG_DEBUG, "Found type %d nalu length: %zu\n", nal_type, box_len);
            }
```

For example run this ffmpeg command

$ ffmpeg -f lavfi -i testsrc=d=5:s=1920x1080:r=24,format=yuv420p \
-ignore_internal_sei 0 -vcodec h264_videotoolbox -b:v 40m -y bar.h264

got a output like this

[h264_videotoolbox @ 0x7fa30d00ca00] Found sei nalu length: 25 value: 06 05 10 b9 ed b9 30 5d 21 4b 71 83 71 2c 10 a3 14 bb 29 80 00 00 03 00 01
[h264_videotoolbox @ 0x7fa30d00ca00] Found type 5 nalu length: 135751

This proves that the last 5 bytes are added by videotoolboxenc.  


February 16, 2021 12:23 AM, "Rick Kern" <kernrj@gmail.com> 写到:

> On Mon, Feb 15, 2021 at 7:51 AM Andreas Rheinhardt <
> andreas.rheinhardt@gmail.com> wrote:
> 
>> sharpbai:
>> Before macOS 11, the encoded h264 sample contains fixed SEI before
>> IDR frame, which the content is below
>> 
>> 06 05 10 b9 ed b9 30 5d 21 4b 71 83 71 2c 10 a3
>> 14 bb 29 80
>> 
>> The length of the encoded SEI nalu is 20 byte. According to
>> the ITU-T H.264 Recommendation section 7.3.2.3.1, the last byte
>> 0x80 means type. Then there is no length byte, which make the
>> SEI nonstandard.
>> 
>> Wrong:
>> 06: forbidden_zero_bit + nal_ref_idc + nal_unit_type (6 for SEI)
>> 05: payload type 5 (user data unregistered) SEI message
>> 10: length of this SEI message is 16
>> b9-29: the payload of this SEI message (the first 12 byte are an uuid,
>> the last are user_data_payload_byte)
>> 80: rbsp_trailing_bits: the first bit is rbsp_stop_one_bit (equal to
>> one), the remaining bits are padding (with value zero)
>> 
>> You can use trace_headers to inspect this.
>> 
>> (Notice that one needs to know the length of the NAL unit in advance
>> before one can start parsing it; how one gets it depends upon the
>> framing. There are two common methods for this: Annex B and mp4. The
>> former works by using start codes 0x00 00 01 to mark the beginning of a
>> new NAL, the latter prefixes the length of the NAL units to the units.)
>> 
>> On macOS 11, the encoded h264 sample still contains fixed SEI before
>> IDR frame, which length is 5 bytes longer than before.
>> 
>> 06 05 10 b9 ed b9 30 5d 21 4b 71 83 71 2c 10 a3
>> 14 bb 29 80 00 00 03 00 01
>> ^^ ^^ ^^ ^^ ^^
>> 
>> That looks as if there were a 00 00 00 01 startcode after the SEI that
>> some tool has tried to 0x03 escape. That is a bug. Can you share samples
>> containing these NAL units?
> 
> This file is inserting the emulation prevention byte 0x03. I can take a
> look later today.
> 
>> This time type the content of the SEI has type 0 payload but
>> invalid length payload data, which violates recommendation
>> appendix D.
>> 
>> Whether it is a bug or not, these SEI nalus should be erased to keep
>> the output bytestream not violating the standard. But we may
>> not come across the situration we do need these encoded SEI
>> nalu, so we just reserve a switch and set not to output by default.
>> 
>> Signed-off-by: sharpbai <sharpbai@gmail.com>
>> ---
>> libavcodec/videotoolboxenc.c | 51 +++++++++++++++++++++---------------
>> 1 file changed, 30 insertions(+), 21 deletions(-)
>> 
>> diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c
>> index cc08cf6a50..c240090f10 100644
>> --- a/libavcodec/videotoolboxenc.c
>> +++ b/libavcodec/videotoolboxenc.c
>> @@ -221,6 +221,7 @@ typedef struct VTEncContext {
>> 
>> int64_t allow_sw;
>> int64_t require_sw;
>> + int64_t ignore_internal_sei;
>> 
>> bool flushing;
>> bool has_b_frames;
>> @@ -1690,7 +1691,8 @@ static int copy_replace_length_codes(
>> CMSampleBufferRef sample_buffer,
>> ExtraSEI *sei,
>> uint8_t *dst_data,
>> - size_t dst_size)
>> + size_t dst_size,
>> + int ignore_internal_sei)
>> {
>> size_t src_size = CMSampleBufferGetTotalSampleSize(sample_buffer);
>> size_t remaining_src_size = src_size;
>> @@ -1707,8 +1709,8 @@ static int copy_replace_length_codes(
>> }
>> 
>> while (remaining_src_size > 0) {
>> - size_t curr_src_len;
>> - size_t curr_dst_len;
>> + size_t curr_src_len = 0;
>> + size_t curr_dst_len = 0;
>> size_t box_len = 0;
>> size_t i;
>> 
>> @@ -1740,7 +1742,8 @@ static int copy_replace_length_codes(
>> box_len |= size_buf[i];
>> }
>> 
>> - if (sei && !wrote_sei && is_post_sei_nal_type(nal_type)) {
>> + if (sei && !wrote_sei &&
>> + (ignore_internal_sei ||
>> is_post_sei_nal_type(nal_type))) {
>> //No SEI NAL unit - insert.
>> int wrote_bytes;
>> 
>> @@ -1775,27 +1778,30 @@ static int copy_replace_length_codes(
>> }
>> 
>> curr_src_len = box_len + length_code_size;
>> - curr_dst_len = box_len + sizeof(start_code);
>> 
>> - if (remaining_src_size < curr_src_len) {
>> - return AVERROR_BUFFER_TOO_SMALL;
>> - }
>> + if (!(ignore_internal_sei && nal_type == H264_NAL_SEI)) {
>> + curr_dst_len = box_len + sizeof(start_code);
>> 
>> - if (remaining_dst_size < curr_dst_len) {
>> - return AVERROR_BUFFER_TOO_SMALL;
>> - }
>> + if (remaining_src_size < curr_src_len) {
>> + return AVERROR_BUFFER_TOO_SMALL;
>> + }
>> +
>> + if (remaining_dst_size < curr_dst_len) {
>> + return AVERROR_BUFFER_TOO_SMALL;
>> + }
>> 
>> - dst_box = dst_data + sizeof(start_code);
>> + dst_box = dst_data + sizeof(start_code);
>> 
>> - memcpy(dst_data, start_code, sizeof(start_code));
>> - status = CMBlockBufferCopyDataBytes(block,
>> - src_offset +
>> length_code_size,
>> - box_len,
>> - dst_box);
>> + memcpy(dst_data, start_code, sizeof(start_code));
>> + status = CMBlockBufferCopyDataBytes(block,
>> + src_offset +
>> length_code_size,
>> + box_len,
>> + dst_box);
>> 
>> - if (status) {
>> - av_log(avctx, AV_LOG_ERROR, "Cannot copy data: %d\n",
>> status);
>> - return AVERROR_EXTERNAL;
>> + if (status) {
>> + av_log(avctx, AV_LOG_ERROR, "Cannot copy data: %d\n",
>> status);
>> + return AVERROR_EXTERNAL;
>> + }
>> }
>> 
>> if (sei && !wrote_sei && nal_type == H264_NAL_SEI) {
>> @@ -1931,7 +1937,8 @@ static int vtenc_cm_to_avpacket(
>> sample_buffer,
>> sei,
>> pkt->data + header_size,
>> - pkt->size - header_size
>> + pkt->size - header_size,
>> + vtctx->ignore_internal_sei
>> );
>> 
>> if (status) {
>> @@ -2543,6 +2550,8 @@ static const enum AVPixelFormat hevc_pix_fmts[] = {
>> { .i64 = 0 }, 0, 1, VE }, \
>> { "require_sw", "Require software encoding", OFFSET(require_sw),
>> AV_OPT_TYPE_BOOL, \
>> { .i64 = 0 }, 0, 1, VE }, \
>> + { "ignore_internal_sei", "Ignore SEI nalu generated by
>> videotoolbox", OFFSET(ignore_internal_sei), AV_OPT_TYPE_BOOL, \
>> + { .i64 = 1 }, 0, 1, VE }, \
>> { "realtime", "Hint that encoding should happen in real-time if not
>> faster (e.g. capturing from camera).", \
>> OFFSET(realtime), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, \
>> { "frames_before", "Other frames will come before the frames in
>> this session. This helps smooth concatenation issues.", \
>> 
>> _______________________________________________
>> 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".
> 
> _______________________________________________
> 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".
diff mbox series

Patch

diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c
index cc08cf6a50..c240090f10 100644
--- a/libavcodec/videotoolboxenc.c
+++ b/libavcodec/videotoolboxenc.c
@@ -221,6 +221,7 @@  typedef struct VTEncContext {
 
     int64_t allow_sw;
     int64_t require_sw;
+    int64_t ignore_internal_sei;
 
     bool flushing;
     bool has_b_frames;
@@ -1690,7 +1691,8 @@  static int copy_replace_length_codes(
     CMSampleBufferRef sample_buffer,
     ExtraSEI      *sei,
     uint8_t       *dst_data,
-    size_t        dst_size)
+    size_t        dst_size,
+    int           ignore_internal_sei)
 {
     size_t src_size = CMSampleBufferGetTotalSampleSize(sample_buffer);
     size_t remaining_src_size = src_size;
@@ -1707,8 +1709,8 @@  static int copy_replace_length_codes(
     }
 
     while (remaining_src_size > 0) {
-        size_t curr_src_len;
-        size_t curr_dst_len;
+        size_t curr_src_len = 0;
+        size_t curr_dst_len = 0;
         size_t box_len = 0;
         size_t i;
 
@@ -1740,7 +1742,8 @@  static int copy_replace_length_codes(
             box_len |= size_buf[i];
         }
 
-        if (sei && !wrote_sei && is_post_sei_nal_type(nal_type)) {
+        if (sei && !wrote_sei &&
+                (ignore_internal_sei || is_post_sei_nal_type(nal_type))) {
             //No SEI NAL unit - insert.
             int wrote_bytes;
 
@@ -1775,27 +1778,30 @@  static int copy_replace_length_codes(
         }
 
         curr_src_len = box_len + length_code_size;
-        curr_dst_len = box_len + sizeof(start_code);
 
-        if (remaining_src_size < curr_src_len) {
-            return AVERROR_BUFFER_TOO_SMALL;
-        }
+        if (!(ignore_internal_sei && nal_type == H264_NAL_SEI)) {
+            curr_dst_len = box_len + sizeof(start_code);
 
-        if (remaining_dst_size < curr_dst_len) {
-            return AVERROR_BUFFER_TOO_SMALL;
-        }
+            if (remaining_src_size < curr_src_len) {
+                return AVERROR_BUFFER_TOO_SMALL;
+            }
+
+            if (remaining_dst_size < curr_dst_len) {
+                return AVERROR_BUFFER_TOO_SMALL;
+            }
 
-        dst_box = dst_data + sizeof(start_code);
+            dst_box = dst_data + sizeof(start_code);
 
-        memcpy(dst_data, start_code, sizeof(start_code));
-        status = CMBlockBufferCopyDataBytes(block,
-                                            src_offset + length_code_size,
-                                            box_len,
-                                            dst_box);
+            memcpy(dst_data, start_code, sizeof(start_code));
+            status = CMBlockBufferCopyDataBytes(block,
+                                                src_offset + length_code_size,
+                                                box_len,
+                                                dst_box);
 
-        if (status) {
-            av_log(avctx, AV_LOG_ERROR, "Cannot copy data: %d\n", status);
-            return AVERROR_EXTERNAL;
+            if (status) {
+                av_log(avctx, AV_LOG_ERROR, "Cannot copy data: %d\n", status);
+                return AVERROR_EXTERNAL;
+            }
         }
 
         if (sei && !wrote_sei && nal_type == H264_NAL_SEI) {
@@ -1931,7 +1937,8 @@  static int vtenc_cm_to_avpacket(
         sample_buffer,
         sei,
         pkt->data + header_size,
-        pkt->size - header_size
+        pkt->size - header_size,
+        vtctx->ignore_internal_sei
     );
 
     if (status) {
@@ -2543,6 +2550,8 @@  static const enum AVPixelFormat hevc_pix_fmts[] = {
         { .i64 = 0 }, 0, 1, VE }, \
     { "require_sw", "Require software encoding", OFFSET(require_sw), AV_OPT_TYPE_BOOL, \
         { .i64 = 0 }, 0, 1, VE }, \
+    { "ignore_internal_sei", "Ignore SEI nalu generated by videotoolbox", OFFSET(ignore_internal_sei), AV_OPT_TYPE_BOOL, \
+        { .i64 = 1 }, 0, 1, VE }, \
     { "realtime", "Hint that encoding should happen in real-time if not faster (e.g. capturing from camera).", \
         OFFSET(realtime), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, \
     { "frames_before", "Other frames will come before the frames in this session. This helps smooth concatenation issues.", \