Transcoding: Add audio bitrate limiter, video quantizer, tweaking of default encoder settings
This commit is contained in:
parent
ad8b61ba5a
commit
7b01d9c1f0
3 changed files with 56 additions and 14 deletions
|
@ -542,13 +542,16 @@ transcoder_stream_audio(transcoder_t *t, transcoder_stream_t *ts, th_pkt_t *pkt)
|
|||
}
|
||||
}
|
||||
|
||||
// User specified streaming profile audio bitrate limiter.
|
||||
if (t->t_props.tp_abitrate >=16) {
|
||||
octx->bit_rate = t->t_props.tp_abitrate * 1000;
|
||||
}
|
||||
|
||||
switch (ts->ts_type) {
|
||||
case SCT_MPEG2AUDIO:
|
||||
octx->bit_rate = 128000;
|
||||
break;
|
||||
|
||||
case SCT_AAC:
|
||||
octx->bit_rate = 128000;
|
||||
octx->flags |= CODEC_FLAG_BITEXACT;
|
||||
break;
|
||||
|
||||
|
@ -587,10 +590,10 @@ transcoder_stream_audio(transcoder_t *t, transcoder_stream_t *ts, th_pkt_t *pkt)
|
|||
// Convert audio
|
||||
tvhtrace("transcode", "%04X: converting audio", shortid(t));
|
||||
|
||||
tvhtrace("transcode", "%04X: IN : channels=%d, layout=%" PRIi64 ", rate=%d, fmt=%d, bitrate=%d",
|
||||
tvhinfo("transcode", "%04X: IN : channels=%d, layout=%" PRIi64 ", rate=%d, fmt=%d, bitrate=%d",
|
||||
shortid(t), ictx->channels, ictx->channel_layout, ictx->sample_rate,
|
||||
ictx->sample_fmt, ictx->bit_rate);
|
||||
tvhtrace("transcode", "%04X: OUT: channels=%d, layout=%" PRIi64 ", rate=%d, fmt=%d, bitrate=%d",
|
||||
tvhinfo("transcode", "%04X: OUT: channels=%d, layout=%" PRIi64 ", rate=%d, fmt=%d, bitrate=%d",
|
||||
shortid(t), octx->channels, octx->channel_layout, octx->sample_rate,
|
||||
octx->sample_fmt, octx->bit_rate);
|
||||
|
||||
|
@ -1043,7 +1046,7 @@ transcoder_stream_video(transcoder_t *t, transcoder_stream_t *ts, th_pkt_t *pkt)
|
|||
|
||||
} else {
|
||||
octx->bit_rate = t->t_props.tp_vbitrate * 1000;
|
||||
octx->rc_max_rate = octx->bit_rate * 1.05;
|
||||
octx->rc_max_rate = octx->bit_rate;
|
||||
}
|
||||
|
||||
octx->rc_buffer_size = 2 * octx->rc_max_rate;
|
||||
|
@ -1053,14 +1056,19 @@ transcoder_stream_video(transcoder_t *t, transcoder_stream_t *ts, th_pkt_t *pkt)
|
|||
octx->codec_id = AV_CODEC_ID_VP8;
|
||||
octx->pix_fmt = PIX_FMT_YUV420P;
|
||||
|
||||
av_dict_set(&opts, "quality", "realtime", 0);
|
||||
av_dict_set(&opts, "quality", "good", 0);
|
||||
|
||||
if (t->t_props.tp_vbitrate == 0) {
|
||||
octx->qmin = 10;
|
||||
octx->qmax = 20;
|
||||
} else {
|
||||
}
|
||||
|
||||
// Stream profile vbitrate 1-63 is used for user specified qmin quantizer (CRF mode).
|
||||
if (t->t_props.tp_vbitrate >0 && t->t_props.tp_vbitrate <64) {
|
||||
octx->qmin = t->t_props.tp_vbitrate; // qmax = 63 as default.
|
||||
} else { // CBR mode.
|
||||
octx->bit_rate = t->t_props.tp_vbitrate * 1000;
|
||||
octx->rc_max_rate = octx->bit_rate * 1.05;
|
||||
octx->rc_max_rate = octx->bit_rate;
|
||||
}
|
||||
|
||||
octx->rc_buffer_size = 8 * 1024 * 224;
|
||||
|
@ -1088,16 +1096,29 @@ transcoder_stream_video(transcoder_t *t, transcoder_stream_t *ts, th_pkt_t *pkt)
|
|||
// Recommended default: -qmax 51
|
||||
// octx->qmax = 30;
|
||||
|
||||
av_dict_set(&opts, "preset", "medium", 0);
|
||||
av_dict_set(&opts, "profile", "baseline", 0);
|
||||
av_dict_set(&opts, "preset", "veryfast", 0);
|
||||
// Use main profile instead of the standard "baseline", we are aiming for better quality.
|
||||
// Older devices (iPhone <4, Android <4) only supports baseline. Chromecast only supports >=4.1...
|
||||
av_dict_set(&opts, "profile", "main", 0); // L3.0
|
||||
av_dict_set(&opts, "tune", "zerolatency", 0);
|
||||
|
||||
if (t->t_props.tp_vbitrate == 0) {
|
||||
// If we are encoding HD, upgrade the profile to high.
|
||||
if (octx->height >= 720 && t->t_props.tp_resolution >=720) {
|
||||
av_dict_set(&opts, "profile", "high", 0); // L3.1
|
||||
}
|
||||
|
||||
// Default "auto" CRF settings. Aimed for quality without being too agressive.
|
||||
if (t->t_props.tp_vbitrate == 0 ) {
|
||||
octx->qmin = 10;
|
||||
octx->qmax = 30;
|
||||
} else {
|
||||
}
|
||||
|
||||
// Stream profile vbitrate 1-63 is used for user specified qmin quantizer (CRF mode).
|
||||
if (t->t_props.tp_vbitrate >0 && t->t_props.tp_vbitrate <64) {
|
||||
octx->qmin = t->t_props.tp_vbitrate; // qmax = 51 in all default profiles, let's stick with it for now.
|
||||
} else { // Bitrate limited encoding (CBR mode).
|
||||
octx->bit_rate = t->t_props.tp_vbitrate * 1000;
|
||||
octx->rc_max_rate = octx->bit_rate * 1.05;
|
||||
octx->rc_max_rate = octx->bit_rate;
|
||||
}
|
||||
|
||||
octx->rc_buffer_size = 8 * 1024 * 224;
|
||||
|
@ -1406,8 +1427,10 @@ transcoder_init_audio(transcoder_t *t, streaming_start_component_t *ssc)
|
|||
|
||||
sct = codec_id2streaming_component_type(ocodec->id);
|
||||
|
||||
if (sct == ssc->ssc_type)
|
||||
// Don't transcode to identical output codec unless the streaming profile specifies a bitrate limiter.
|
||||
if (sct == ssc->ssc_type && t->t_props.tp_abitrate <16 ) {
|
||||
return transcoder_init_stream(t, ssc);
|
||||
}
|
||||
|
||||
as = calloc(1, sizeof(audio_stream_t));
|
||||
|
||||
|
@ -1767,6 +1790,7 @@ transcoder_set_properties(streaming_target_t *st,
|
|||
tp->tp_channels = props->tp_channels;
|
||||
tp->tp_bandwidth = props->tp_bandwidth;
|
||||
tp->tp_vbitrate = props->tp_vbitrate;
|
||||
tp->tp_abitrate = props->tp_abitrate;
|
||||
tp->tp_resolution = props->tp_resolution;
|
||||
|
||||
memcpy(tp->tp_language, props->tp_language, 4);
|
||||
|
|
|
@ -28,6 +28,7 @@ typedef struct transcoder_prop {
|
|||
int8_t tp_channels;
|
||||
int32_t tp_bandwidth;
|
||||
int32_t tp_vbitrate;
|
||||
int32_t tp_abitrate;
|
||||
char tp_language[4];
|
||||
int32_t tp_resolution;
|
||||
|
||||
|
|
|
@ -1020,6 +1020,7 @@ typedef struct profile_transcode {
|
|||
uint32_t pro_channels;
|
||||
uint32_t pro_bandwidth;
|
||||
uint32_t pro_vbitrate;
|
||||
uint32_t pro_abitrate;
|
||||
char *pro_language;
|
||||
char *pro_vcodec;
|
||||
char *pro_acodec;
|
||||
|
@ -1230,6 +1231,13 @@ const idclass_t profile_transcode_class =
|
|||
.def.s = "libvorbis",
|
||||
.list = profile_class_acodec_list,
|
||||
},
|
||||
{
|
||||
.type = PT_U32,
|
||||
.id = "abitrate",
|
||||
.name = "Audio Bitrate (kb/s) (0=Auto)",
|
||||
.off = offsetof(profile_transcode_t, pro_abitrate),
|
||||
.def.u32 = 0,
|
||||
},
|
||||
{
|
||||
.type = PT_STR,
|
||||
.id = "scodec",
|
||||
|
@ -1260,6 +1268,12 @@ profile_transcode_vbitrate(profile_transcode_t *pro)
|
|||
return pro->pro_vbitrate;
|
||||
}
|
||||
|
||||
static int
|
||||
profile_transcode_abitrate(profile_transcode_t *pro)
|
||||
{
|
||||
return pro->pro_abitrate;
|
||||
}
|
||||
|
||||
static int
|
||||
profile_transcode_can_share(profile_chain_t *prch,
|
||||
profile_chain_t *joiner)
|
||||
|
@ -1286,6 +1300,8 @@ profile_transcode_can_share(profile_chain_t *prch,
|
|||
return 0;
|
||||
if (profile_transcode_vbitrate(pro1) != profile_transcode_vbitrate(pro2))
|
||||
return 0;
|
||||
if (profile_transcode_abitrate(pro1) != profile_transcode_abitrate(pro2))
|
||||
return 0;
|
||||
if (strcmp(pro1->pro_language ?: "", pro2->pro_language ?: ""))
|
||||
return 0;
|
||||
return 1;
|
||||
|
@ -1314,6 +1330,7 @@ profile_transcode_work(profile_chain_t *prch,
|
|||
props.tp_channels = pro->pro_channels;
|
||||
props.tp_bandwidth = profile_transcode_bandwidth(pro);
|
||||
props.tp_vbitrate = profile_transcode_vbitrate(pro);
|
||||
props.tp_abitrate = profile_transcode_abitrate(pro);
|
||||
strncpy(props.tp_language, pro->pro_language ?: "", 3);
|
||||
|
||||
dst = prch->prch_gh = globalheaders_create(dst);
|
||||
|
|
Loading…
Add table
Reference in a new issue