*/
static GstStaticPadTemplate videosink_templ =
- GST_STATIC_PAD_TEMPLATE ("video_%d",
+ GST_STATIC_PAD_TEMPLATE ("video_%u",
GST_PAD_SINK,
GST_PAD_REQUEST,
GST_STATIC_CAPS ("video/mpeg, "
* * require codec data, etc as needed
*/
static GstStaticPadTemplate audiosink_templ =
- GST_STATIC_PAD_TEMPLATE ("audio_%d",
+ GST_STATIC_PAD_TEMPLATE ("audio_%u",
GST_PAD_SINK,
GST_PAD_REQUEST,
GST_STATIC_CAPS ("audio/mpeg, "
);
static GstStaticPadTemplate subtitlesink_templ =
-GST_STATIC_PAD_TEMPLATE ("subtitle_%d",
+GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
GST_PAD_SINK,
GST_PAD_REQUEST,
GST_STATIC_CAPS ("subtitle/x-kate"));
{
GstMatroskaMux *mux = GST_MATROSKA_MUX (object);
+ gst_event_replace (&mux->force_key_unit_event, NULL);
+
gst_object_unref (mux->collect);
gst_object_unref (mux->ebml_write);
if (mux->writing_app)
event = NULL;
break;
}
- case GST_EVENT_NEWSEGMENT:
- /* We don't support NEWSEGMENT events */
- ret = FALSE;
- gst_event_unref (event);
- event = NULL;
+ case GST_EVENT_NEWSEGMENT:{
+ GstFormat format;
+
+ gst_event_parse_new_segment (event, NULL, NULL, &format, NULL, NULL,
+ NULL);
+ if (format != GST_FORMAT_TIME) {
+ ret = FALSE;
+ gst_event_unref (event);
+ event = NULL;
+ }
break;
+ }
+ case GST_EVENT_CUSTOM_DOWNSTREAM:{
+ const GstStructure *structure;
+
+ structure = gst_event_get_structure (event);
+ if (gst_structure_has_name (structure, "GstForceKeyUnit")) {
+ gst_event_replace (&mux->force_key_unit_event, NULL);
+ mux->force_key_unit_event = event;
+ event = NULL;
+ }
+ break;
+ }
default:
break;
}
if (!strcmp (mimetype, "video/x-raw-yuv")) {
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_UNCOMPRESSED);
gst_structure_get_fourcc (structure, "format", &videocontext->fourcc);
- } else if (!strcmp (mimetype, "image/jpeg")) {
- context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_MJPEG);
} else if (!strcmp (mimetype, "video/x-xvid") /* MS/VfW compatibility cases */
||!strcmp (mimetype, "video/x-huffyuv")
|| !strcmp (mimetype, "video/x-divx")
|| !strcmp (mimetype, "video/x-dv")
|| !strcmp (mimetype, "video/x-h263")
|| !strcmp (mimetype, "video/x-msmpeg")
- || !strcmp (mimetype, "video/x-wmv")) {
+ || !strcmp (mimetype, "video/x-wmv")
+ || !strcmp (mimetype, "image/jpeg")) {
gst_riff_strf_vids *bih;
gint size = sizeof (gst_riff_strf_vids);
guint32 fourcc = 0;
fourcc = GST_MAKE_FOURCC ('W', 'M', 'V', '3');
}
}
+ } else if (!strcmp (mimetype, "image/jpeg")) {
+ fourcc = GST_MAKE_FOURCC ('M', 'J', 'P', 'G');
}
if (!fourcc)
GstMatroskaTrackContext *context = NULL;
gint pad_id;
- if (templ == gst_element_class_get_pad_template (klass, "audio_%d")) {
+ if (templ == gst_element_class_get_pad_template (klass, "audio_%u")) {
/* don't mix named and unnamed pads, if the pad already exists we fail when
* trying to add it */
- if (req_name != NULL && sscanf (req_name, "audio_%d", &pad_id) == 1) {
+ if (req_name != NULL && sscanf (req_name, "audio_%u", &pad_id) == 1) {
pad_name = req_name;
} else {
- name = g_strdup_printf ("audio_%d", mux->num_a_streams++);
+ name = g_strdup_printf ("audio_%u", mux->num_a_streams++);
pad_name = name;
}
setcapsfunc = GST_DEBUG_FUNCPTR (gst_matroska_mux_audio_pad_setcaps);
g_new0 (GstMatroskaTrackAudioContext, 1);
context->type = GST_MATROSKA_TRACK_TYPE_AUDIO;
context->name = g_strdup ("Audio");
- } else if (templ == gst_element_class_get_pad_template (klass, "video_%d")) {
+ } else if (templ == gst_element_class_get_pad_template (klass, "video_%u")) {
/* don't mix named and unnamed pads, if the pad already exists we fail when
* trying to add it */
- if (req_name != NULL && sscanf (req_name, "video_%d", &pad_id) == 1) {
+ if (req_name != NULL && sscanf (req_name, "video_%u", &pad_id) == 1) {
pad_name = req_name;
} else {
- name = g_strdup_printf ("video_%d", mux->num_v_streams++);
+ name = g_strdup_printf ("video_%u", mux->num_v_streams++);
pad_name = name;
}
setcapsfunc = GST_DEBUG_FUNCPTR (gst_matroska_mux_video_pad_setcaps);
g_new0 (GstMatroskaTrackVideoContext, 1);
context->type = GST_MATROSKA_TRACK_TYPE_VIDEO;
context->name = g_strdup ("Video");
- } else if (templ == gst_element_class_get_pad_template (klass, "subtitle_%d")) {
+ } else if (templ == gst_element_class_get_pad_template (klass, "subtitle_%u")) {
/* don't mix named and unnamed pads, if the pad already exists we fail when
* trying to add it */
- if (req_name != NULL && sscanf (req_name, "subtitle_%d", &pad_id) == 1) {
+ if (req_name != NULL && sscanf (req_name, "subtitle_%u", &pad_id) == 1) {
pad_name = req_name;
} else {
- name = g_strdup_printf ("subtitle_%d", mux->num_t_streams++);
+ name = g_strdup_printf ("subtitle_%u", mux->num_t_streams++);
pad_name = name;
}
setcapsfunc = GST_DEBUG_FUNCPTR (gst_matroska_mux_subtitle_pad_setcaps);
child = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TRACKENTRY);
gst_matroska_mux_track_header (mux, collect_pad->track);
gst_ebml_write_master_finish (ebml, child);
+ /* some remaing pad/track setup */
+ collect_pad->default_duration_scaled =
+ gst_util_uint64_scale (collect_pad->track->default_duration,
+ 1, mux->time_scale);
}
}
gst_ebml_write_master_finish (ebml, master);
collect_pad->buffer = NULL;
return NULL;
} else {
+ GST_LOG_OBJECT (mux, "buffer ts %" GST_TIME_FORMAT " -> %"
+ GST_TIME_FORMAT " running time",
+ GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (collect_pad->buffer)),
+ GST_TIME_ARGS (time));
collect_pad->buffer =
gst_buffer_make_metadata_writable (collect_pad->buffer);
GST_BUFFER_TIMESTAMP (collect_pad->buffer) = time;
next_parse_offset = GST_READ_UINT32_BE (data + 5);
- if (G_UNLIKELY (next_parse_offset == 0))
+ if (G_UNLIKELY (next_parse_offset == 0 || next_parse_offset > size))
break;
data += next_parse_offset;
}
if (mux->cluster) {
- /* start a new cluster at every keyframe or when we may be reaching the
- * limit of the relative timestamp */
+ /* start a new cluster at every keyframe, at every GstForceKeyUnit event,
+ * or when we may be reaching the limit of the relative timestamp */
if (mux->cluster_time +
mux->max_cluster_duration < GST_BUFFER_TIMESTAMP (buf)
- || is_video_keyframe) {
+ || is_video_keyframe || mux->force_key_unit_event) {
if (!mux->streamable)
gst_ebml_write_master_finish (ebml, mux->cluster);
+
+ /* Forward the GstForceKeyUnit event after finishing the cluster */
+ if (mux->force_key_unit_event) {
+ gst_pad_push_event (mux->srcpad, mux->force_key_unit_event);
+ mux->force_key_unit_event = NULL;
+ }
+
mux->prev_cluster_size = ebml->pos - mux->cluster_pos;
mux->cluster_pos = ebml->pos;
gst_ebml_write_set_cache (ebml, 0x20);
/* Check if the duration differs from the default duration. */
write_duration = FALSE;
- block_duration = GST_BUFFER_DURATION (buf);
+ block_duration = 0;
if (GST_BUFFER_DURATION_IS_VALID (buf)) {
- if (block_duration != collect_pad->track->default_duration) {
+ block_duration = gst_util_uint64_scale (GST_BUFFER_DURATION (buf),
+ 1, mux->time_scale);
+
+ /* small difference should be ok. */
+ if (block_duration > collect_pad->default_duration_scaled + 1 ||
+ block_duration < collect_pad->default_duration_scaled - 1) {
write_duration = TRUE;
}
}
hdr =
gst_matroska_mux_create_buffer_header (collect_pad->track,
relative_timestamp, 0);
- if (write_duration) {
- gst_ebml_write_uint (ebml, GST_MATROSKA_ID_BLOCKDURATION,
- gst_util_uint64_scale (block_duration, 1, mux->time_scale));
- }
+ if (write_duration)
+ gst_ebml_write_uint (ebml, GST_MATROSKA_ID_BLOCKDURATION, block_duration);
gst_ebml_write_buffer_header (ebml, GST_MATROSKA_ID_BLOCK,
GST_BUFFER_SIZE (buf) + GST_BUFFER_SIZE (hdr));
gst_ebml_write_buffer (ebml, hdr);