mirror of https://git.ffmpeg.org/ffmpeg.git
h264_metadata: Add option to set the level of the stream
This commit is contained in:
parent
bb3503164e
commit
6522ba30e9
|
@ -215,6 +215,15 @@ insert the string ``hello'' associated with the given UUID.
|
||||||
@item delete_filler
|
@item delete_filler
|
||||||
Deletes both filler NAL units and filler SEI messages.
|
Deletes both filler NAL units and filler SEI messages.
|
||||||
|
|
||||||
|
@item level
|
||||||
|
Set the level in the SPS. Refer to H.264 section A.3 and tables A-1
|
||||||
|
to A-5.
|
||||||
|
|
||||||
|
The argument must be the name of a level (for example, @samp{4.2}), a
|
||||||
|
level_idc value (for example, @samp{42}), or the special name @samp{auto}
|
||||||
|
indicating that the filter should attempt to guess the level from the
|
||||||
|
input stream properties.
|
||||||
|
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
@section h264_mp4toannexb
|
@section h264_mp4toannexb
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "cbs.h"
|
#include "cbs.h"
|
||||||
#include "cbs_h264.h"
|
#include "cbs_h264.h"
|
||||||
#include "h264.h"
|
#include "h264.h"
|
||||||
|
#include "h264_levels.h"
|
||||||
#include "h264_sei.h"
|
#include "h264_sei.h"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
@ -39,6 +40,11 @@ enum {
|
||||||
FLIP_VERTICAL = 2,
|
FLIP_VERTICAL = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
LEVEL_UNSET = -2,
|
||||||
|
LEVEL_AUTO = -1,
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct H264MetadataContext {
|
typedef struct H264MetadataContext {
|
||||||
const AVClass *class;
|
const AVClass *class;
|
||||||
|
|
||||||
|
@ -74,6 +80,8 @@ typedef struct H264MetadataContext {
|
||||||
int display_orientation;
|
int display_orientation;
|
||||||
double rotate;
|
double rotate;
|
||||||
int flip;
|
int flip;
|
||||||
|
|
||||||
|
int level;
|
||||||
} H264MetadataContext;
|
} H264MetadataContext;
|
||||||
|
|
||||||
|
|
||||||
|
@ -208,6 +216,58 @@ static int h264_metadata_update_sps(AVBSFContext *bsf,
|
||||||
CROP(bottom, crop_unit_y);
|
CROP(bottom, crop_unit_y);
|
||||||
#undef CROP
|
#undef CROP
|
||||||
|
|
||||||
|
if (ctx->level != LEVEL_UNSET) {
|
||||||
|
int level_idc;
|
||||||
|
|
||||||
|
if (ctx->level == LEVEL_AUTO) {
|
||||||
|
const H264LevelDescriptor *desc;
|
||||||
|
int64_t bit_rate;
|
||||||
|
int width, height;
|
||||||
|
|
||||||
|
if (sps->vui.nal_hrd_parameters_present_flag) {
|
||||||
|
bit_rate = (sps->vui.nal_hrd_parameters.bit_rate_value_minus1[0] + 1) *
|
||||||
|
(1 << (sps->vui.nal_hrd_parameters.bit_rate_scale + 6));
|
||||||
|
} else if (sps->vui.vcl_hrd_parameters_present_flag) {
|
||||||
|
bit_rate = (sps->vui.vcl_hrd_parameters.bit_rate_value_minus1[0] + 1) *
|
||||||
|
(1 << (sps->vui.vcl_hrd_parameters.bit_rate_scale + 6));
|
||||||
|
// Adjust for VCL vs. NAL limits.
|
||||||
|
bit_rate = bit_rate * 6 / 5;
|
||||||
|
} else {
|
||||||
|
bit_rate = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
width = 16 * (sps->pic_width_in_mbs_minus1 + 1);
|
||||||
|
height = 16 * (sps->pic_height_in_map_units_minus1 + 1) *
|
||||||
|
(2 - sps->frame_mbs_only_flag);
|
||||||
|
|
||||||
|
desc = ff_h264_guess_level(sps->profile_idc, bit_rate,
|
||||||
|
width, height,
|
||||||
|
sps->vui.max_dec_frame_buffering);
|
||||||
|
if (desc) {
|
||||||
|
level_idc = desc->level_idc;
|
||||||
|
} else {
|
||||||
|
av_log(bsf, AV_LOG_WARNING, "Stream does not appear to "
|
||||||
|
"conform to any level: using level 6.2.\n");
|
||||||
|
level_idc = 62;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
level_idc = ctx->level;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (level_idc == 9) {
|
||||||
|
if (sps->profile_idc == 66 ||
|
||||||
|
sps->profile_idc == 77 ||
|
||||||
|
sps->profile_idc == 88) {
|
||||||
|
sps->level_idc = 10;
|
||||||
|
sps->constraint_set3_flag = 1;
|
||||||
|
} else {
|
||||||
|
sps->level_idc = 9;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sps->level_idc = level_idc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (need_vui)
|
if (need_vui)
|
||||||
sps->vui_parameters_present_flag = 1;
|
sps->vui_parameters_present_flag = 1;
|
||||||
|
|
||||||
|
@ -683,6 +743,36 @@ static const AVOption h264_metadata_options[] = {
|
||||||
0, AV_OPT_TYPE_CONST,
|
0, AV_OPT_TYPE_CONST,
|
||||||
{ .i64 = FLIP_VERTICAL }, .flags = FLAGS, .unit = "flip" },
|
{ .i64 = FLIP_VERTICAL }, .flags = FLAGS, .unit = "flip" },
|
||||||
|
|
||||||
|
{ "level", "Set level (table A-1)",
|
||||||
|
OFFSET(level), AV_OPT_TYPE_INT,
|
||||||
|
{ .i64 = LEVEL_UNSET }, LEVEL_UNSET, 0xff, FLAGS, "level" },
|
||||||
|
{ "auto", "Attempt to guess level from stream properties",
|
||||||
|
0, AV_OPT_TYPE_CONST,
|
||||||
|
{ .i64 = LEVEL_AUTO }, .flags = FLAGS, .unit = "level" },
|
||||||
|
#define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \
|
||||||
|
{ .i64 = value }, .flags = FLAGS, .unit = "level"
|
||||||
|
{ LEVEL("1", 10) },
|
||||||
|
{ LEVEL("1b", 9) },
|
||||||
|
{ LEVEL("1.1", 11) },
|
||||||
|
{ LEVEL("1.2", 12) },
|
||||||
|
{ LEVEL("1.3", 13) },
|
||||||
|
{ LEVEL("2", 20) },
|
||||||
|
{ LEVEL("2.1", 21) },
|
||||||
|
{ LEVEL("2.2", 22) },
|
||||||
|
{ LEVEL("3", 30) },
|
||||||
|
{ LEVEL("3.1", 31) },
|
||||||
|
{ LEVEL("3.2", 32) },
|
||||||
|
{ LEVEL("4", 40) },
|
||||||
|
{ LEVEL("4.1", 41) },
|
||||||
|
{ LEVEL("4.2", 42) },
|
||||||
|
{ LEVEL("5", 50) },
|
||||||
|
{ LEVEL("5.1", 51) },
|
||||||
|
{ LEVEL("5.2", 52) },
|
||||||
|
{ LEVEL("6", 60) },
|
||||||
|
{ LEVEL("6.1", 61) },
|
||||||
|
{ LEVEL("6.2", 62) },
|
||||||
|
#undef LEVEL
|
||||||
|
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue