From 2e7fee8e53c158c9eb5707cc23edc72a282a4f99 Mon Sep 17 00:00:00 2001 From: jpark37 Date: Sat, 18 Jul 2020 23:32:15 -0700 Subject: [PATCH 1/4] deps/libff: Remove very old version check --- deps/libff/libff/ff-util.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/deps/libff/libff/ff-util.c b/deps/libff/libff/ff-util.c index 87ad58108..b34c48a3b 100644 --- a/deps/libff/libff/ff-util.c +++ b/deps/libff/libff/ff-util.c @@ -291,7 +291,6 @@ static inline bool is_output_device(const AVClass *avclass) if (!avclass) return 0; -#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(52, 66, 101) switch (avclass->category) { case AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT: case AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT: @@ -300,9 +299,6 @@ static inline bool is_output_device(const AVClass *avclass) default: return false; } -#else - return (avclass->category == AV_CLASS_CATEGORY_OUTPUT); -#endif } const struct ff_format_desc *ff_format_supported() From f8cae4639e901fb914702cc93a85f4c6707e0b60 Mon Sep 17 00:00:00 2001 From: jpark37 Date: Sat, 18 Jul 2020 23:33:21 -0700 Subject: [PATCH 2/4] deps/media-playback: Remove unused #define --- deps/media-playback/media-playback/decode.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/deps/media-playback/media-playback/decode.h b/deps/media-playback/media-playback/decode.h index 9f2fd3c0d..f09058250 100644 --- a/deps/media-playback/media-playback/decode.h +++ b/deps/media-playback/media-playback/decode.h @@ -44,12 +44,6 @@ extern "C" { #define CODEC_FLAG_TRUNC CODEC_FLAG_TRUNCATED #endif -#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(54, 31, 100) -#define AV_PIX_FMT_VDTOOL AV_PIX_FMT_VIDEOTOOLBOX -#else -#define AV_PIX_FMT_VDTOOL AV_PIX_FMT_VDA_VLD -#endif - struct mp_media; struct mp_decode { From 06e4b10675c250a0e013788083a166673c8281e1 Mon Sep 17 00:00:00 2001 From: jpark37 Date: Sat, 18 Jul 2020 23:35:35 -0700 Subject: [PATCH 3/4] libobs/media-io: Add missing codec_tag set --- libobs/media-io/media-remux.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libobs/media-io/media-remux.c b/libobs/media-io/media-remux.c index feea64cb4..20fbc76f9 100644 --- a/libobs/media-io/media-remux.c +++ b/libobs/media-io/media-remux.c @@ -111,8 +111,10 @@ static inline bool init_output(media_remux_job_t job, const char *out_filename) av_dict_copy(&out_stream->metadata, in_stream->metadata, 0); +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101) + out_stream->codecpar->codec_tag = 0; +#else out_stream->codec->codec_tag = 0; -#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 48, 101) out_stream->time_base = out_stream->codec->time_base; if (job->ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) out_stream->codec->flags |= CODEC_FLAG_GLOBAL_H; From ffbc3ed9233b1626e858610912dc63ad6eadaa26 Mon Sep 17 00:00:00 2001 From: jpark37 Date: Sun, 19 Jul 2020 12:44:34 -0700 Subject: [PATCH 4/4] obs-ffmpeg: Fix race and deprecation warnings Attempt to simply shutdown sequence to avoid race between vidoe and write threads. Can no longer join on write thread from write thread. Also use codecpar instead of deprecated codec member. --- plugins/obs-ffmpeg/obs-ffmpeg-output.c | 88 ++++++++++++++++---------- plugins/obs-ffmpeg/obs-ffmpeg-output.h | 8 ++- 2 files changed, 63 insertions(+), 33 deletions(-) diff --git a/plugins/obs-ffmpeg/obs-ffmpeg-output.c b/plugins/obs-ffmpeg/obs-ffmpeg-output.c index 6c711f5ec..50f046254 100644 --- a/plugins/obs-ffmpeg/obs-ffmpeg-output.c +++ b/plugins/obs-ffmpeg/obs-ffmpeg-output.c @@ -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; @@ -180,6 +180,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; } @@ -218,7 +222,11 @@ static bool create_video_stream(struct ffmpeg_data *data) 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; @@ -234,6 +242,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 +260,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 +302,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 +326,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 +346,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 +356,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 +372,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 +423,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 +449,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 +473,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 +492,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 +581,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 +714,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; @@ -833,13 +859,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); @@ -868,7 +894,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 */ @@ -878,7 +904,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; @@ -916,7 +942,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; } @@ -949,10 +975,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; @@ -1159,12 +1183,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); } } diff --git a/plugins/obs-ffmpeg/obs-ffmpeg-output.h b/plugins/obs-ffmpeg/obs-ffmpeg-output.h index adb4494f6..f608d68aa 100644 --- a/plugins/obs-ffmpeg/obs-ffmpeg-output.h +++ b/plugins/obs-ffmpeg/obs-ffmpeg-output.h @@ -30,9 +30,15 @@ struct ffmpeg_cfg { int height; }; +struct ffmpeg_audio_info { + AVStream *stream; + AVCodecContext *ctx; +}; + struct ffmpeg_data { AVStream *video; - AVStream **audio_streams; + AVCodecContext *video_ctx; + struct ffmpeg_audio_info *audio_infos; AVCodec *acodec; AVCodec *vcodec; AVFormatContext *output;