mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-06 15:38:53 +00:00
gst/matroska/matroska-mux.c: Fix possible deadlock in matroska muxer (#327825).
Original commit message from CVS: Reviewed by: Tim-Philipp Müller <tim at centricular dot net> * gst/matroska/matroska-mux.c: (gst_matroska_mux_best_pad), (gst_matroska_mux_write_data), (gst_matroska_mux_collected): Fix possible deadlock in matroska muxer (#327825).
This commit is contained in:
parent
f42029d79f
commit
00c44209d8
2 changed files with 50 additions and 29 deletions
|
@ -1,3 +1,11 @@
|
||||||
|
2006-01-23 Michal Benes <michal dot benes at xeris dot cz>
|
||||||
|
|
||||||
|
Reviewed by: Tim-Philipp Müller <tim at centricular dot net>
|
||||||
|
|
||||||
|
* gst/matroska/matroska-mux.c: (gst_matroska_mux_best_pad),
|
||||||
|
(gst_matroska_mux_write_data), (gst_matroska_mux_collected):
|
||||||
|
Fix possible deadlock in matroska muxer (#327825).
|
||||||
|
|
||||||
2006-01-23 Tim-Philipp Müller <tim at centricular dot net>
|
2006-01-23 Tim-Philipp Müller <tim at centricular dot net>
|
||||||
|
|
||||||
* ext/libpng/gstpngenc.c: (gst_pngenc_chain):
|
* ext/libpng/gstpngenc.c: (gst_pngenc_chain):
|
||||||
|
|
|
@ -1244,6 +1244,7 @@ gst_matroska_mux_finish (GstMatroskaMux * mux)
|
||||||
/**
|
/**
|
||||||
* gst_matroska_mux_best_pad:
|
* gst_matroska_mux_best_pad:
|
||||||
* @mux: #GstMatroskaMux
|
* @mux: #GstMatroskaMux
|
||||||
|
* @popped: True if at least one buffer was popped from #GstCollectPads
|
||||||
*
|
*
|
||||||
* Find a pad with the oldest data
|
* Find a pad with the oldest data
|
||||||
* (data from this pad should be written first).
|
* (data from this pad should be written first).
|
||||||
|
@ -1251,11 +1252,12 @@ gst_matroska_mux_finish (GstMatroskaMux * mux)
|
||||||
* Returns: Selected pad.
|
* Returns: Selected pad.
|
||||||
*/
|
*/
|
||||||
static GstMatroskaPad *
|
static GstMatroskaPad *
|
||||||
gst_matroska_mux_best_pad (GstMatroskaMux * mux)
|
gst_matroska_mux_best_pad (GstMatroskaMux * mux, gboolean * popped)
|
||||||
{
|
{
|
||||||
GSList *collected;
|
GSList *collected;
|
||||||
GstMatroskaPad *best = NULL;
|
GstMatroskaPad *best = NULL;
|
||||||
|
|
||||||
|
*popped = FALSE;
|
||||||
for (collected = mux->collect->data; collected;
|
for (collected = mux->collect->data; collected;
|
||||||
collected = g_slist_next (collected)) {
|
collected = g_slist_next (collected)) {
|
||||||
GstMatroskaPad *collect_pad;
|
GstMatroskaPad *collect_pad;
|
||||||
|
@ -1265,6 +1267,9 @@ gst_matroska_mux_best_pad (GstMatroskaMux * mux)
|
||||||
if (collect_pad->buffer == NULL) {
|
if (collect_pad->buffer == NULL) {
|
||||||
collect_pad->buffer = gst_collect_pads_pop (mux->collect,
|
collect_pad->buffer = gst_collect_pads_pop (mux->collect,
|
||||||
(GstCollectData *) collect_pad);
|
(GstCollectData *) collect_pad);
|
||||||
|
|
||||||
|
if (collect_pad->buffer != NULL)
|
||||||
|
*popped = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if we have a buffer check if it is better then the current best one */
|
/* if we have a buffer check if it is better then the current best one */
|
||||||
|
@ -1312,15 +1317,15 @@ gst_matroska_mux_create_buffer_header (GstMatroskaTrackContext * track,
|
||||||
/**
|
/**
|
||||||
* gst_matroska_mux_write_data:
|
* gst_matroska_mux_write_data:
|
||||||
* @mux: #GstMatroskaMux
|
* @mux: #GstMatroskaMux
|
||||||
|
* @collect_pad: #GstMatroskaPad with the data
|
||||||
*
|
*
|
||||||
* Write collected data (called from gst_matroska_mux_collected).
|
* Write collected data (called from gst_matroska_mux_collected).
|
||||||
*
|
*
|
||||||
* Returns: Result of the gst_pad_push issued to write the data.
|
* Returns: Result of the gst_pad_push issued to write the data.
|
||||||
*/
|
*/
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_matroska_mux_write_data (GstMatroskaMux * mux)
|
gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad)
|
||||||
{
|
{
|
||||||
GstMatroskaPad *best;
|
|
||||||
GstEbmlWrite *ebml = mux->ebml_write;
|
GstEbmlWrite *ebml = mux->ebml_write;
|
||||||
GstBuffer *buf, *hdr;
|
GstBuffer *buf, *hdr;
|
||||||
guint64 cluster, blockgroup;
|
guint64 cluster, blockgroup;
|
||||||
|
@ -1328,21 +1333,9 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux)
|
||||||
guint16 relative_timestamp;
|
guint16 relative_timestamp;
|
||||||
guint64 block_duration;
|
guint64 block_duration;
|
||||||
|
|
||||||
/* which stream to write from? */
|
|
||||||
best = gst_matroska_mux_best_pad (mux);
|
|
||||||
|
|
||||||
/* if there is no best pad, we have reached EOS */
|
|
||||||
if (best == NULL) {
|
|
||||||
GST_DEBUG_OBJECT (mux, "No best pad finishing...");
|
|
||||||
gst_matroska_mux_finish (mux);
|
|
||||||
gst_pad_push_event (mux->srcpad, gst_event_new_eos ());
|
|
||||||
return GST_FLOW_WRONG_STATE;
|
|
||||||
}
|
|
||||||
GST_DEBUG_OBJECT (best->collect.pad, "best pad");
|
|
||||||
|
|
||||||
/* write data */
|
/* write data */
|
||||||
buf = best->buffer;
|
buf = collect_pad->buffer;
|
||||||
best->buffer = NULL;
|
collect_pad->buffer = NULL;
|
||||||
|
|
||||||
/* set the timestamp for outgoing buffers */
|
/* set the timestamp for outgoing buffers */
|
||||||
ebml->timestamp = GST_BUFFER_TIMESTAMP (buf);
|
ebml->timestamp = GST_BUFFER_TIMESTAMP (buf);
|
||||||
|
@ -1390,14 +1383,14 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux)
|
||||||
|
|
||||||
/* update duration of this track */
|
/* update duration of this track */
|
||||||
if (GST_BUFFER_DURATION_IS_VALID (buf))
|
if (GST_BUFFER_DURATION_IS_VALID (buf))
|
||||||
best->duration += GST_BUFFER_DURATION (buf);
|
collect_pad->duration += GST_BUFFER_DURATION (buf);
|
||||||
|
|
||||||
/* We currently write an index entry for each keyframe in a
|
/* We currently write an index entry for each keyframe in a
|
||||||
* video track or one entry for each cluster in an audio track
|
* video track or one entry for each cluster in an audio track
|
||||||
* for audio only files. This can be largely improved, such as doing
|
* for audio only files. This can be largely improved, such as doing
|
||||||
* one for each keyframe or each second (for all-keyframe
|
* one for each keyframe or each second (for all-keyframe
|
||||||
* streams), only the *first* video track. But that'll come later... */
|
* streams), only the *first* video track. But that'll come later... */
|
||||||
if (best->track->type == GST_MATROSKA_TRACK_TYPE_VIDEO &&
|
if (collect_pad->track->type == GST_MATROSKA_TRACK_TYPE_VIDEO &&
|
||||||
!GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT)) {
|
!GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT)) {
|
||||||
GstMatroskaIndex *idx;
|
GstMatroskaIndex *idx;
|
||||||
|
|
||||||
|
@ -1409,8 +1402,8 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux)
|
||||||
|
|
||||||
idx->pos = mux->cluster_pos;
|
idx->pos = mux->cluster_pos;
|
||||||
idx->time = GST_BUFFER_TIMESTAMP (buf);
|
idx->time = GST_BUFFER_TIMESTAMP (buf);
|
||||||
idx->track = best->track->num;
|
idx->track = collect_pad->track->num;
|
||||||
} else if ((best->track->type == GST_MATROSKA_TRACK_TYPE_AUDIO) &&
|
} else if ((collect_pad->track->type == GST_MATROSKA_TRACK_TYPE_AUDIO) &&
|
||||||
(mux->num_streams == 1)) {
|
(mux->num_streams == 1)) {
|
||||||
GstMatroskaIndex *idx;
|
GstMatroskaIndex *idx;
|
||||||
|
|
||||||
|
@ -1422,14 +1415,14 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux)
|
||||||
|
|
||||||
idx->pos = mux->cluster_pos;
|
idx->pos = mux->cluster_pos;
|
||||||
idx->time = GST_BUFFER_TIMESTAMP (buf);
|
idx->time = GST_BUFFER_TIMESTAMP (buf);
|
||||||
idx->track = best->track->num;
|
idx->track = collect_pad->track->num;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if the duration differs from the default duration. */
|
/* Check if the duration differs from the default duration. */
|
||||||
write_duration = FALSE;
|
write_duration = FALSE;
|
||||||
block_duration = GST_BUFFER_DURATION (buf);
|
block_duration = GST_BUFFER_DURATION (buf);
|
||||||
if (GST_BUFFER_DURATION_IS_VALID (buf)) {
|
if (GST_BUFFER_DURATION_IS_VALID (buf)) {
|
||||||
if (block_duration != best->track->default_duration) {
|
if (block_duration != collect_pad->track->default_duration) {
|
||||||
write_duration = TRUE;
|
write_duration = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1444,8 +1437,8 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux)
|
||||||
GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT) ? 0 : 0x80;
|
GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT) ? 0 : 0x80;
|
||||||
|
|
||||||
hdr =
|
hdr =
|
||||||
gst_matroska_mux_create_buffer_header (best->track, relative_timestamp,
|
gst_matroska_mux_create_buffer_header (collect_pad->track,
|
||||||
flags);
|
relative_timestamp, flags);
|
||||||
gst_ebml_write_buffer_header (ebml, GST_MATROSKA_ID_SIMPLEBLOCK,
|
gst_ebml_write_buffer_header (ebml, GST_MATROSKA_ID_SIMPLEBLOCK,
|
||||||
GST_BUFFER_SIZE (buf) + GST_BUFFER_SIZE (hdr));
|
GST_BUFFER_SIZE (buf) + GST_BUFFER_SIZE (hdr));
|
||||||
gst_ebml_write_buffer (ebml, hdr);
|
gst_ebml_write_buffer (ebml, hdr);
|
||||||
|
@ -1455,8 +1448,8 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux)
|
||||||
} else {
|
} else {
|
||||||
blockgroup = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_BLOCKGROUP);
|
blockgroup = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_BLOCKGROUP);
|
||||||
hdr =
|
hdr =
|
||||||
gst_matroska_mux_create_buffer_header (best->track, relative_timestamp,
|
gst_matroska_mux_create_buffer_header (collect_pad->track,
|
||||||
0);
|
relative_timestamp, 0);
|
||||||
gst_ebml_write_buffer_header (ebml, GST_MATROSKA_ID_BLOCK,
|
gst_ebml_write_buffer_header (ebml, GST_MATROSKA_ID_BLOCK,
|
||||||
GST_BUFFER_SIZE (buf) + GST_BUFFER_SIZE (hdr));
|
GST_BUFFER_SIZE (buf) + GST_BUFFER_SIZE (hdr));
|
||||||
gst_ebml_write_buffer (ebml, hdr);
|
gst_ebml_write_buffer (ebml, hdr);
|
||||||
|
@ -1484,6 +1477,9 @@ static GstFlowReturn
|
||||||
gst_matroska_mux_collected (GstCollectPads * pads, gpointer user_data)
|
gst_matroska_mux_collected (GstCollectPads * pads, gpointer user_data)
|
||||||
{
|
{
|
||||||
GstMatroskaMux *mux = GST_MATROSKA_MUX (user_data);
|
GstMatroskaMux *mux = GST_MATROSKA_MUX (user_data);
|
||||||
|
GstMatroskaPad *best;
|
||||||
|
gboolean popped;
|
||||||
|
GstFlowReturn ret;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (mux, "Collected pads");
|
GST_DEBUG_OBJECT (mux, "Collected pads");
|
||||||
|
|
||||||
|
@ -1499,8 +1495,25 @@ gst_matroska_mux_collected (GstCollectPads * pads, gpointer user_data)
|
||||||
mux->state = GST_MATROSKA_MUX_STATE_DATA;
|
mux->state = GST_MATROSKA_MUX_STATE_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* do one single buffer */
|
do {
|
||||||
return gst_matroska_mux_write_data (mux);
|
/* which stream to write from? */
|
||||||
|
best = gst_matroska_mux_best_pad (mux, &popped);
|
||||||
|
|
||||||
|
/* if there is no best pad, we have reached EOS */
|
||||||
|
if (best == NULL) {
|
||||||
|
GST_DEBUG_OBJECT (mux, "No best pad finishing...");
|
||||||
|
gst_matroska_mux_finish (mux);
|
||||||
|
gst_pad_push_event (mux->srcpad, gst_event_new_eos ());
|
||||||
|
ret = GST_FLOW_UNEXPECTED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
GST_DEBUG_OBJECT (best->collect.pad, "best pad");
|
||||||
|
|
||||||
|
/* write one buffer */
|
||||||
|
ret = gst_matroska_mux_write_data (mux, best);
|
||||||
|
} while (ret == GST_FLOW_OK && !popped);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue