New upstream version 26.0.0+dfsg1

This commit is contained in:
Sebastian Ramacher 2020-10-01 22:15:25 +02:00
parent 8e020cdacb
commit 240080891f
837 changed files with 41275 additions and 9196 deletions

View file

@ -135,7 +135,7 @@ static bool parse_params(AVCodecContext *context, char **opts)
static bool open_video_codec(struct ffmpeg_data *data)
{
AVCodecContext *context = data->video->codec;
AVCodecContext *const context = data->video_ctx;
char **opts = strlist_split(data->config.video_settings, ' ', false);
int ret;
@ -169,8 +169,10 @@ static bool open_video_codec(struct ffmpeg_data *data)
data->vframe->format = context->pix_fmt;
data->vframe->width = context->width;
data->vframe->height = context->height;
data->vframe->colorspace = data->config.color_space;
data->vframe->color_range = data->config.color_range;
data->vframe->color_primaries = data->config.color_primaries;
data->vframe->color_trc = data->config.color_trc;
data->vframe->colorspace = data->config.colorspace;
ret = av_frame_get_buffer(data->vframe, base_get_alignment());
if (ret < 0) {
@ -180,6 +182,10 @@ static bool open_video_codec(struct ffmpeg_data *data)
return false;
}
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
avcodec_parameters_from_context(data->video->codecpar, context);
#endif
return true;
}
@ -215,18 +221,27 @@ static bool create_video_stream(struct ffmpeg_data *data)
data->config.video_encoder))
return false;
closest_format = avcodec_find_best_pix_fmt_of_list(
data->vcodec->pix_fmts, data->config.format, 0, NULL);
closest_format = data->config.format;
if (data->vcodec->pix_fmts) {
closest_format = avcodec_find_best_pix_fmt_of_list(
data->vcodec->pix_fmts, data->config.format, 0, NULL);
}
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
context = avcodec_alloc_context3(data->vcodec);
#else
context = data->video->codec;
#endif
context->bit_rate = (int64_t)data->config.video_bitrate * 1000;
context->width = data->config.scale_width;
context->height = data->config.scale_height;
context->time_base = (AVRational){ovi.fps_den, ovi.fps_num};
context->gop_size = data->config.gop_size;
context->pix_fmt = closest_format;
context->colorspace = data->config.color_space;
context->color_range = data->config.color_range;
context->color_primaries = data->config.color_primaries;
context->color_trc = data->config.color_trc;
context->colorspace = data->config.colorspace;
context->thread_count = 0;
data->video->time_base = context->time_base;
@ -234,6 +249,8 @@ static bool create_video_stream(struct ffmpeg_data *data)
if (data->output->oformat->flags & AVFMT_GLOBALHEADER)
context->flags |= CODEC_FLAG_GLOBAL_H;
data->video_ctx = context;
if (!open_video_codec(data))
return false;
@ -250,7 +267,7 @@ static bool create_video_stream(struct ffmpeg_data *data)
static bool open_audio_codec(struct ffmpeg_data *data, int idx)
{
AVCodecContext *context = data->audio_streams[idx]->codec;
AVCodecContext *const context = data->audio_infos[idx].ctx;
char **opts = strlist_split(data->config.audio_settings, ' ', false);
int ret;
@ -292,6 +309,11 @@ static bool open_audio_codec(struct ffmpeg_data *data, int idx)
return false;
}
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
avcodec_parameters_from_context(data->audio_infos[idx].stream->codecpar,
context);
#endif
return true;
}
@ -311,8 +333,11 @@ static bool create_audio_stream(struct ffmpeg_data *data, int idx)
data->config.audio_encoder))
return false;
data->audio_streams[idx] = stream;
context = data->audio_streams[idx]->codec;
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
context = avcodec_alloc_context3(data->acodec);
#else
context = stream->codec;
#endif
context->bit_rate = (int64_t)data->config.audio_bitrate * 1000;
context->time_base = (AVRational){1, aoi.samples_per_sec};
context->channels = get_audio_channels(aoi.speakers);
@ -328,7 +353,7 @@ static bool create_audio_stream(struct ffmpeg_data *data, int idx)
? data->acodec->sample_fmts[0]
: AV_SAMPLE_FMT_FLTP;
data->audio_streams[idx]->time_base = context->time_base;
stream->time_base = context->time_base;
data->audio_samplerate = aoi.samples_per_sec;
data->audio_format = convert_ffmpeg_sample_format(context->sample_fmt);
@ -338,6 +363,9 @@ static bool create_audio_stream(struct ffmpeg_data *data, int idx)
if (data->output->oformat->flags & AVFMT_GLOBALHEADER)
context->flags |= CODEC_FLAG_GLOBAL_H;
data->audio_infos[idx].stream = stream;
data->audio_infos[idx].ctx = context;
return open_audio_codec(data, idx);
}
@ -351,8 +379,8 @@ static inline bool init_streams(struct ffmpeg_data *data)
if (format->audio_codec != AV_CODEC_ID_NONE &&
data->num_audio_streams) {
data->audio_streams =
calloc(1, data->num_audio_streams * sizeof(void *));
data->audio_infos = calloc(data->num_audio_streams,
sizeof(*data->audio_infos));
for (int i = 0; i < data->num_audio_streams; i++) {
if (!create_audio_stream(data, i))
return false;
@ -402,10 +430,6 @@ static inline bool open_output_file(struct ffmpeg_data *data)
}
}
strncpy(data->output->filename, data->config.url,
sizeof(data->output->filename));
data->output->filename[sizeof(data->output->filename) - 1] = 0;
ret = avformat_write_header(data->output, &dict);
if (ret < 0) {
ffmpeg_log_error(LOG_WARNING, data, "Error opening '%s': %s",
@ -432,7 +456,11 @@ static inline bool open_output_file(struct ffmpeg_data *data)
static void close_video(struct ffmpeg_data *data)
{
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
avcodec_free_context(&data->video_ctx);
#else
avcodec_close(data->video->codec);
#endif
av_frame_unref(data->vframe);
// This format for some reason derefs video frame
@ -452,8 +480,13 @@ static void close_audio(struct ffmpeg_data *data)
if (data->samples[idx][0])
av_freep(&data->samples[idx][0]);
if (data->audio_streams[idx])
avcodec_close(data->audio_streams[idx]->codec);
if (data->audio_infos[idx].ctx) {
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
avcodec_free_context(&data->audio_infos[idx].ctx);
#else
avcodec_close(data->audio_infos[idx].stream->codec);
#endif
}
if (data->aframe[idx])
av_frame_free(&data->aframe[idx]);
}
@ -466,10 +499,10 @@ void ffmpeg_data_free(struct ffmpeg_data *data)
if (data->video)
close_video(data);
if (data->audio_streams) {
if (data->audio_infos) {
close_audio(data);
free(data->audio_streams);
data->audio_streams = NULL;
free(data->audio_infos);
data->audio_infos = NULL;
}
if (data->output) {
@ -555,7 +588,7 @@ bool ffmpeg_data_init(struct ffmpeg_data *data, struct ffmpeg_cfg *config)
}
avformat_alloc_output_context2(&data->output, output_format, NULL,
NULL);
data->config.url);
if (!data->output) {
ffmpeg_log_error(LOG_WARNING, data,
@ -688,7 +721,7 @@ static void receive_video(void *param, struct video_data *frame)
if (!data->video)
return;
AVCodecContext *context = data->video->codec;
AVCodecContext *context = data->video_ctx;
AVPacket packet = {0};
int ret = 0, got_packet;
@ -699,6 +732,15 @@ static void receive_video(void *param, struct video_data *frame)
if (!data->start_timestamp)
data->start_timestamp = frame->timestamp;
ret = av_frame_make_writable(data->vframe);
if (ret < 0) {
blog(LOG_WARNING,
"receive_video: Error obtaining writable "
"AVFrame: %s",
av_err2str(ret));
//FIXME: stop the encode with an error
return;
}
if (!!data->swscale)
sws_scale(data->swscale, (const uint8_t *const *)frame->data,
(const int *)frame->linesize, 0, data->config.height,
@ -824,13 +866,13 @@ static void encode_audio(struct ffmpeg_output *output, int idx,
return;
packet.pts = rescale_ts(packet.pts, context,
data->audio_streams[idx]->time_base);
data->audio_infos[idx].stream->time_base);
packet.dts = rescale_ts(packet.dts, context,
data->audio_streams[idx]->time_base);
data->audio_infos[idx].stream->time_base);
packet.duration =
(int)av_rescale_q(packet.duration, context->time_base,
data->audio_streams[idx]->time_base);
packet.stream_index = data->audio_streams[idx]->index;
data->audio_infos[idx].stream->time_base);
packet.stream_index = data->audio_infos[idx].stream->index;
pthread_mutex_lock(&output->write_mutex);
da_push_back(output->packets, &packet);
@ -859,7 +901,7 @@ static void receive_audio(void *param, size_t mix_idx, struct audio_data *frame)
int track_order;
// codec doesn't support audio or none configured
if (!data->audio_streams)
if (!data->audio_infos)
return;
/* check that the track was selected */
@ -869,7 +911,7 @@ static void receive_audio(void *param, size_t mix_idx, struct audio_data *frame)
/* get track order (first selected, etc ...) */
track_order = get_track_order(data->audio_tracks, mix_idx);
AVCodecContext *context = data->audio_streams[track_order]->codec;
AVCodecContext *context = data->audio_infos[track_order].ctx;
if (!data->start_timestamp)
return;
@ -907,7 +949,7 @@ static uint64_t get_packet_sys_dts(struct ffmpeg_output *output,
time_base = data->video->time_base;
start_ts = output->video_start_ts;
} else {
time_base = data->audio_streams[0]->time_base;
time_base = data->audio_infos[0].stream->time_base;
start_ts = output->audio_start_ts;
}
@ -940,10 +982,8 @@ static int process_packet(struct ffmpeg_output *output)
if (stopping(output)) {
uint64_t sys_ts = get_packet_sys_dts(output, &packet);
if (sys_ts >= output->stop_ts) {
ffmpeg_output_full_stop(output);
if (sys_ts >= output->stop_ts)
return 0;
}
}
output->total_bytes += packet.size;
@ -952,7 +992,7 @@ static int process_packet(struct ffmpeg_output *output)
if (ret < 0) {
av_free_packet(&packet);
ffmpeg_log_error(LOG_WARNING, &output->ff_data,
"receive_audio: Error writing packet: %s",
"process_packet: Error writing packet: %s",
av_err2str(ret));
return ret;
}
@ -1048,16 +1088,30 @@ static bool try_connect(struct ffmpeg_output *output)
config.audio_tracks = (int)obs_output_get_mixers(output->output);
config.audio_mix_count = get_audio_mix_count(config.audio_tracks);
config.color_range = voi->range == VIDEO_RANGE_FULL ? AVCOL_RANGE_JPEG
: AVCOL_RANGE_MPEG;
switch (voi->colorspace) {
case VIDEO_CS_601:
config.color_primaries = AVCOL_PRI_SMPTE170M;
config.color_trc = AVCOL_TRC_SMPTE170M;
break;
case VIDEO_CS_DEFAULT:
case VIDEO_CS_709:
config.color_primaries = AVCOL_PRI_BT709;
config.color_trc = AVCOL_TRC_BT709;
break;
case VIDEO_CS_SRGB:
config.color_primaries = AVCOL_PRI_BT709;
config.color_trc = AVCOL_TRC_IEC61966_2_1;
break;
}
if (format_is_yuv(voi->format)) {
config.color_range = voi->range == VIDEO_RANGE_FULL
? AVCOL_RANGE_JPEG
: AVCOL_RANGE_MPEG;
config.color_space = voi->colorspace == VIDEO_CS_709
? AVCOL_SPC_BT709
: AVCOL_SPC_BT470BG;
config.colorspace = (voi->colorspace == VIDEO_CS_601)
? AVCOL_SPC_SMPTE170M
: AVCOL_SPC_BT709;
} else {
config.color_range = AVCOL_RANGE_UNSPECIFIED;
config.color_space = AVCOL_SPC_RGB;
config.colorspace = AVCOL_SPC_RGB;
}
if (config.format == AV_PIX_FMT_NONE) {
@ -1150,12 +1204,12 @@ static void ffmpeg_output_stop(void *data, uint64_t ts)
struct ffmpeg_output *output = data;
if (output->active) {
if (ts == 0) {
ffmpeg_output_full_stop(output);
} else {
os_atomic_set_bool(&output->stopping, true);
if (ts > 0) {
output->stop_ts = ts;
os_atomic_set_bool(&output->stopping, true);
}
ffmpeg_output_full_stop(output);
}
}