Re: [FFmpeg-devel] [PATCH 4/8] h264_metadata: Add support for A/53 closed captions
On Mon, Mar 12, 2018 at 9:25 AM, Mark Thompson wrote: > On 12/03/18 15:10, Hendrik Leppkes wrote: > > On Mon, Mar 12, 2018 at 2:38 PM, Mark Thompson wrote: > >> On 12/03/18 09:54, Hendrik Leppkes wrote: > >>> On Sun, Mar 11, 2018 at 7:30 PM, Mark Thompson wrote: > --- > libavcodec/h264_metadata_bsf.c | 121 ++ > +++ > 1 file changed, 121 insertions(+) > > diff --git a/libavcodec/h264_metadata_bsf.c > b/libavcodec/h264_metadata_bsf.c > index 36047887ca..d340c55990 100644 > --- a/libavcodec/h264_metadata_bsf.c > +++ b/libavcodec/h264_metadata_bsf.c > @@ -77,6 +77,8 @@ typedef struct H264MetadataContext { > int display_orientation; > double rotate; > int flip; > + > +int a53_cc; > } H264MetadataContext; > > > @@ -225,6 +227,8 @@ static int h264_metadata_filter(AVBSFContext > *bsf, AVPacket *out) > int err, i, j, has_sps; > uint8_t *displaymatrix_side_data = NULL; > size_t displaymatrix_side_data_size = 0; > +uint8_t *a53_side_data = NULL; > +size_t a53_side_data_size = 0; > > err = ff_bsf_get_packet(bsf, &in); > if (err < 0) > @@ -514,6 +518,104 @@ static int h264_metadata_filter(AVBSFContext > *bsf, AVPacket *out) > } > } > > +if (ctx->a53_cc == INSERT) { > +uint8_t *data; > +int size; > + > +data = av_packet_get_side_data(in, AV_PKT_DATA_A53_CC, > &size); > +if (data) { > +H264RawSEIPayload payload = { > +.payload_type = H264_SEI_TYPE_USER_DATA_REGISTERED, > +}; > +H264RawSEIUserDataRegistered *udr = > +&payload.payload.user_data_registered; > + > +av_log(bsf, AV_LOG_WARNING, "A53 CC insert: %d > bytes.\n", size); > + > +udr->data_length = size + 10; > +udr->data_ref= av_buffer_alloc(udr->data_length); > +if (!udr->data_ref) { > +err = AVERROR(ENOMEM); > +goto fail; > +} > +udr->data = udr->data_ref->data; > + > +udr->itu_t_t35_country_code = 181; > +udr->data[0] = 0; > +udr->data[1] = 49; > +AV_WB32(udr->data + 2, MKBETAG('G', 'A', '9', '4')); > +udr->data[6] = 3; > +udr->data[7] = ((size / 3) & 0x1f) | 0x40; > +udr->data[8] = 0; > +memcpy(udr->data + 9, data, size); > +udr->data[size + 9] = 0xff; > + > +err = ff_cbs_h264_add_sei_message(ctx->cbc, au, > &payload); > +if (err < 0) { > +av_log(bsf, AV_LOG_ERROR, "Failed to add user data > SEI " > + "message to access unit.\n"); > +av_buffer_unref(&udr->data_ref); > +goto fail; > +} > +} > + > +} else if (ctx->a53_cc == REMOVE || ctx->a53_cc == EXTRACT) { > +for (i = 0; i < au->nb_units; i++) { > +H264RawSEI *sei; > +if (au->units[i].type != H264_NAL_SEI) > +continue; > +sei = au->units[i].content; > + > +for (j = 0; j < sei->payload_count; j++) { > +H264RawSEIUserDataRegistered *udr; > +uint32_t tag; > +uint8_t type_code, count; > + > +if (sei->payload[j].payload_type != > +H264_SEI_TYPE_USER_DATA_REGISTERED) > +continue; > +udr = &sei->payload[j].payload.user_data_registered; > +tag = AV_RB32(udr->data + 2); > +type_code = udr->data[6]; > +if (tag != MKBETAG('G', 'A', '9', '4') || type_code > != 3) > +continue; > + > +if (ctx->a53_cc == REMOVE) { > +err = ff_cbs_h264_delete_sei_message(ctx->cbc, > au, > + > &au->units[i], j); > +if (err < 0) { > +av_log(bsf, AV_LOG_ERROR, "Failed to delete " > + "A53 CC SEI message.\n"); > +goto fail; > +} > +av_log(bsf, AV_LOG_WARNING, "A53 CC remove!.\n"); > + > +--i; > +break; > +} > + > +// Extract. > +count = udr->data[7] & 0x1f; > +if (3 * count + 10 > udr->data_length) { > +av_log(bsf, AV_LOG_E
Re: [FFmpeg-devel] [PATCH 4/8] h264_metadata: Add support for A/53 closed captions
On 12/03/18 15:10, Hendrik Leppkes wrote: > On Mon, Mar 12, 2018 at 2:38 PM, Mark Thompson wrote: >> On 12/03/18 09:54, Hendrik Leppkes wrote: >>> On Sun, Mar 11, 2018 at 7:30 PM, Mark Thompson wrote: --- libavcodec/h264_metadata_bsf.c | 121 + 1 file changed, 121 insertions(+) diff --git a/libavcodec/h264_metadata_bsf.c b/libavcodec/h264_metadata_bsf.c index 36047887ca..d340c55990 100644 --- a/libavcodec/h264_metadata_bsf.c +++ b/libavcodec/h264_metadata_bsf.c @@ -77,6 +77,8 @@ typedef struct H264MetadataContext { int display_orientation; double rotate; int flip; + +int a53_cc; } H264MetadataContext; @@ -225,6 +227,8 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out) int err, i, j, has_sps; uint8_t *displaymatrix_side_data = NULL; size_t displaymatrix_side_data_size = 0; +uint8_t *a53_side_data = NULL; +size_t a53_side_data_size = 0; err = ff_bsf_get_packet(bsf, &in); if (err < 0) @@ -514,6 +518,104 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out) } } +if (ctx->a53_cc == INSERT) { +uint8_t *data; +int size; + +data = av_packet_get_side_data(in, AV_PKT_DATA_A53_CC, &size); +if (data) { +H264RawSEIPayload payload = { +.payload_type = H264_SEI_TYPE_USER_DATA_REGISTERED, +}; +H264RawSEIUserDataRegistered *udr = +&payload.payload.user_data_registered; + +av_log(bsf, AV_LOG_WARNING, "A53 CC insert: %d bytes.\n", size); + +udr->data_length = size + 10; +udr->data_ref= av_buffer_alloc(udr->data_length); +if (!udr->data_ref) { +err = AVERROR(ENOMEM); +goto fail; +} +udr->data = udr->data_ref->data; + +udr->itu_t_t35_country_code = 181; +udr->data[0] = 0; +udr->data[1] = 49; +AV_WB32(udr->data + 2, MKBETAG('G', 'A', '9', '4')); +udr->data[6] = 3; +udr->data[7] = ((size / 3) & 0x1f) | 0x40; +udr->data[8] = 0; +memcpy(udr->data + 9, data, size); +udr->data[size + 9] = 0xff; + +err = ff_cbs_h264_add_sei_message(ctx->cbc, au, &payload); +if (err < 0) { +av_log(bsf, AV_LOG_ERROR, "Failed to add user data SEI " + "message to access unit.\n"); +av_buffer_unref(&udr->data_ref); +goto fail; +} +} + +} else if (ctx->a53_cc == REMOVE || ctx->a53_cc == EXTRACT) { +for (i = 0; i < au->nb_units; i++) { +H264RawSEI *sei; +if (au->units[i].type != H264_NAL_SEI) +continue; +sei = au->units[i].content; + +for (j = 0; j < sei->payload_count; j++) { +H264RawSEIUserDataRegistered *udr; +uint32_t tag; +uint8_t type_code, count; + +if (sei->payload[j].payload_type != +H264_SEI_TYPE_USER_DATA_REGISTERED) +continue; +udr = &sei->payload[j].payload.user_data_registered; +tag = AV_RB32(udr->data + 2); +type_code = udr->data[6]; +if (tag != MKBETAG('G', 'A', '9', '4') || type_code != 3) +continue; + +if (ctx->a53_cc == REMOVE) { +err = ff_cbs_h264_delete_sei_message(ctx->cbc, au, + &au->units[i], j); +if (err < 0) { +av_log(bsf, AV_LOG_ERROR, "Failed to delete " + "A53 CC SEI message.\n"); +goto fail; +} +av_log(bsf, AV_LOG_WARNING, "A53 CC remove!.\n"); + +--i; +break; +} + +// Extract. +count = udr->data[7] & 0x1f; +if (3 * count + 10 > udr->data_length) { +av_log(bsf, AV_LOG_ERROR, "Invalid A/53 closed caption " + "data: count %d overflows length %zu.\n", + count, udr->data_length); +continue; >>>
Re: [FFmpeg-devel] [PATCH 4/8] h264_metadata: Add support for A/53 closed captions
On Mon, Mar 12, 2018 at 2:38 PM, Mark Thompson wrote: > On 12/03/18 09:54, Hendrik Leppkes wrote: >> On Sun, Mar 11, 2018 at 7:30 PM, Mark Thompson wrote: >>> --- >>> libavcodec/h264_metadata_bsf.c | 121 >>> + >>> 1 file changed, 121 insertions(+) >>> >>> diff --git a/libavcodec/h264_metadata_bsf.c b/libavcodec/h264_metadata_bsf.c >>> index 36047887ca..d340c55990 100644 >>> --- a/libavcodec/h264_metadata_bsf.c >>> +++ b/libavcodec/h264_metadata_bsf.c >>> @@ -77,6 +77,8 @@ typedef struct H264MetadataContext { >>> int display_orientation; >>> double rotate; >>> int flip; >>> + >>> +int a53_cc; >>> } H264MetadataContext; >>> >>> >>> @@ -225,6 +227,8 @@ static int h264_metadata_filter(AVBSFContext *bsf, >>> AVPacket *out) >>> int err, i, j, has_sps; >>> uint8_t *displaymatrix_side_data = NULL; >>> size_t displaymatrix_side_data_size = 0; >>> +uint8_t *a53_side_data = NULL; >>> +size_t a53_side_data_size = 0; >>> >>> err = ff_bsf_get_packet(bsf, &in); >>> if (err < 0) >>> @@ -514,6 +518,104 @@ static int h264_metadata_filter(AVBSFContext *bsf, >>> AVPacket *out) >>> } >>> } >>> >>> +if (ctx->a53_cc == INSERT) { >>> +uint8_t *data; >>> +int size; >>> + >>> +data = av_packet_get_side_data(in, AV_PKT_DATA_A53_CC, &size); >>> +if (data) { >>> +H264RawSEIPayload payload = { >>> +.payload_type = H264_SEI_TYPE_USER_DATA_REGISTERED, >>> +}; >>> +H264RawSEIUserDataRegistered *udr = >>> +&payload.payload.user_data_registered; >>> + >>> +av_log(bsf, AV_LOG_WARNING, "A53 CC insert: %d bytes.\n", >>> size); >>> + >>> +udr->data_length = size + 10; >>> +udr->data_ref= av_buffer_alloc(udr->data_length); >>> +if (!udr->data_ref) { >>> +err = AVERROR(ENOMEM); >>> +goto fail; >>> +} >>> +udr->data = udr->data_ref->data; >>> + >>> +udr->itu_t_t35_country_code = 181; >>> +udr->data[0] = 0; >>> +udr->data[1] = 49; >>> +AV_WB32(udr->data + 2, MKBETAG('G', 'A', '9', '4')); >>> +udr->data[6] = 3; >>> +udr->data[7] = ((size / 3) & 0x1f) | 0x40; >>> +udr->data[8] = 0; >>> +memcpy(udr->data + 9, data, size); >>> +udr->data[size + 9] = 0xff; >>> + >>> +err = ff_cbs_h264_add_sei_message(ctx->cbc, au, &payload); >>> +if (err < 0) { >>> +av_log(bsf, AV_LOG_ERROR, "Failed to add user data SEI " >>> + "message to access unit.\n"); >>> +av_buffer_unref(&udr->data_ref); >>> +goto fail; >>> +} >>> +} >>> + >>> +} else if (ctx->a53_cc == REMOVE || ctx->a53_cc == EXTRACT) { >>> +for (i = 0; i < au->nb_units; i++) { >>> +H264RawSEI *sei; >>> +if (au->units[i].type != H264_NAL_SEI) >>> +continue; >>> +sei = au->units[i].content; >>> + >>> +for (j = 0; j < sei->payload_count; j++) { >>> +H264RawSEIUserDataRegistered *udr; >>> +uint32_t tag; >>> +uint8_t type_code, count; >>> + >>> +if (sei->payload[j].payload_type != >>> +H264_SEI_TYPE_USER_DATA_REGISTERED) >>> +continue; >>> +udr = &sei->payload[j].payload.user_data_registered; >>> +tag = AV_RB32(udr->data + 2); >>> +type_code = udr->data[6]; >>> +if (tag != MKBETAG('G', 'A', '9', '4') || type_code != 3) >>> +continue; >>> + >>> +if (ctx->a53_cc == REMOVE) { >>> +err = ff_cbs_h264_delete_sei_message(ctx->cbc, au, >>> + &au->units[i], j); >>> +if (err < 0) { >>> +av_log(bsf, AV_LOG_ERROR, "Failed to delete " >>> + "A53 CC SEI message.\n"); >>> +goto fail; >>> +} >>> +av_log(bsf, AV_LOG_WARNING, "A53 CC remove!.\n"); >>> + >>> +--i; >>> +break; >>> +} >>> + >>> +// Extract. >>> +count = udr->data[7] & 0x1f; >>> +if (3 * count + 10 > udr->data_length) { >>> +av_log(bsf, AV_LOG_ERROR, "Invalid A/53 closed caption >>> " >>> + "data: count %d overflows length %zu.\n", >>> + count, udr->data_length); >>> +continue; >>> +} >>> + >>> +av_log(bsf, AV_LOG_WARNING, "A53 CC extract: %zu >>> bytes.\n", udr->data_length); >>> + >>> +err = av_reallocp(
Re: [FFmpeg-devel] [PATCH 4/8] h264_metadata: Add support for A/53 closed captions
On 12/03/18 09:54, Hendrik Leppkes wrote: > On Sun, Mar 11, 2018 at 7:30 PM, Mark Thompson wrote: >> --- >> libavcodec/h264_metadata_bsf.c | 121 >> + >> 1 file changed, 121 insertions(+) >> >> diff --git a/libavcodec/h264_metadata_bsf.c b/libavcodec/h264_metadata_bsf.c >> index 36047887ca..d340c55990 100644 >> --- a/libavcodec/h264_metadata_bsf.c >> +++ b/libavcodec/h264_metadata_bsf.c >> @@ -77,6 +77,8 @@ typedef struct H264MetadataContext { >> int display_orientation; >> double rotate; >> int flip; >> + >> +int a53_cc; >> } H264MetadataContext; >> >> >> @@ -225,6 +227,8 @@ static int h264_metadata_filter(AVBSFContext *bsf, >> AVPacket *out) >> int err, i, j, has_sps; >> uint8_t *displaymatrix_side_data = NULL; >> size_t displaymatrix_side_data_size = 0; >> +uint8_t *a53_side_data = NULL; >> +size_t a53_side_data_size = 0; >> >> err = ff_bsf_get_packet(bsf, &in); >> if (err < 0) >> @@ -514,6 +518,104 @@ static int h264_metadata_filter(AVBSFContext *bsf, >> AVPacket *out) >> } >> } >> >> +if (ctx->a53_cc == INSERT) { >> +uint8_t *data; >> +int size; >> + >> +data = av_packet_get_side_data(in, AV_PKT_DATA_A53_CC, &size); >> +if (data) { >> +H264RawSEIPayload payload = { >> +.payload_type = H264_SEI_TYPE_USER_DATA_REGISTERED, >> +}; >> +H264RawSEIUserDataRegistered *udr = >> +&payload.payload.user_data_registered; >> + >> +av_log(bsf, AV_LOG_WARNING, "A53 CC insert: %d bytes.\n", size); >> + >> +udr->data_length = size + 10; >> +udr->data_ref= av_buffer_alloc(udr->data_length); >> +if (!udr->data_ref) { >> +err = AVERROR(ENOMEM); >> +goto fail; >> +} >> +udr->data = udr->data_ref->data; >> + >> +udr->itu_t_t35_country_code = 181; >> +udr->data[0] = 0; >> +udr->data[1] = 49; >> +AV_WB32(udr->data + 2, MKBETAG('G', 'A', '9', '4')); >> +udr->data[6] = 3; >> +udr->data[7] = ((size / 3) & 0x1f) | 0x40; >> +udr->data[8] = 0; >> +memcpy(udr->data + 9, data, size); >> +udr->data[size + 9] = 0xff; >> + >> +err = ff_cbs_h264_add_sei_message(ctx->cbc, au, &payload); >> +if (err < 0) { >> +av_log(bsf, AV_LOG_ERROR, "Failed to add user data SEI " >> + "message to access unit.\n"); >> +av_buffer_unref(&udr->data_ref); >> +goto fail; >> +} >> +} >> + >> +} else if (ctx->a53_cc == REMOVE || ctx->a53_cc == EXTRACT) { >> +for (i = 0; i < au->nb_units; i++) { >> +H264RawSEI *sei; >> +if (au->units[i].type != H264_NAL_SEI) >> +continue; >> +sei = au->units[i].content; >> + >> +for (j = 0; j < sei->payload_count; j++) { >> +H264RawSEIUserDataRegistered *udr; >> +uint32_t tag; >> +uint8_t type_code, count; >> + >> +if (sei->payload[j].payload_type != >> +H264_SEI_TYPE_USER_DATA_REGISTERED) >> +continue; >> +udr = &sei->payload[j].payload.user_data_registered; >> +tag = AV_RB32(udr->data + 2); >> +type_code = udr->data[6]; >> +if (tag != MKBETAG('G', 'A', '9', '4') || type_code != 3) >> +continue; >> + >> +if (ctx->a53_cc == REMOVE) { >> +err = ff_cbs_h264_delete_sei_message(ctx->cbc, au, >> + &au->units[i], j); >> +if (err < 0) { >> +av_log(bsf, AV_LOG_ERROR, "Failed to delete " >> + "A53 CC SEI message.\n"); >> +goto fail; >> +} >> +av_log(bsf, AV_LOG_WARNING, "A53 CC remove!.\n"); >> + >> +--i; >> +break; >> +} >> + >> +// Extract. >> +count = udr->data[7] & 0x1f; >> +if (3 * count + 10 > udr->data_length) { >> +av_log(bsf, AV_LOG_ERROR, "Invalid A/53 closed caption " >> + "data: count %d overflows length %zu.\n", >> + count, udr->data_length); >> +continue; >> +} >> + >> +av_log(bsf, AV_LOG_WARNING, "A53 CC extract: %zu bytes.\n", >> udr->data_length); >> + >> +err = av_reallocp(&a53_side_data, >> + a53_side_data_size + 3 * count); >> +if (err) >> +goto fail; >> +memcpy(a53_side_dat
Re: [FFmpeg-devel] [PATCH 4/8] h264_metadata: Add support for A/53 closed captions
On 12/03/18 07:19, Aman Gupta wrote: > On Sun, Mar 11, 2018 at 11:30 AM, Mark Thompson wrote: > >> --- >> libavcodec/h264_metadata_bsf.c | 121 ++ >> +++ >> 1 file changed, 121 insertions(+) >> >> diff --git a/libavcodec/h264_metadata_bsf.c b/libavcodec/h264_metadata_ >> bsf.c >> index 36047887ca..d340c55990 100644 >> --- a/libavcodec/h264_metadata_bsf.c >> +++ b/libavcodec/h264_metadata_bsf.c >> @@ -77,6 +77,8 @@ typedef struct H264MetadataContext { >> int display_orientation; >> double rotate; >> int flip; >> + >> +int a53_cc; >> } H264MetadataContext; >> >> >> @@ -225,6 +227,8 @@ static int h264_metadata_filter(AVBSFContext *bsf, >> AVPacket *out) >> int err, i, j, has_sps; >> uint8_t *displaymatrix_side_data = NULL; >> size_t displaymatrix_side_data_size = 0; >> +uint8_t *a53_side_data = NULL; >> +size_t a53_side_data_size = 0; >> >> err = ff_bsf_get_packet(bsf, &in); >> if (err < 0) >> @@ -514,6 +518,104 @@ static int h264_metadata_filter(AVBSFContext *bsf, >> AVPacket *out) >> } >> } >> >> +if (ctx->a53_cc == INSERT) { >> +uint8_t *data; >> +int size; >> + >> +data = av_packet_get_side_data(in, AV_PKT_DATA_A53_CC, &size); >> +if (data) { >> +H264RawSEIPayload payload = { >> +.payload_type = H264_SEI_TYPE_USER_DATA_REGISTERED, >> +}; >> +H264RawSEIUserDataRegistered *udr = >> +&payload.payload.user_data_registered; >> + >> +av_log(bsf, AV_LOG_WARNING, "A53 CC insert: %d bytes.\n", >> size); >> + >> +udr->data_length = size + 10; >> +udr->data_ref= av_buffer_alloc(udr->data_length); >> +if (!udr->data_ref) { >> +err = AVERROR(ENOMEM); >> +goto fail; >> +} >> +udr->data = udr->data_ref->data; >> + >> +udr->itu_t_t35_country_code = 181; >> +udr->data[0] = 0; >> +udr->data[1] = 49; >> +AV_WB32(udr->data + 2, MKBETAG('G', 'A', '9', '4')); >> +udr->data[6] = 3; >> +udr->data[7] = ((size / 3) & 0x1f) | 0x40; >> +udr->data[8] = 0; >> +memcpy(udr->data + 9, data, size); >> +udr->data[size + 9] = 0xff; >> + >> +err = ff_cbs_h264_add_sei_message(ctx->cbc, au, &payload); >> +if (err < 0) { >> +av_log(bsf, AV_LOG_ERROR, "Failed to add user data SEI " >> + "message to access unit.\n"); >> +av_buffer_unref(&udr->data_ref); >> +goto fail; >> +} >> +} >> + >> +} else if (ctx->a53_cc == REMOVE || ctx->a53_cc == EXTRACT) { >> +for (i = 0; i < au->nb_units; i++) { >> +H264RawSEI *sei; >> +if (au->units[i].type != H264_NAL_SEI) >> +continue; >> +sei = au->units[i].content; >> + >> +for (j = 0; j < sei->payload_count; j++) { >> +H264RawSEIUserDataRegistered *udr; >> +uint32_t tag; >> +uint8_t type_code, count; >> + >> +if (sei->payload[j].payload_type != >> +H264_SEI_TYPE_USER_DATA_REGISTERED) >> +continue; >> +udr = &sei->payload[j].payload.user_data_registered; >> +tag = AV_RB32(udr->data + 2); >> +type_code = udr->data[6]; >> +if (tag != MKBETAG('G', 'A', '9', '4') || type_code != 3) >> +continue; >> + >> +if (ctx->a53_cc == REMOVE) { >> +err = ff_cbs_h264_delete_sei_message(ctx->cbc, au, >> + &au->units[i], >> j); >> +if (err < 0) { >> +av_log(bsf, AV_LOG_ERROR, "Failed to delete " >> + "A53 CC SEI message.\n"); >> +goto fail; >> +} >> +av_log(bsf, AV_LOG_WARNING, "A53 CC remove!.\n"); > > + >> +--i; >> +break; >> +} >> + >> +// Extract. >> +count = udr->data[7] & 0x1f; >> +if (3 * count + 10 > udr->data_length) { >> +av_log(bsf, AV_LOG_ERROR, "Invalid A/53 closed >> caption " >> + "data: count %d overflows length %zu.\n", >> + count, udr->data_length); >> +continue; >> +} >> + >> +av_log(bsf, AV_LOG_WARNING, "A53 CC extract: %zu >> bytes.\n", udr->data_length); >> > > I assume these are WARNINGs from testing? Seems like TRACE or DEBUG would > be fine. Oops, yeah. Removed this one and others. (The filter probably does want some more logging to explain what it's doing (at VERB
Re: [FFmpeg-devel] [PATCH 4/8] h264_metadata: Add support for A/53 closed captions
> Does extracting really make sense? Doesn't the data end up out of > order and basically unusable? For what it’s worth, I’ve got a video filter which extracts the A53 side data and saves it into an MCC file (Telestream MacCaption format). If people think that’s something that would be useful, I’ll see about getting it upstreamed. Devin ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH 4/8] h264_metadata: Add support for A/53 closed captions
On Sun, Mar 11, 2018 at 7:30 PM, Mark Thompson wrote: > --- > libavcodec/h264_metadata_bsf.c | 121 > + > 1 file changed, 121 insertions(+) > > diff --git a/libavcodec/h264_metadata_bsf.c b/libavcodec/h264_metadata_bsf.c > index 36047887ca..d340c55990 100644 > --- a/libavcodec/h264_metadata_bsf.c > +++ b/libavcodec/h264_metadata_bsf.c > @@ -77,6 +77,8 @@ typedef struct H264MetadataContext { > int display_orientation; > double rotate; > int flip; > + > +int a53_cc; > } H264MetadataContext; > > > @@ -225,6 +227,8 @@ static int h264_metadata_filter(AVBSFContext *bsf, > AVPacket *out) > int err, i, j, has_sps; > uint8_t *displaymatrix_side_data = NULL; > size_t displaymatrix_side_data_size = 0; > +uint8_t *a53_side_data = NULL; > +size_t a53_side_data_size = 0; > > err = ff_bsf_get_packet(bsf, &in); > if (err < 0) > @@ -514,6 +518,104 @@ static int h264_metadata_filter(AVBSFContext *bsf, > AVPacket *out) > } > } > > +if (ctx->a53_cc == INSERT) { > +uint8_t *data; > +int size; > + > +data = av_packet_get_side_data(in, AV_PKT_DATA_A53_CC, &size); > +if (data) { > +H264RawSEIPayload payload = { > +.payload_type = H264_SEI_TYPE_USER_DATA_REGISTERED, > +}; > +H264RawSEIUserDataRegistered *udr = > +&payload.payload.user_data_registered; > + > +av_log(bsf, AV_LOG_WARNING, "A53 CC insert: %d bytes.\n", size); > + > +udr->data_length = size + 10; > +udr->data_ref= av_buffer_alloc(udr->data_length); > +if (!udr->data_ref) { > +err = AVERROR(ENOMEM); > +goto fail; > +} > +udr->data = udr->data_ref->data; > + > +udr->itu_t_t35_country_code = 181; > +udr->data[0] = 0; > +udr->data[1] = 49; > +AV_WB32(udr->data + 2, MKBETAG('G', 'A', '9', '4')); > +udr->data[6] = 3; > +udr->data[7] = ((size / 3) & 0x1f) | 0x40; > +udr->data[8] = 0; > +memcpy(udr->data + 9, data, size); > +udr->data[size + 9] = 0xff; > + > +err = ff_cbs_h264_add_sei_message(ctx->cbc, au, &payload); > +if (err < 0) { > +av_log(bsf, AV_LOG_ERROR, "Failed to add user data SEI " > + "message to access unit.\n"); > +av_buffer_unref(&udr->data_ref); > +goto fail; > +} > +} > + > +} else if (ctx->a53_cc == REMOVE || ctx->a53_cc == EXTRACT) { > +for (i = 0; i < au->nb_units; i++) { > +H264RawSEI *sei; > +if (au->units[i].type != H264_NAL_SEI) > +continue; > +sei = au->units[i].content; > + > +for (j = 0; j < sei->payload_count; j++) { > +H264RawSEIUserDataRegistered *udr; > +uint32_t tag; > +uint8_t type_code, count; > + > +if (sei->payload[j].payload_type != > +H264_SEI_TYPE_USER_DATA_REGISTERED) > +continue; > +udr = &sei->payload[j].payload.user_data_registered; > +tag = AV_RB32(udr->data + 2); > +type_code = udr->data[6]; > +if (tag != MKBETAG('G', 'A', '9', '4') || type_code != 3) > +continue; > + > +if (ctx->a53_cc == REMOVE) { > +err = ff_cbs_h264_delete_sei_message(ctx->cbc, au, > + &au->units[i], j); > +if (err < 0) { > +av_log(bsf, AV_LOG_ERROR, "Failed to delete " > + "A53 CC SEI message.\n"); > +goto fail; > +} > +av_log(bsf, AV_LOG_WARNING, "A53 CC remove!.\n"); > + > +--i; > +break; > +} > + > +// Extract. > +count = udr->data[7] & 0x1f; > +if (3 * count + 10 > udr->data_length) { > +av_log(bsf, AV_LOG_ERROR, "Invalid A/53 closed caption " > + "data: count %d overflows length %zu.\n", > + count, udr->data_length); > +continue; > +} > + > +av_log(bsf, AV_LOG_WARNING, "A53 CC extract: %zu bytes.\n", > udr->data_length); > + > +err = av_reallocp(&a53_side_data, > + a53_side_data_size + 3 * count); > +if (err) > +goto fail; > +memcpy(a53_side_data + a53_side_data_size, > + udr->data + 9, 3 * count); > +a53_side_data_size += 3 * count; > +} > +} > +} >
Re: [FFmpeg-devel] [PATCH 4/8] h264_metadata: Add support for A/53 closed captions
On Sun, Mar 11, 2018 at 11:30 AM, Mark Thompson wrote: > --- > libavcodec/h264_metadata_bsf.c | 121 ++ > +++ > 1 file changed, 121 insertions(+) > > diff --git a/libavcodec/h264_metadata_bsf.c b/libavcodec/h264_metadata_ > bsf.c > index 36047887ca..d340c55990 100644 > --- a/libavcodec/h264_metadata_bsf.c > +++ b/libavcodec/h264_metadata_bsf.c > @@ -77,6 +77,8 @@ typedef struct H264MetadataContext { > int display_orientation; > double rotate; > int flip; > + > +int a53_cc; > } H264MetadataContext; > > > @@ -225,6 +227,8 @@ static int h264_metadata_filter(AVBSFContext *bsf, > AVPacket *out) > int err, i, j, has_sps; > uint8_t *displaymatrix_side_data = NULL; > size_t displaymatrix_side_data_size = 0; > +uint8_t *a53_side_data = NULL; > +size_t a53_side_data_size = 0; > > err = ff_bsf_get_packet(bsf, &in); > if (err < 0) > @@ -514,6 +518,104 @@ static int h264_metadata_filter(AVBSFContext *bsf, > AVPacket *out) > } > } > > +if (ctx->a53_cc == INSERT) { > +uint8_t *data; > +int size; > + > +data = av_packet_get_side_data(in, AV_PKT_DATA_A53_CC, &size); > +if (data) { > +H264RawSEIPayload payload = { > +.payload_type = H264_SEI_TYPE_USER_DATA_REGISTERED, > +}; > +H264RawSEIUserDataRegistered *udr = > +&payload.payload.user_data_registered; > + > +av_log(bsf, AV_LOG_WARNING, "A53 CC insert: %d bytes.\n", > size); > + > +udr->data_length = size + 10; > +udr->data_ref= av_buffer_alloc(udr->data_length); > +if (!udr->data_ref) { > +err = AVERROR(ENOMEM); > +goto fail; > +} > +udr->data = udr->data_ref->data; > + > +udr->itu_t_t35_country_code = 181; > +udr->data[0] = 0; > +udr->data[1] = 49; > +AV_WB32(udr->data + 2, MKBETAG('G', 'A', '9', '4')); > +udr->data[6] = 3; > +udr->data[7] = ((size / 3) & 0x1f) | 0x40; > +udr->data[8] = 0; > +memcpy(udr->data + 9, data, size); > +udr->data[size + 9] = 0xff; > + > +err = ff_cbs_h264_add_sei_message(ctx->cbc, au, &payload); > +if (err < 0) { > +av_log(bsf, AV_LOG_ERROR, "Failed to add user data SEI " > + "message to access unit.\n"); > +av_buffer_unref(&udr->data_ref); > +goto fail; > +} > +} > + > +} else if (ctx->a53_cc == REMOVE || ctx->a53_cc == EXTRACT) { > +for (i = 0; i < au->nb_units; i++) { > +H264RawSEI *sei; > +if (au->units[i].type != H264_NAL_SEI) > +continue; > +sei = au->units[i].content; > + > +for (j = 0; j < sei->payload_count; j++) { > +H264RawSEIUserDataRegistered *udr; > +uint32_t tag; > +uint8_t type_code, count; > + > +if (sei->payload[j].payload_type != > +H264_SEI_TYPE_USER_DATA_REGISTERED) > +continue; > +udr = &sei->payload[j].payload.user_data_registered; > +tag = AV_RB32(udr->data + 2); > +type_code = udr->data[6]; > +if (tag != MKBETAG('G', 'A', '9', '4') || type_code != 3) > +continue; > + > +if (ctx->a53_cc == REMOVE) { > +err = ff_cbs_h264_delete_sei_message(ctx->cbc, au, > + &au->units[i], > j); > +if (err < 0) { > +av_log(bsf, AV_LOG_ERROR, "Failed to delete " > + "A53 CC SEI message.\n"); > +goto fail; > +} > +av_log(bsf, AV_LOG_WARNING, "A53 CC remove!.\n"); + > +--i; > +break; > +} > + > +// Extract. > +count = udr->data[7] & 0x1f; > +if (3 * count + 10 > udr->data_length) { > +av_log(bsf, AV_LOG_ERROR, "Invalid A/53 closed > caption " > + "data: count %d overflows length %zu.\n", > + count, udr->data_length); > +continue; > +} > + > +av_log(bsf, AV_LOG_WARNING, "A53 CC extract: %zu > bytes.\n", udr->data_length); > I assume these are WARNINGs from testing? Seems like TRACE or DEBUG would be fine. > + > +err = av_reallocp(&a53_side_data, > + a53_side_data_size + 3 * count); > +if (err) > +goto fail; > +memcpy(a53_side_data + a53_side_data_size, > + udr->data + 9, 3 * count)
[FFmpeg-devel] [PATCH 4/8] h264_metadata: Add support for A/53 closed captions
--- libavcodec/h264_metadata_bsf.c | 121 + 1 file changed, 121 insertions(+) diff --git a/libavcodec/h264_metadata_bsf.c b/libavcodec/h264_metadata_bsf.c index 36047887ca..d340c55990 100644 --- a/libavcodec/h264_metadata_bsf.c +++ b/libavcodec/h264_metadata_bsf.c @@ -77,6 +77,8 @@ typedef struct H264MetadataContext { int display_orientation; double rotate; int flip; + +int a53_cc; } H264MetadataContext; @@ -225,6 +227,8 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out) int err, i, j, has_sps; uint8_t *displaymatrix_side_data = NULL; size_t displaymatrix_side_data_size = 0; +uint8_t *a53_side_data = NULL; +size_t a53_side_data_size = 0; err = ff_bsf_get_packet(bsf, &in); if (err < 0) @@ -514,6 +518,104 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out) } } +if (ctx->a53_cc == INSERT) { +uint8_t *data; +int size; + +data = av_packet_get_side_data(in, AV_PKT_DATA_A53_CC, &size); +if (data) { +H264RawSEIPayload payload = { +.payload_type = H264_SEI_TYPE_USER_DATA_REGISTERED, +}; +H264RawSEIUserDataRegistered *udr = +&payload.payload.user_data_registered; + +av_log(bsf, AV_LOG_WARNING, "A53 CC insert: %d bytes.\n", size); + +udr->data_length = size + 10; +udr->data_ref= av_buffer_alloc(udr->data_length); +if (!udr->data_ref) { +err = AVERROR(ENOMEM); +goto fail; +} +udr->data = udr->data_ref->data; + +udr->itu_t_t35_country_code = 181; +udr->data[0] = 0; +udr->data[1] = 49; +AV_WB32(udr->data + 2, MKBETAG('G', 'A', '9', '4')); +udr->data[6] = 3; +udr->data[7] = ((size / 3) & 0x1f) | 0x40; +udr->data[8] = 0; +memcpy(udr->data + 9, data, size); +udr->data[size + 9] = 0xff; + +err = ff_cbs_h264_add_sei_message(ctx->cbc, au, &payload); +if (err < 0) { +av_log(bsf, AV_LOG_ERROR, "Failed to add user data SEI " + "message to access unit.\n"); +av_buffer_unref(&udr->data_ref); +goto fail; +} +} + +} else if (ctx->a53_cc == REMOVE || ctx->a53_cc == EXTRACT) { +for (i = 0; i < au->nb_units; i++) { +H264RawSEI *sei; +if (au->units[i].type != H264_NAL_SEI) +continue; +sei = au->units[i].content; + +for (j = 0; j < sei->payload_count; j++) { +H264RawSEIUserDataRegistered *udr; +uint32_t tag; +uint8_t type_code, count; + +if (sei->payload[j].payload_type != +H264_SEI_TYPE_USER_DATA_REGISTERED) +continue; +udr = &sei->payload[j].payload.user_data_registered; +tag = AV_RB32(udr->data + 2); +type_code = udr->data[6]; +if (tag != MKBETAG('G', 'A', '9', '4') || type_code != 3) +continue; + +if (ctx->a53_cc == REMOVE) { +err = ff_cbs_h264_delete_sei_message(ctx->cbc, au, + &au->units[i], j); +if (err < 0) { +av_log(bsf, AV_LOG_ERROR, "Failed to delete " + "A53 CC SEI message.\n"); +goto fail; +} +av_log(bsf, AV_LOG_WARNING, "A53 CC remove!.\n"); + +--i; +break; +} + +// Extract. +count = udr->data[7] & 0x1f; +if (3 * count + 10 > udr->data_length) { +av_log(bsf, AV_LOG_ERROR, "Invalid A/53 closed caption " + "data: count %d overflows length %zu.\n", + count, udr->data_length); +continue; +} + +av_log(bsf, AV_LOG_WARNING, "A53 CC extract: %zu bytes.\n", udr->data_length); + +err = av_reallocp(&a53_side_data, + a53_side_data_size + 3 * count); +if (err) +goto fail; +memcpy(a53_side_data + a53_side_data_size, + udr->data + 9, 3 * count); +a53_side_data_size += 3 * count; +} +} +} + err = ff_cbs_write_packet(ctx->cbc, out, au); if (err < 0) { av_log(bsf, AV_LOG_ERROR, "Failed to write packet.\n"); @@ -535,6 +637,16 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out) } displaymatrix_side_data = NULL; } +if (a53_side_data) {