/* buffer needs some custom processing, e.g. subtitles */
gboolean need_process;
+ /* buffer needs potentially be split, e.g. CEA608 subtitles */
+ gboolean need_split;
/* current position */
guint32 segment_index;
gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
g_queue_init (&stream->protection_scheme_event_queue);
stream->ref_count = 1;
+ /* consistent default for push based mode */
+ gst_segment_init (&stream->segment, GST_FORMAT_TIME);
return stream;
}
if (hard) {
qtdemux->segment_seqnum = GST_SEQNUM_INVALID;
- g_ptr_array_remove_range (qtdemux->active_streams,
- 0, qtdemux->active_streams->len);
- g_ptr_array_remove_range (qtdemux->old_streams,
- 0, qtdemux->old_streams->len);
+ g_ptr_array_set_size (qtdemux->active_streams, 0);
+ g_ptr_array_set_size (qtdemux->old_streams, 0);
qtdemux->n_video_streams = 0;
qtdemux->n_audio_streams = 0;
qtdemux->n_sub_streams = 0;
g_ptr_array_add (dest, gst_qtdemux_stream_ref (stream));
}
- g_ptr_array_remove_range (src, 0, len);
+ g_ptr_array_set_size (src, 0);
}
static gboolean
seg_media_start_mov = seg->trak_media_start;
GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
- " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
+ " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT,
k_index, target_ts, seg_media_start_mov,
GST_TIME_ARGS (seg->media_start));
}
static guint8 *
-convert_to_ccdata (const guint8 * ccpair, guint8 ccpair_size, guint field,
+convert_to_s334_1a (const guint8 * ccpair, guint8 ccpair_size, guint field,
gsize * res)
{
guint8 *storage;
*res = ccpair_size / 2 * 3;
storage = g_malloc (*res);
for (i = 0; i * 2 < ccpair_size; i += 1) {
+ /* FIXME: Use line offset 0 as we simply can't know here */
if (field == 1)
- storage[i * 3] = 0xfc;
+ storage[i * 3] = 0x80 | 0x00;
else
- storage[i * 3] = 0xfd;
+ storage[i * 3] = 0x00 | 0x00;
storage[i * 3 + 1] = ccpair[i * 2];
storage[i * 3 + 2] = ccpair[i * 2 + 1];
}
goto invalid_cdat;
}
- /* Convert to cc_data triplet */
+ /* Convert to S334-1 Annex A byte triplet */
if (fourcc == FOURCC_cdat)
- cdat = convert_to_ccdata (data + 8, atom_length - 8, 1, &cdat_size);
+ cdat = convert_to_s334_1a (data + 8, atom_length - 8, 1, &cdat_size);
else
- cdt2 = convert_to_ccdata (data + 8, atom_length - 8, 2, &cdt2_size);
+ cdt2 = convert_to_s334_1a (data + 8, atom_length - 8, 2, &cdt2_size);
GST_DEBUG_OBJECT (stream->pad, "size:%" G_GSIZE_FORMAT " atom_length:%u",
size, atom_length);
if (fourcc == FOURCC_cdat) {
if (cdat == NULL)
cdat =
- convert_to_ccdata (data + atom_length + 8,
+ convert_to_s334_1a (data + atom_length + 8,
new_atom_length - 8, 1, &cdat_size);
else
GST_WARNING_OBJECT (stream->pad,
} else {
if (cdt2 == NULL)
cdt2 =
- convert_to_ccdata (data + atom_length + 8,
+ convert_to_s334_1a (data + atom_length + 8,
new_atom_length - 8, 2, &cdt2_size);
else
GST_WARNING_OBJECT (stream->pad,
return buf;
}
+static GstFlowReturn
+gst_qtdemux_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
+ GstBuffer * buf)
+{
+ GstFlowReturn ret = GST_FLOW_OK;
+ GstClockTime pts, duration;
+
+ if (stream->need_clip)
+ buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
+
+ if (G_UNLIKELY (buf == NULL))
+ goto exit;
+
+ if (G_UNLIKELY (stream->discont)) {
+ GST_LOG_OBJECT (qtdemux, "marking discont buffer");
+ GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
+ stream->discont = FALSE;
+ } else {
+ GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
+ }
+
+ GST_LOG_OBJECT (qtdemux,
+ "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
+ ", duration %" GST_TIME_FORMAT " on pad %s",
+ GST_TIME_ARGS (GST_BUFFER_DTS (buf)),
+ GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
+ GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_PAD_NAME (stream->pad));
+
+ if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
+ GstStructure *crypto_info;
+ QtDemuxCencSampleSetInfo *info =
+ (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
+ gint index;
+ GstEvent *event;
+
+ while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
+ GST_TRACE_OBJECT (stream->pad, "pushing protection event: %"
+ GST_PTR_FORMAT, event);
+ gst_pad_push_event (stream->pad, event);
+ }
+
+ if (info->crypto_info == NULL) {
+ GST_DEBUG_OBJECT (qtdemux,
+ "cenc metadata hasn't been parsed yet, pushing buffer as if it wasn't encrypted");
+ } else {
+ /* The end of the crypto_info array matches our n_samples position,
+ * so count backward from there */
+ index = stream->sample_index - stream->n_samples + info->crypto_info->len;
+ if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
+ /* steal structure from array */
+ crypto_info = g_ptr_array_index (info->crypto_info, index);
+ g_ptr_array_index (info->crypto_info, index) = NULL;
+ GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
+ info->crypto_info->len);
+ if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
+ GST_ERROR_OBJECT (qtdemux,
+ "failed to attach cenc metadata to buffer");
+ } else {
+ GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
+ index, stream->sample_index);
+ }
+ }
+ }
+
+ if (stream->alignment > 1)
+ buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
+
+ pts = GST_BUFFER_PTS (buf);
+ duration = GST_BUFFER_DURATION (buf);
+
+ ret = gst_pad_push (stream->pad, buf);
+
+ if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
+ /* mark position in stream, we'll need this to know when to send GAP event */
+ stream->segment.position = pts + duration;
+ }
+
+exit:
+
+ return ret;
+}
+
+static GstFlowReturn
+gst_qtdemux_split_and_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
+ GstBuffer * buf)
+{
+ GstFlowReturn ret = GST_FLOW_OK;
+
+ if (stream->subtype == FOURCC_clcp
+ && CUR_STREAM (stream)->fourcc == FOURCC_c608 && stream->need_split) {
+ GstMapInfo map;
+ guint n_output_buffers, n_field1 = 0, n_field2 = 0;
+ guint n_triplets, i;
+ guint field1_off = 0, field2_off = 0;
+
+ /* We have to split CEA608 buffers so that each outgoing buffer contains
+ * one byte pair per field according to the framerate of the video track.
+ *
+ * If there is only a single byte pair per field we don't have to do
+ * anything
+ */
+
+ gst_buffer_map (buf, &map, GST_MAP_READ);
+
+ n_triplets = map.size / 3;
+ for (i = 0; i < n_triplets; i++) {
+ if (map.data[3 * i] & 0x80)
+ n_field1++;
+ else
+ n_field2++;
+ }
+
+ g_assert (n_field1 || n_field2);
+
+ /* If there's more than 1 frame we have to split, otherwise we can just
+ * pass through */
+ if (n_field1 > 1 || n_field2 > 1) {
+ n_output_buffers =
+ gst_util_uint64_scale (GST_BUFFER_DURATION (buf),
+ CUR_STREAM (stream)->fps_n, GST_SECOND * CUR_STREAM (stream)->fps_d);
+
+ for (i = 0; i < n_output_buffers; i++) {
+ GstBuffer *outbuf =
+ gst_buffer_new_and_alloc ((n_field1 ? 3 : 0) + (n_field2 ? 3 : 0));
+ GstMapInfo outmap;
+ guint8 *outptr;
+
+ gst_buffer_map (outbuf, &outmap, GST_MAP_WRITE);
+ outptr = outmap.data;
+
+ if (n_field1) {
+ gboolean found = FALSE;
+
+ while (map.data + field1_off < map.data + map.size) {
+ if (map.data[field1_off] & 0x80) {
+ memcpy (outptr, &map.data[field1_off], 3);
+ field1_off += 3;
+ found = TRUE;
+ break;
+ }
+ field1_off += 3;
+ }
+
+ if (!found) {
+ const guint8 empty[] = { 0x80, 0x80, 0x80 };
+
+ memcpy (outptr, empty, 3);
+ }
+
+ outptr += 3;
+ }
+
+ if (n_field2) {
+ gboolean found = FALSE;
+
+ while (map.data + field2_off < map.data + map.size) {
+ if ((map.data[field2_off] & 0x80) == 0) {
+ memcpy (outptr, &map.data[field2_off], 3);
+ field2_off += 3;
+ found = TRUE;
+ break;
+ }
+ field2_off += 3;
+ }
+
+ if (!found) {
+ const guint8 empty[] = { 0x00, 0x80, 0x80 };
+
+ memcpy (outptr, empty, 3);
+ }
+
+ outptr += 3;
+ }
+
+ gst_buffer_unmap (outbuf, &outmap);
+
+ GST_BUFFER_PTS (outbuf) =
+ GST_BUFFER_PTS (buf) + gst_util_uint64_scale (i,
+ GST_SECOND * CUR_STREAM (stream)->fps_d,
+ CUR_STREAM (stream)->fps_n);
+ GST_BUFFER_DURATION (outbuf) =
+ gst_util_uint64_scale (GST_SECOND, CUR_STREAM (stream)->fps_d,
+ CUR_STREAM (stream)->fps_n);
+ GST_BUFFER_OFFSET (outbuf) = -1;
+ GST_BUFFER_OFFSET_END (outbuf) = -1;
+
+ ret = gst_qtdemux_push_buffer (qtdemux, stream, outbuf);
+
+ if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
+ break;
+ }
+ gst_buffer_unmap (buf, &map);
+ gst_buffer_unref (buf);
+ } else {
+ gst_buffer_unmap (buf, &map);
+ ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
+ }
+ } else {
+ ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
+ }
+
+ return ret;
+}
+
/* Sets a buffer's attributes properly and pushes it downstream.
* Also checks for additional actions and custom processing that may
* need to be done first.
GST_BUFFER_OFFSET (buf) = -1;
GST_BUFFER_OFFSET_END (buf) = -1;
+ if (!keyframe) {
+ GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
+ stream->on_keyframe = FALSE;
+ } else {
+ stream->on_keyframe = TRUE;
+ }
+
if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
gst_buffer_append_memory (buf,
gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
}
#endif
- if (stream->need_clip)
- buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
-
- if (G_UNLIKELY (buf == NULL))
- goto exit;
-
- if (G_UNLIKELY (stream->discont)) {
- GST_LOG_OBJECT (qtdemux, "marking discont buffer");
- GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
- stream->discont = FALSE;
- } else {
- GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
- }
-
- if (!keyframe) {
- GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
- stream->on_keyframe = FALSE;
- } else {
- stream->on_keyframe = TRUE;
- }
-
-
- GST_LOG_OBJECT (qtdemux,
- "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
- ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
- GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
- GST_PAD_NAME (stream->pad));
-
- if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
- GstStructure *crypto_info;
- QtDemuxCencSampleSetInfo *info =
- (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
- gint index;
- GstEvent *event;
-
- while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
- GST_TRACE_OBJECT (stream->pad, "pushing protection event: %"
- GST_PTR_FORMAT, event);
- gst_pad_push_event (stream->pad, event);
- }
-
- if (info->crypto_info == NULL) {
- GST_DEBUG_OBJECT (qtdemux,
- "cenc metadata hasn't been parsed yet, pushing buffer as if it wasn't encrypted");
- } else {
- /* The end of the crypto_info array matches our n_samples position,
- * so count backward from there */
- index = stream->sample_index - stream->n_samples + info->crypto_info->len;
- if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
- /* steal structure from array */
- crypto_info = g_ptr_array_index (info->crypto_info, index);
- g_ptr_array_index (info->crypto_info, index) = NULL;
- GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
- info->crypto_info->len);
- if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
- GST_ERROR_OBJECT (qtdemux,
- "failed to attach cenc metadata to buffer");
- } else {
- GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
- index, stream->sample_index);
- }
- }
- }
-
- if (stream->alignment > 1)
- buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
-
- ret = gst_pad_push (stream->pad, buf);
-
- if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
- /* mark position in stream, we'll need this to know when to send GAP event */
- stream->segment.position = pts + duration;
- }
+ ret = gst_qtdemux_split_and_push_buffer (qtdemux, stream, buf);
exit:
return ret;
}
static gboolean
-gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
+gst_qtdemux_guess_framerate (GstQTDemux * qtdemux, QtDemuxStream * stream)
{
- if (stream->subtype == FOURCC_vide) {
- /* fps is calculated base on the duration of the average framerate since
- * qt does not have a fixed framerate. */
- gboolean fps_available = TRUE;
- guint32 first_duration = 0;
-
- if (stream->n_samples > 0)
- first_duration = stream->samples[0].duration;
-
- if ((stream->n_samples == 1 && first_duration == 0)
- || (qtdemux->fragmented && stream->n_samples_moof == 1)) {
- /* still frame */
- CUR_STREAM (stream)->fps_n = 0;
+ /* fps is calculated base on the duration of the average framerate since
+ * qt does not have a fixed framerate. */
+ gboolean fps_available = TRUE;
+ guint32 first_duration = 0;
+
+ if (stream->n_samples > 0)
+ first_duration = stream->samples[0].duration;
+
+ if ((stream->n_samples == 1 && first_duration == 0)
+ || (qtdemux->fragmented && stream->n_samples_moof == 1)) {
+ /* still frame */
+ CUR_STREAM (stream)->fps_n = 0;
+ CUR_STREAM (stream)->fps_d = 1;
+ } else {
+ if (stream->duration == 0 || stream->n_samples < 2) {
+ CUR_STREAM (stream)->fps_n = stream->timescale;
CUR_STREAM (stream)->fps_d = 1;
+ fps_available = FALSE;
} else {
- if (stream->duration == 0 || stream->n_samples < 2) {
- CUR_STREAM (stream)->fps_n = stream->timescale;
- CUR_STREAM (stream)->fps_d = 1;
- fps_available = FALSE;
+ GstClockTime avg_duration;
+ guint64 duration;
+ guint32 n_samples;
+
+ /* duration and n_samples can be updated for fragmented format
+ * so, framerate of fragmented format is calculated using data in a moof */
+ if (qtdemux->fragmented && stream->n_samples_moof > 0
+ && stream->duration_moof > 0) {
+ n_samples = stream->n_samples_moof;
+ duration = stream->duration_moof;
} else {
- GstClockTime avg_duration;
- guint64 duration;
- guint32 n_samples;
-
- /* duration and n_samples can be updated for fragmented format
- * so, framerate of fragmented format is calculated using data in a moof */
- if (qtdemux->fragmented && stream->n_samples_moof > 0
- && stream->duration_moof > 0) {
- n_samples = stream->n_samples_moof;
- duration = stream->duration_moof;
- } else {
- n_samples = stream->n_samples;
- duration = stream->duration;
- }
+ n_samples = stream->n_samples;
+ duration = stream->duration;
+ }
- /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
- /* stream->duration is guint64, timescale, n_samples are guint32 */
- avg_duration =
- gst_util_uint64_scale_round (duration -
- first_duration, GST_SECOND,
- (guint64) (stream->timescale) * (n_samples - 1));
+ /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
+ /* stream->duration is guint64, timescale, n_samples are guint32 */
+ avg_duration =
+ gst_util_uint64_scale_round (duration -
+ first_duration, GST_SECOND,
+ (guint64) (stream->timescale) * (n_samples - 1));
- GST_LOG_OBJECT (qtdemux,
- "Calculating avg sample duration based on stream (or moof) duration %"
- G_GUINT64_FORMAT
- " minus first sample %u, leaving %d samples gives %"
- GST_TIME_FORMAT, duration, first_duration,
- n_samples - 1, GST_TIME_ARGS (avg_duration));
+ GST_LOG_OBJECT (qtdemux,
+ "Calculating avg sample duration based on stream (or moof) duration %"
+ G_GUINT64_FORMAT
+ " minus first sample %u, leaving %d samples gives %"
+ GST_TIME_FORMAT, duration, first_duration,
+ n_samples - 1, GST_TIME_ARGS (avg_duration));
- gst_video_guess_framerate (avg_duration, &CUR_STREAM (stream)->fps_n,
- &CUR_STREAM (stream)->fps_d);
+ fps_available =
+ gst_video_guess_framerate (avg_duration,
+ &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
- GST_DEBUG_OBJECT (qtdemux,
- "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
- stream->timescale, CUR_STREAM (stream)->fps_n,
- CUR_STREAM (stream)->fps_d);
- }
+ GST_DEBUG_OBJECT (qtdemux,
+ "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
+ stream->timescale, CUR_STREAM (stream)->fps_n,
+ CUR_STREAM (stream)->fps_d);
}
+ }
+
+ return fps_available;
+}
+
+static gboolean
+gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
+{
+ if (stream->subtype == FOURCC_vide) {
+ gboolean fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
if (CUR_STREAM (stream)->caps) {
CUR_STREAM (stream)->caps =
}
}
+ else if (stream->subtype == FOURCC_clcp && CUR_STREAM (stream)->caps) {
+ const GstStructure *s;
+ QtDemuxStream *fps_stream = NULL;
+ gboolean fps_available = FALSE;
+
+ /* CEA608 closed caption tracks are a bit special in that each sample
+ * can contain CCs for multiple frames, and CCs can be omitted and have to
+ * be inferred from the duration of the sample then.
+ *
+ * As such we take the framerate from the (first) video track here for
+ * CEA608 as there must be one CC byte pair for every video frame
+ * according to the spec.
+ *
+ * For CEA708 all is fine and there is one sample per frame.
+ */
+
+ s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
+ if (gst_structure_has_name (s, "closedcaption/x-cea-608")) {
+ gint i;
+
+ for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
+ QtDemuxStream *tmp = QTDEMUX_NTH_STREAM (qtdemux, i);
+
+ if (tmp->subtype == FOURCC_vide) {
+ fps_stream = tmp;
+ break;
+ }
+ }
+
+ if (fps_stream) {
+ fps_available = gst_qtdemux_guess_framerate (qtdemux, fps_stream);
+ CUR_STREAM (stream)->fps_n = CUR_STREAM (fps_stream)->fps_n;
+ CUR_STREAM (stream)->fps_d = CUR_STREAM (fps_stream)->fps_d;
+ }
+ } else {
+ fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
+ fps_stream = stream;
+ }
+
+ CUR_STREAM (stream)->caps =
+ gst_caps_make_writable (CUR_STREAM (stream)->caps);
+
+ /* set framerate if calculated framerate is reliable */
+ if (fps_available) {
+ gst_caps_set_simple (CUR_STREAM (stream)->caps,
+ "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
+ CUR_STREAM (stream)->fps_d, NULL);
+ }
+ }
+
if (stream->pad) {
GstCaps *prev_caps = NULL;
QtDemuxStream * stream, GstTagList * list)
{
gboolean ret = TRUE;
- /* consistent default for push based mode */
- gst_segment_init (&stream->segment, GST_FORMAT_TIME);
if (stream->subtype == FOURCC_vide) {
gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
version = QT_UINT32 ((guint8 *) mdhd->data + 8);
GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
if (version == 0x01000000) {
- if (len < 38)
+ if (len < 42)
goto corrupt_file;
stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
- lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
+ lang_code = QT_UINT16 ((guint8 *) mdhd->data + 40);
} else {
if (len < 30)
goto corrupt_file;
fiel = NULL;
/* pick 'the' stsd child */
mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
- if (!stream->protected) {
- if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
+ // We should skip parsing the stsd for non-protected streams if
+ // the entry doesn't match the fourcc, since they don't change
+ // format. However, for protected streams we can have partial
+ // encryption, where parts of the stream are encrypted and parts
+ // not. For both parts of such streams, we should ensure the
+ // esds overrides are parsed for both from the stsd.
+ if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
+ if (stream->protected && QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv)
mp4v = NULL;
- }
- } else {
- if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
+ else if (!stream->protected)
mp4v = NULL;
- }
}
if (mp4v) {
}
mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
- if (!stream->protected) {
- } else {
- if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
- mp4v = NULL;
- }
- }
- if (stream->protected && fourcc == FOURCC_mp4a) {
- if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
+ if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != fourcc) {
+ if (stream->protected && QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca)
mp4a = NULL;
- }
- } else {
- if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_mp4a) {
+ else if (!stream->protected)
mp4a = NULL;
- }
}
wave = NULL;
return GST_FLOW_ERROR;
}
- g_ptr_array_remove_range (qtdemux->old_streams,
- 0, qtdemux->old_streams->len);
+ g_ptr_array_set_size (qtdemux->old_streams, 0);
+ qtdemux->need_segment = TRUE;
return GST_FLOW_OK;
}
}
}
- g_ptr_array_remove_range (qtdemux->old_streams, 0, qtdemux->old_streams->len);
+ g_ptr_array_set_size (qtdemux->old_streams, 0);
/* check if we should post a redirect in case there is a single trak
* and it is a redirecting trak */
_codec ("CEA 608 Closed Caption");
caps =
gst_caps_new_simple ("closedcaption/x-cea-608", "format",
- G_TYPE_STRING, "cc_data", NULL);
+ G_TYPE_STRING, "s334-1a", NULL);
stream->need_process = TRUE;
+ stream->need_split = TRUE;
break;
case FOURCC_c708:
_codec ("CEA 708 Closed Caption");