summaryrefslogtreecommitdiff
path: root/gst/avi/gstavidemux.c
diff options
context:
space:
mode:
Diffstat (limited to 'gst/avi/gstavidemux.c')
-rwxr-xr-x[-rw-r--r--]gst/avi/gstavidemux.c162
1 files changed, 151 insertions, 11 deletions
diff --git a/gst/avi/gstavidemux.c b/gst/avi/gstavidemux.c
index 0b5a55e..e8bef94 100644..100755
--- a/gst/avi/gstavidemux.c
+++ b/gst/avi/gstavidemux.c
@@ -74,6 +74,13 @@
#define ENTRY_SET_KEYFRAME(e) ((e)->flags = GST_AVI_KEYFRAME)
#define ENTRY_UNSET_KEYFRAME(e) ((e)->flags = 0)
+#ifdef AVIDEMUX_MODIFICATION
+enum
+{
+ PROP_0,
+ PROP_PLAYBACK_PROTECTION,
+};
+#endif
GST_DEBUG_CATEGORY_STATIC (avidemux_debug);
#define GST_CAT_DEFAULT avidemux_debug
@@ -157,6 +164,8 @@ gst_avi_demux_find_frame_type (GstAviStream *stream, GstBuffer *buf, int *frame_
static void gst_avidemux_forward_trickplay (GstAviDemux * avi, GstAviStream * stream, guint64 *timestamp);
static void gst_avidemux_backward_trickplay (GstAviDemux * avi, GstAviStream * stream, guint64 *timestamp);
static GstFlowReturn gst_avidemux_seek_to_previous_keyframe (GstAviDemux *avi);
+static void gst_avidemux_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec);
+static void gst_avidemux_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec);
#endif
static GstElementClass *parent_class = NULL;
@@ -347,12 +356,25 @@ gst_avi_demux_class_init (GstAviDemuxClass * klass)
parent_class = g_type_class_peek_parent (klass);
gobject_class->finalize = gst_avi_demux_finalize;
+
+#ifdef AVIDEMUX_MODIFICATION
+ gobject_class->set_property = gst_avidemux_set_property;
+ gobject_class->get_property = gst_avidemux_get_property;
+#endif
+
gstelement_class->change_state =
GST_DEBUG_FUNCPTR (gst_avi_demux_change_state);
gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_avi_demux_set_index);
gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_avi_demux_get_index);
+#ifdef AVIDEMUX_MODIFICATION
+ g_object_class_install_property (gobject_class, PROP_PLAYBACK_PROTECTION,
+ g_param_spec_boolean ("playback-protection", "whether file is playback protected or not",
+ "TRUE->playback protected, FALSE->not playback protected", FALSE,
+ G_PARAM_READWRITE));
+#endif
+
#ifdef DIVX_DRM
gst_tag_register ("drm_divx", GST_TAG_FLAG_META,
G_TYPE_STRING,
@@ -362,6 +384,43 @@ gst_avi_demux_class_init (GstAviDemuxClass * klass)
#endif
}
+#ifdef AVIDEMUX_MODIFICATION
+static void
+gst_avidemux_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstAviDemux *avi = GST_AVI_DEMUX (object);
+ switch (prop_id) {
+ case PROP_PLAYBACK_PROTECTION:
+ {
+ avi->playback_protected = g_value_get_boolean(value);
+ break;
+ }
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_avidemux_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+ GstAviDemux *avi = GST_AVI_DEMUX (object);
+
+ switch (prop_id) {
+ case PROP_PLAYBACK_PROTECTION:
+ {
+ g_value_set_boolean(value, avi->playback_protected);
+ break;
+ }
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+#endif
+
static void
gst_avi_demux_init (GstAviDemux * avi)
{
@@ -379,7 +438,9 @@ gst_avi_demux_init (GstAviDemux * avi)
gst_element_add_pad (GST_ELEMENT_CAST (avi), avi->sinkpad);
avi->adapter = gst_adapter_new ();
-
+#ifdef AVIDEMUX_MODIFICATION
+ avi->playback_protected = FALSE;
+#endif
gst_avi_demux_reset (avi);
}
@@ -748,11 +809,7 @@ gst_avi_demux_handle_src_query (GstPad * pad, GstQuery * query)
GST_DEBUG_OBJECT (query, "total frames is %" G_GUINT32_FORMAT,
stream->idx_n);
- if (stream->idx_n >= 0)
- gst_query_set_duration (query, fmt, stream->idx_n);
- else if (gst_pad_query_convert (pad, GST_FORMAT_TIME,
- duration, &fmt, &dur))
- gst_query_set_duration (query, fmt, dur);
+ gst_query_set_duration (query, fmt, stream->idx_n);
break;
}
default:
@@ -1085,6 +1142,7 @@ gst_avi_demux_handle_sink_event (GstPad * pad, GstEvent * event)
for (i = 0; i < avi->num_streams; i++) {
avi->stream[i].last_flow = GST_FLOW_OK;
avi->stream[i].discont = TRUE;
+ avi->stream[i].sent_eos = FALSE;
}
/* fall through to default case so that the event gets passed downstream */
}
@@ -1483,8 +1541,7 @@ invalid_params:
{
GST_ERROR_OBJECT (avi, "invalid index parameters (num = %d, bpe = %d)",
num, bpe);
- if (buf)
- gst_buffer_unref (buf);
+ gst_buffer_unref (buf);
return FALSE;
}
}
@@ -2088,6 +2145,13 @@ gst_riff_parse_strd (GstAviDemux * avi,
GST_DEBUG_OBJECT (avi, " version %d", ((gst_riff_strd*)GST_BUFFER_DATA(buf))->version);
GST_DEBUG_OBJECT (avi, " drm_size %d", ((gst_riff_strd*)GST_BUFFER_DATA(buf))->drm_size);
+ if(avi->playback_protected) {
+ gst_buffer_unref (buf);
+ GST_ERROR_OBJECT (avi, "Trusted OPL violation error");
+ GST_ELEMENT_ERROR (avi, STREAM, DECRYPT_NOKEY, ("Trusted opl violation error"), (NULL));
+ return FALSE;
+ }
+
return gst_avi_demux_init_divx_drm (avi, GST_BUFFER_DATA(buf)+sizeof(gst_riff_strd));
/* ERRORS */
@@ -2257,6 +2321,14 @@ gst_avi_demux_parse_stream (GstAviDemux * avi, GstBuffer * buf)
stream->is_vbr = (stream->strh->samplesize == 0)
&& stream->strh->scale > 1
&& stream->strf.auds->blockalign != 1;
+#ifdef AVIDEMUX_MODIFICATION
+ /* This is processing for exception condition.
+ * samplesize is not 0, but is_vbr must become true. */
+ if(stream->strf.auds->format == GST_RIFF_WAVE_FORMAT_AAC) {
+ if (stream->strh->scale > 1 && stream->strf.auds->blockalign != 1)
+ stream->is_vbr = TRUE;
+ }
+#endif
GST_DEBUG_OBJECT (element, "marking audio as VBR:%d, res %d",
stream->is_vbr, res);
/* we need these or we have no way to come up with timestamps */
@@ -2434,6 +2506,9 @@ gst_avi_demux_parse_stream (GstAviDemux * avi, GstBuffer * buf)
g_free (vprp);
vprp = NULL;
}
+#ifdef AVIDEMUX_MODIFICATION
+ gst_caps_set_simple (caps, "ts-linear", G_TYPE_BOOLEAN, TRUE, NULL);
+#endif
tag_name = GST_TAG_VIDEO_CODEC;
avi->num_v_streams++;
break;
@@ -2531,6 +2606,7 @@ gst_avi_demux_parse_stream (GstAviDemux * avi, GstBuffer * buf)
stream->idx_n = 0;
stream->idx_max = 0;
+ stream->sent_eos = FALSE;
gst_pad_set_element_private (pad, stream);
avi->num_streams++;
@@ -2706,7 +2782,7 @@ gst_avi_demux_index_for_time (GstAviDemux * avi,
GstAviStream * stream, guint64 time)
{
guint index = -1;
- guint64 total;
+ guint64 total = 0;
GST_LOG_OBJECT (avi, "search time:%" GST_TIME_FORMAT, GST_TIME_ARGS (time));
@@ -2793,7 +2869,7 @@ gst_avi_demux_parse_index (GstAviDemux * avi, GstBuffer * buf)
gst_riff_index_entry *index;
GstClockTime stamp;
GstAviStream *stream;
- GstAviIndexEntry entry;
+ GstAviIndexEntry entry = {0};
guint32 id;
if (!buf)
@@ -2927,6 +3003,35 @@ gst_avi_demux_stream_index (GstAviDemux * avi)
tag = GST_READ_UINT32_LE (GST_BUFFER_DATA (buf));
size = GST_READ_UINT32_LE (GST_BUFFER_DATA (buf) + 4);
if (tag == GST_RIFF_TAG_LIST) {
+
+#ifdef AVIDEMUX_MODIFICATION
+ /* check for multiple list tag */
+ do {
+ GstBuffer *temp_buf;
+ guint32 temp_tag;
+ guint32 temp_size;
+ res = gst_pad_pull_range (avi->sinkpad, offset + 20, 8, &temp_buf);
+ if (res != GST_FLOW_OK)
+ goto pull_failed;
+ else if (GST_BUFFER_SIZE (buf) < 8)
+ goto too_small;
+ /* check tag first before blindy trying to read 'size' bytes */
+ temp_tag = GST_READ_UINT32_LE (GST_BUFFER_DATA (temp_buf));
+ temp_size = GST_READ_UINT32_LE (GST_BUFFER_DATA (temp_buf) + 4);
+ if (temp_tag == GST_RIFF_TAG_LIST) {
+ GST_WARNING_OBJECT (avi, "there are multiple list tags in the file, so skipping them");
+ gst_buffer_unref (buf);
+ buf = temp_buf;
+ tag = temp_tag;
+ size = temp_size;
+ offset += 20;
+ avi->offset += 20;
+ }
+ else
+ break;
+ } while (1);
+#endif
+
/* this is the movi tag */
GST_DEBUG_OBJECT (avi, "skip LIST chunk, size %" G_GUINT32_FORMAT,
(8 + GST_ROUND_UP_2 (size)));
@@ -3408,6 +3513,7 @@ gst_avi_demux_push_event (GstAviDemux * avi, GstEvent * event)
{
gboolean result = FALSE;
gint i;
+ GstEventType etype = GST_EVENT_TYPE (event);
GST_DEBUG_OBJECT (avi, "sending %s event to %d streams",
GST_EVENT_TYPE_NAME (event), avi->num_streams);
@@ -3416,6 +3522,15 @@ gst_avi_demux_push_event (GstAviDemux * avi, GstEvent * event)
GstAviStream *stream = &avi->stream[i];
if (stream->pad) {
+ if (etype == GST_EVENT_EOS) {
+ /* let's not send twice */
+ if (stream->sent_eos) {
+ result = TRUE;
+ continue;
+ }
+ GST_DEBUG_OBJECT(avi, "Sending EOS for stream %d", i);
+ stream->sent_eos = TRUE;
+ }
result = TRUE;
gst_pad_push_event (stream->pad, gst_event_ref (event));
}
@@ -4305,6 +4420,7 @@ gst_avi_demux_move_stream (GstAviDemux * avi, GstAviStream * stream,
stream->start_entry = index;
stream->step_entry = index;
stream->stop_entry = gst_avi_demux_index_last (avi, stream);
+ stream->sent_eos = FALSE;
}
if (stream->current_entry != index) {
GST_DEBUG_OBJECT (avi, "Move DISCONT from %u to %u",
@@ -4442,7 +4558,7 @@ gst_avi_demux_handle_seek (GstAviDemux * avi, GstPad * pad, GstEvent * event)
GstFormat format;
GstSeekFlags flags;
GstSeekType cur_type = GST_SEEK_TYPE_NONE, stop_type;
- gint64 cur, stop;
+ gint64 cur = 0, stop;
gboolean flush;
gboolean update;
GstSegment seeksegment = { 0, };
@@ -5093,6 +5209,25 @@ gst_avi_demux_loop_data (GstAviDemux * avi)
/* we have the stream now */
stream = &avi->stream[stream_num];
+ if ((stream->current_entry + 1) > stream->stop_entry) {
+ if (stream->sent_eos == FALSE) {
+ if(avi->segment.applied_rate > 0.0)
+ {
+ GstEvent *event = NULL;
+ event = gst_event_new_new_segment_full (FALSE,
+ avi->segment.rate, avi->segment.applied_rate, avi->segment.format,
+ stream->hdr_duration, stream->hdr_duration, avi->segment.time);
+ gst_pad_push_event (stream->pad, event);
+ }
+
+ GST_DEBUG_OBJECT(avi, "Sending EOS for stream %d", stream_num);
+ gst_pad_push_event(stream->pad, gst_event_new_eos ());
+ stream->sent_eos = TRUE;
+ stream->last_flow = GST_FLOW_UNEXPECTED;
+ continue;
+ }
+ }
+
/* skip streams without pads */
if (!stream->pad) {
GST_DEBUG_OBJECT (avi, "skipping entry from stream %d without pad",
@@ -5131,8 +5266,13 @@ gst_avi_demux_loop_data (GstAviDemux * avi)
if (avi->segment.rate > 0.0) {
/* only check this for fowards playback for now */
+#ifdef AVIDEMUX_MODIFICATION
+ if (GST_CLOCK_TIME_IS_VALID (avi->segment.stop)
+ && (timestamp > avi->segment.stop)) {
+#else
if (keyframe && GST_CLOCK_TIME_IS_VALID (avi->segment.stop)
&& (timestamp > avi->segment.stop)) {
+#endif
goto eos_stop;
}
}