mirror of https://git.ffmpeg.org/ffmpeg.git
h264_metadata_bsf: Refactor the filter function into smaller parts
This commit is contained in:
parent
88b65bed9c
commit
8a14d51b8b
|
@ -56,6 +56,7 @@ typedef struct H264MetadataContext {
|
|||
int done_first_au;
|
||||
|
||||
int aud;
|
||||
H264RawAUD aud_nal;
|
||||
|
||||
AVRational sample_aspect_ratio;
|
||||
|
||||
|
@ -91,6 +92,59 @@ typedef struct H264MetadataContext {
|
|||
} H264MetadataContext;
|
||||
|
||||
|
||||
static int h264_metadata_insert_aud(AVBSFContext *bsf,
|
||||
CodedBitstreamFragment *au)
|
||||
{
|
||||
H264MetadataContext *ctx = bsf->priv_data;
|
||||
int primary_pic_type_mask = 0xff;
|
||||
int err, i, j;
|
||||
|
||||
static const int primary_pic_type_table[] = {
|
||||
0x084, // 2, 7
|
||||
0x0a5, // 0, 2, 5, 7
|
||||
0x0e7, // 0, 1, 2, 5, 6, 7
|
||||
0x210, // 4, 9
|
||||
0x318, // 3, 4, 8, 9
|
||||
0x294, // 2, 4, 7, 9
|
||||
0x3bd, // 0, 2, 3, 4, 5, 7, 8, 9
|
||||
0x3ff, // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
|
||||
};
|
||||
|
||||
for (i = 0; i < au->nb_units; i++) {
|
||||
if (au->units[i].type == H264_NAL_SLICE ||
|
||||
au->units[i].type == H264_NAL_IDR_SLICE) {
|
||||
H264RawSlice *slice = au->units[i].content;
|
||||
for (j = 0; j < FF_ARRAY_ELEMS(primary_pic_type_table); j++) {
|
||||
if (!(primary_pic_type_table[j] &
|
||||
(1 << slice->header.slice_type)))
|
||||
primary_pic_type_mask &= ~(1 << j);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (j = 0; j < FF_ARRAY_ELEMS(primary_pic_type_table); j++)
|
||||
if (primary_pic_type_mask & (1 << j))
|
||||
break;
|
||||
if (j >= FF_ARRAY_ELEMS(primary_pic_type_table)) {
|
||||
av_log(bsf, AV_LOG_ERROR, "No usable primary_pic_type: "
|
||||
"invalid slice types?\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
ctx->aud_nal = (H264RawAUD) {
|
||||
.nal_unit_header.nal_unit_type = H264_NAL_AUD,
|
||||
.primary_pic_type = j,
|
||||
};
|
||||
|
||||
err = ff_cbs_insert_unit_content(au, 0, H264_NAL_AUD,
|
||||
&ctx->aud_nal, NULL);
|
||||
if (err < 0) {
|
||||
av_log(bsf, AV_LOG_ERROR, "Failed to insert AUD.\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int h264_metadata_update_sps(AVBSFContext *bsf,
|
||||
H264RawSPS *sps)
|
||||
{
|
||||
|
@ -322,123 +376,16 @@ static int h264_metadata_update_side_data(AVBSFContext *bsf, AVPacket *pkt)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *pkt)
|
||||
static int h264_metadata_handle_display_orientation(AVBSFContext *bsf,
|
||||
AVPacket *pkt,
|
||||
CodedBitstreamFragment *au,
|
||||
int seek_point)
|
||||
{
|
||||
H264MetadataContext *ctx = bsf->priv_data;
|
||||
CodedBitstreamFragment *au = &ctx->access_unit;
|
||||
int err, i, j, has_sps;
|
||||
H264RawAUD aud;
|
||||
SEIRawMessage *message;
|
||||
int err;
|
||||
|
||||
err = ff_bsf_get_packet_ref(bsf, pkt);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = h264_metadata_update_side_data(bsf, pkt);
|
||||
if (err < 0)
|
||||
goto fail;
|
||||
|
||||
err = ff_cbs_read_packet(ctx->input, au, pkt);
|
||||
if (err < 0) {
|
||||
av_log(bsf, AV_LOG_ERROR, "Failed to read packet.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (au->nb_units == 0) {
|
||||
av_log(bsf, AV_LOG_ERROR, "No NAL units in packet.\n");
|
||||
err = AVERROR_INVALIDDATA;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
// If an AUD is present, it must be the first NAL unit.
|
||||
if (au->units[0].type == H264_NAL_AUD) {
|
||||
if (ctx->aud == REMOVE)
|
||||
ff_cbs_delete_unit(au, 0);
|
||||
} else {
|
||||
if (ctx->aud == INSERT) {
|
||||
static const int primary_pic_type_table[] = {
|
||||
0x084, // 2, 7
|
||||
0x0a5, // 0, 2, 5, 7
|
||||
0x0e7, // 0, 1, 2, 5, 6, 7
|
||||
0x210, // 4, 9
|
||||
0x318, // 3, 4, 8, 9
|
||||
0x294, // 2, 4, 7, 9
|
||||
0x3bd, // 0, 2, 3, 4, 5, 7, 8, 9
|
||||
0x3ff, // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
|
||||
};
|
||||
int primary_pic_type_mask = 0xff;
|
||||
|
||||
for (i = 0; i < au->nb_units; i++) {
|
||||
if (au->units[i].type == H264_NAL_SLICE ||
|
||||
au->units[i].type == H264_NAL_IDR_SLICE) {
|
||||
H264RawSlice *slice = au->units[i].content;
|
||||
for (j = 0; j < FF_ARRAY_ELEMS(primary_pic_type_table); j++) {
|
||||
if (!(primary_pic_type_table[j] &
|
||||
(1 << slice->header.slice_type)))
|
||||
primary_pic_type_mask &= ~(1 << j);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (j = 0; j < FF_ARRAY_ELEMS(primary_pic_type_table); j++)
|
||||
if (primary_pic_type_mask & (1 << j))
|
||||
break;
|
||||
if (j >= FF_ARRAY_ELEMS(primary_pic_type_table)) {
|
||||
av_log(bsf, AV_LOG_ERROR, "No usable primary_pic_type: "
|
||||
"invalid slice types?\n");
|
||||
err = AVERROR_INVALIDDATA;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
aud = (H264RawAUD) {
|
||||
.nal_unit_header.nal_unit_type = H264_NAL_AUD,
|
||||
.primary_pic_type = j,
|
||||
};
|
||||
|
||||
err = ff_cbs_insert_unit_content(au,
|
||||
0, H264_NAL_AUD, &aud, NULL);
|
||||
if (err < 0) {
|
||||
av_log(bsf, AV_LOG_ERROR, "Failed to insert AUD.\n");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
has_sps = 0;
|
||||
for (i = 0; i < au->nb_units; i++) {
|
||||
if (au->units[i].type == H264_NAL_SPS) {
|
||||
err = h264_metadata_update_sps(bsf, au->units[i].content);
|
||||
if (err < 0)
|
||||
goto fail;
|
||||
has_sps = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Only insert the SEI in access units containing SPSs, and also
|
||||
// unconditionally in the first access unit we ever see.
|
||||
if (ctx->sei_user_data && (has_sps || !ctx->done_first_au)) {
|
||||
err = ff_cbs_sei_add_message(ctx->output, au, 1,
|
||||
SEI_TYPE_USER_DATA_UNREGISTERED,
|
||||
&ctx->sei_user_data_payload, NULL);
|
||||
if (err < 0) {
|
||||
av_log(bsf, AV_LOG_ERROR, "Failed to add user data SEI "
|
||||
"message to access unit.\n");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->delete_filler) {
|
||||
for (i = au->nb_units - 1; i >= 0; i--) {
|
||||
if (au->units[i].type == H264_NAL_FILLER_DATA) {
|
||||
ff_cbs_delete_unit(au, i);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
ff_cbs_sei_delete_message_type(ctx->output, au,
|
||||
SEI_TYPE_FILLER_PAYLOAD);
|
||||
}
|
||||
|
||||
if (ctx->display_orientation != PASS) {
|
||||
SEIRawMessage *message = NULL;
|
||||
message = NULL;
|
||||
while (ff_cbs_sei_find_message(ctx->output, au,
|
||||
SEI_TYPE_DISPLAY_ORIENTATION,
|
||||
&message) == 0) {
|
||||
|
@ -446,10 +393,8 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *pkt)
|
|||
int32_t *matrix;
|
||||
|
||||
matrix = av_malloc(9 * sizeof(int32_t));
|
||||
if (!matrix) {
|
||||
err = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
if (!matrix)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
av_display_rotation_set(matrix,
|
||||
disp->anticlockwise_rotation *
|
||||
|
@ -466,7 +411,7 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *pkt)
|
|||
av_log(bsf, AV_LOG_ERROR, "Failed to attach extracted "
|
||||
"displaymatrix side data to packet.\n");
|
||||
av_free(matrix);
|
||||
goto fail;
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -475,7 +420,7 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *pkt)
|
|||
ff_cbs_sei_delete_message_type(ctx->output, au,
|
||||
SEI_TYPE_DISPLAY_ORIENTATION);
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->display_orientation == INSERT) {
|
||||
H264RawSEIDisplayOrientation *disp =
|
||||
&ctx->display_orientation_payload;
|
||||
|
@ -516,7 +461,7 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *pkt)
|
|||
}
|
||||
}
|
||||
|
||||
if (has_sps || !ctx->done_first_au) {
|
||||
if (seek_point) {
|
||||
if (!isnan(ctx->rotate)) {
|
||||
disp->anticlockwise_rotation =
|
||||
(uint16_t)rint((ctx->rotate >= 0.0 ? ctx->rotate
|
||||
|
@ -540,9 +485,98 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *pkt)
|
|||
if (err < 0) {
|
||||
av_log(bsf, AV_LOG_ERROR, "Failed to add display orientation "
|
||||
"SEI message to access unit.\n");
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *pkt)
|
||||
{
|
||||
H264MetadataContext *ctx = bsf->priv_data;
|
||||
CodedBitstreamFragment *au = &ctx->access_unit;
|
||||
int err, i, has_sps, seek_point;
|
||||
|
||||
err = ff_bsf_get_packet_ref(bsf, pkt);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = h264_metadata_update_side_data(bsf, pkt);
|
||||
if (err < 0)
|
||||
goto fail;
|
||||
|
||||
err = ff_cbs_read_packet(ctx->input, au, pkt);
|
||||
if (err < 0) {
|
||||
av_log(bsf, AV_LOG_ERROR, "Failed to read packet.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (au->nb_units == 0) {
|
||||
av_log(bsf, AV_LOG_ERROR, "No NAL units in packet.\n");
|
||||
err = AVERROR_INVALIDDATA;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
// If an AUD is present, it must be the first NAL unit.
|
||||
if (au->units[0].type == H264_NAL_AUD) {
|
||||
if (ctx->aud == REMOVE)
|
||||
ff_cbs_delete_unit(au, 0);
|
||||
} else {
|
||||
if (ctx->aud == INSERT) {
|
||||
err = h264_metadata_insert_aud(bsf, au);
|
||||
if (err < 0)
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
has_sps = 0;
|
||||
for (i = 0; i < au->nb_units; i++) {
|
||||
if (au->units[i].type == H264_NAL_SPS) {
|
||||
err = h264_metadata_update_sps(bsf, au->units[i].content);
|
||||
if (err < 0)
|
||||
goto fail;
|
||||
has_sps = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// The current packet should be treated as a seek point for metadata
|
||||
// insertion if any of:
|
||||
// - It is the first packet in the stream.
|
||||
// - It contains an SPS, indicating that a sequence might start here.
|
||||
// - It is marked as containing a key frame.
|
||||
seek_point = !ctx->done_first_au || has_sps ||
|
||||
(pkt->flags & AV_PKT_FLAG_KEY);
|
||||
|
||||
if (ctx->sei_user_data && seek_point) {
|
||||
err = ff_cbs_sei_add_message(ctx->output, au, 1,
|
||||
SEI_TYPE_USER_DATA_UNREGISTERED,
|
||||
&ctx->sei_user_data_payload, NULL);
|
||||
if (err < 0) {
|
||||
av_log(bsf, AV_LOG_ERROR, "Failed to add user data SEI "
|
||||
"message to access unit.\n");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->delete_filler) {
|
||||
for (i = au->nb_units - 1; i >= 0; i--) {
|
||||
if (au->units[i].type == H264_NAL_FILLER_DATA) {
|
||||
ff_cbs_delete_unit(au, i);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
ff_cbs_sei_delete_message_type(ctx->output, au,
|
||||
SEI_TYPE_FILLER_PAYLOAD);
|
||||
}
|
||||
|
||||
if (ctx->display_orientation != PASS) {
|
||||
err = h264_metadata_handle_display_orientation(bsf, pkt, au,
|
||||
seek_point);
|
||||
if (err < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
err = ff_cbs_write_packet(ctx->output, pkt, au);
|
||||
|
|
Loading…
Reference in New Issue