Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix a possible crash in avformat probe #944

Merged
merged 2 commits into from
Sep 4, 2023
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 27 additions & 27 deletions src/modules/avformat/producer_avformat.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ struct producer_avformat_s
int video_index;
int64_t first_pts;
atomic_int_fast64_t last_position;
int probe_complete;
int video_seekable;
int seekable; /// This one is used for both audio and file level seekability.
atomic_int_fast64_t current_position;
Expand Down Expand Up @@ -1505,28 +1504,28 @@ static int pick_av_pixel_format(int *pix_fmt, int full_range)

static void property_changed(mlt_service owner, producer_avformat self, char *name)
{
if (self && name) {
if (self && name && self->parent) {
mlt_properties properties = MLT_PRODUCER_PROPERTIES(self->parent);
if (!strcmp("color_range", name)) {
if (self->video_codec
&& !av_opt_set(self->video_codec,
name,
mlt_properties_get(MLT_PRODUCER_PROPERTIES(self->parent), name),
mlt_properties_get(properties, name),
AV_OPT_SEARCH_CHILDREN)) {
if (self->full_range != (self->video_codec->color_range == AVCOL_RANGE_JPEG)) {
self->full_range = self->video_codec->color_range == AVCOL_RANGE_JPEG;
self->reset_image_cache = 1;
}
}
} else if (!strcmp("force_full_range", name) || !strcmp("set.force_full_luma", name)) {
mlt_properties properties = MLT_PRODUCER_PROPERTIES(self->parent);
if (self->full_range != mlt_properties_get_int(properties, name)) {
self->full_range = mlt_properties_get_int(properties, name);
self->reset_image_cache = 1;
}
} else if (!strcmp("force_progressive", name) || !strcmp("force_tff", name)) {
self->reset_image_cache = 1;
} else if (!strcmp("autorotate", name)) {
self->autorotate = mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(self->parent), name);
self->autorotate = mlt_properties_get_int(properties, name);
if (self->video_index != -1) {
mlt_service_lock(MLT_PRODUCER_SERVICE(self->parent));
avfilter_graph_free(&self->vfilter_graph);
Expand All @@ -1536,6 +1535,10 @@ static void property_changed(mlt_service owner, producer_avformat self, char *na
self->reset_image_cache = 1;
mlt_service_unlock(MLT_PRODUCER_SERVICE(self->parent));
}
} else if (!strcmp("video_index", name) || !strcmp("vstream", name)) {
if (mlt_properties_get_int(properties, "_probe_complete")) {
mlt_properties_set_int(properties, "_probe_complete", 0);
}
}
}
}
Expand Down Expand Up @@ -2540,7 +2543,7 @@ static int producer_get_image(mlt_frame frame,
// Set immutable properties of the selected track's (or overridden) source attributes.
mlt_properties_set_int(properties, "meta.media.top_field_first", self->top_field_first);
mlt_properties_set_int(properties, "meta.media.progressive", self->progressive);
self->probe_complete = 1;
mlt_properties_set_int(properties, "_probe_complete", 1);
mlt_service_unlock(MLT_PRODUCER_SERVICE(producer));

mlt_log_timings_end(NULL, __FUNCTION__);
Expand Down Expand Up @@ -2922,7 +2925,7 @@ static void producer_set_up_video(producer_avformat self, mlt_frame frame)
if (context && index > -1 && index != self->video_index) {
// Reset the video properties if the index changed
self->video_index = index;
self->probe_complete = 0;
mlt_properties_set_int(properties, "_probe_complete", 0);
pthread_mutex_lock(&self->open_mutex);
avcodec_free_context(&self->video_codec);
set_up_discard(self, self->audio_index, index);
Expand Down Expand Up @@ -3682,7 +3685,7 @@ static void producer_set_up_audio(producer_avformat self, mlt_frame frame)
1,
0);
context = self->audio_format;
self->probe_complete = 0;
mlt_properties_set_int(properties, "_probe_complete", 0);
}
index = pick_audio_stream(self);

Expand Down Expand Up @@ -3741,7 +3744,6 @@ static int producer_get_frame(mlt_producer producer, mlt_frame_ptr frame, int in
// If cache miss
if (!self) {
self = calloc(1, sizeof(struct producer_avformat_s));
producer->child = self;
ddennedy marked this conversation as resolved.
Show resolved Hide resolved
self->parent = producer;
mlt_service_cache_put(service,
"producer_avformat",
Expand Down Expand Up @@ -3784,7 +3786,8 @@ static int producer_get_frame(mlt_producer producer, mlt_frame_ptr frame, int in
mlt_position position = mlt_producer_frame(producer);
mlt_properties_set_position(frame_properties, "original_position", position);

if (!self->probe_complete && self->video_index < 0) {
if (!mlt_properties_get_int(MLT_PRODUCER_PROPERTIES(producer), "_probe_complete")
&& self->video_index < 0) {
// If video index is valid, get_image() must be called before the probe is complete
mlt_properties_clear(MLT_PRODUCER_PROPERTIES(producer), "meta.media.width");
mlt_properties_clear(MLT_PRODUCER_PROPERTIES(producer), "meta.media.height");
Expand All @@ -3794,7 +3797,6 @@ static int producer_get_frame(mlt_producer producer, mlt_frame_ptr frame, int in
mlt_properties_clear(MLT_PRODUCER_PROPERTIES(producer), "meta.media.sample_aspect_num");
mlt_properties_clear(MLT_PRODUCER_PROPERTIES(producer), "meta.media.sample_aspect_den");
mlt_properties_clear(MLT_PRODUCER_PROPERTIES(producer), "meta.media.top_field_first");
mlt_properties_clear(MLT_PRODUCER_PROPERTIES(producer), "meta.media.progressive");
mlt_properties_clear(MLT_PRODUCER_PROPERTIES(producer), "meta.media.variable_frame_rate");
mlt_properties_clear(MLT_PRODUCER_PROPERTIES(producer), "meta.media.colorspace");
mlt_properties_clear(MLT_PRODUCER_PROPERTIES(producer), "meta.media.color_trc");
Expand All @@ -3803,7 +3805,7 @@ static int producer_get_frame(mlt_producer producer, mlt_frame_ptr frame, int in
mlt_properties_clear(MLT_PRODUCER_PROPERTIES(producer), "width");
mlt_properties_clear(MLT_PRODUCER_PROPERTIES(producer), "height");
mlt_properties_clear(MLT_PRODUCER_PROPERTIES(producer), "format");
self->probe_complete = 1;
mlt_properties_set_int(MLT_PRODUCER_PROPERTIES(producer), "_probe_complete", 1);
}

// Calculate the next timecode
Expand All @@ -3814,33 +3816,31 @@ static int producer_get_frame(mlt_producer producer, mlt_frame_ptr frame, int in

static int producer_probe(mlt_producer producer)
{
producer_avformat self = producer->child;
int error = 0;
mlt_properties properties = MLT_PRODUCER_PROPERTIES(producer);

// Update the video properties if the index changed
int video_index = pick_video_stream(self);

if (self->video_format && video_index > -1 && video_index != self->video_index)
self->probe_complete = 0;

// Update the audio properties if the index changed
int audio_index = pick_audio_stream(self);

if (self->audio_format && audio_index > -1 && audio_index != self->audio_index)
self->probe_complete = 0;

if (self->probe_complete) {
if (mlt_properties_get_int(properties, "_probe_complete")) {
return error;
}

if (!mlt_properties_exists(properties, "_probe_complete")) {
// If metadata was loaded from XML, no need to probe
int video_in_use = mlt_properties_get_int(properties, "vstream") > -1;
if (video_in_use && mlt_properties_exists(properties, "meta.media.progressive")) {
return error;
} else if (!video_in_use && mlt_properties_exists(properties, "meta.media.0.codec.name")) {
ddennedy marked this conversation as resolved.
Show resolved Hide resolved
return error;
}
}

mlt_frame fr = NULL;
mlt_position save_position = mlt_producer_position(producer);

// Call producer_get_frame() directly so that the underlying service will not attach any normalizers
mlt_service_lock(MLT_PRODUCER_SERVICE(producer));
error = producer_get_frame(producer, &fr, 0);
mlt_service_unlock(MLT_PRODUCER_SERVICE(producer));
if (!error && fr && self->video_index > -1) {
if (!error && fr && mlt_properties_get_int(properties, "vstream") > -1) {
// Some video metadata is not exposed until after the first get_image call.
uint8_t *buffer = NULL;
mlt_image_format fmt = mlt_image_none;
Expand Down
Loading