1.1 --- a/gst-plugins-nuvdemux/src/gstnuvdemux.c Thu Nov 09 19:12:55 2006 +0000
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,1137 +0,0 @@
1.4 -/* GStreamer
1.5 - * Copyright (C) <2006> Renato Araujo Oliveira Filho <renato.filho@indt.org.br>
1.6 - * Rosfran Borges <rosfran.borges@indt.org.br>
1.7 - *
1.8 - * This library is free software; you can redistribute it and/or
1.9 - * modify it under the terms of the GNU Library General Public
1.10 - * License as published by the Free Software Foundation; either
1.11 - * version 2 of the License, or (at your option) any later version.
1.12 - *
1.13 - * This library is distributed in the hope that it will be useful,
1.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1.16 - * Library General Public License for more details.
1.17 - *
1.18 - * You should have received a copy of the GNU Library General Public
1.19 - * License along with this library; if not, write to the
1.20 - * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
1.21 - * Boston, MA 02111-1307, USA.
1.22 - */
1.23 -/* Element-Checklist-Version: 5 */
1.24 -
1.25 -/**
1.26 - * SECTION:element-nuvdemux
1.27 - *
1.28 - * <refsect2>
1.29 - * <para>
1.30 - * Demuxes an .nuv file into raw or compressed audio and/or video streams.
1.31 - * </para>
1.32 - * <para>
1.33 - * This element currently only supports pull-based scheduling.
1.34 - * </para>
1.35 - * <title>Example launch line</title>
1.36 - * <para>
1.37 - * <programlisting>
1.38 - * gst-launch filesrc test.nuv ! nuvdemux name=demux demux.audio_00 ! decodebin ! audioconvert ! audioresample ! autoaudiosink demux.video_00 ! queue ! decodebin ! ffmpegcolorspace ! videoscale ! autovideosink
1.39 - * </programlisting>
1.40 - * Play (parse and decode) an .nuv file and try to output it to
1.41 - * an automatically detected soundcard and videosink. If the NUV file contains
1.42 - * compressed audio or video data, this will only work if you have the
1.43 - * right decoder elements/plugins installed.
1.44 - * </para>
1.45 - * </refsect2>
1.46 - *
1.47 - */
1.48 -
1.49 -#ifdef HAVE_CONFIG_H
1.50 -#include "config.h"
1.51 -#endif
1.52 -
1.53 -#include <gst/gst.h>
1.54 -#include <gst/gsterror.h>
1.55 -#include <gst/gstplugin.h>
1.56 -#include <string.h>
1.57 -
1.58 -#include "glib/gi18n.h"
1.59 -#include "gstnuvdemux.h"
1.60 -
1.61 -GST_DEBUG_CATEGORY_STATIC (nuvdemux_debug);
1.62 -#define GST_CAT_DEFAULT nuvdemux_debug
1.63 -
1.64 -
1.65 -#define GST_FLOW_ERROR_NO_DATA -101
1.66 -
1.67 -GST_DEBUG_CATEGORY_EXTERN (GST_CAT_EVENT);
1.68 -
1.69 -static const GstElementDetails gst_nuv_demux_details =
1.70 -GST_ELEMENT_DETAILS ("Nuv demuxer",
1.71 - "Codec/Demuxer",
1.72 - "Demultiplex a .nuv file into audio and video",
1.73 - "Renato Araujo Oliveira Filho <renato.filho@indt.org.br>,"
1.74 - "Rosfran Borges <rosfran.borges@indt.org.br>");
1.75 -
1.76 -static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
1.77 - GST_PAD_SINK,
1.78 - GST_PAD_ALWAYS,
1.79 - GST_STATIC_CAPS ("video/x-nuv"));
1.80 -
1.81 -static GstStaticPadTemplate audio_src_template =
1.82 -GST_STATIC_PAD_TEMPLATE ("audio_src",
1.83 - GST_PAD_SRC,
1.84 - GST_PAD_SOMETIMES,
1.85 - GST_STATIC_CAPS_ANY);
1.86 -
1.87 -static GstStaticPadTemplate video_src_template =
1.88 -GST_STATIC_PAD_TEMPLATE ("video_src",
1.89 - GST_PAD_SRC,
1.90 - GST_PAD_SOMETIMES,
1.91 - GST_STATIC_CAPS_ANY);
1.92 -
1.93 -/* NUV Demux indexes init/dispose callers */
1.94 -static void gst_nuv_demux_index_init( nuv_demux_index **p_idx );
1.95 -static void gst_nuv_demux_index_clean( nuv_demux_index **p_idx );
1.96 -
1.97 -/* NUV Demux indexes manipulation functions */
1.98 -//static gint64 gst_nuv_demux_index_find_offset( GstNuvDemux *nuv, gint64 i_offset );
1.99 -static void gst_nuv_demux_index_append( GstNuvDemux *nuv, gint64 i_time, gint64 i_offset );
1.100 -static gint64 gst_nuv_demux_index_convert_time( GstNuvDemux *nuv, gint64 i_time );
1.101 -
1.102 -/* NUV Demux plug-in time-line functions */
1.103 -static void gst_nuv_demux_finalize (GObject * object);
1.104 -static GstStateChangeReturn gst_nuv_demux_change_state (GstElement * element,
1.105 - GstStateChange transition);
1.106 -static void gst_nuv_demux_loop (GstPad * pad);
1.107 -static GstFlowReturn gst_nuv_demux_chain (GstPad * pad, GstBuffer * buf);
1.108 -static GstFlowReturn gst_nuv_demux_play (GstPad * pad);
1.109 -static gboolean gst_nuv_demux_sink_activate_pull (GstPad * sinkpad,
1.110 - gboolean active);
1.111 -static gboolean gst_nuv_demux_sink_activate (GstPad * sinkpad);
1.112 -static GstFlowReturn gst_nuv_demux_read_bytes (GstNuvDemux * nuv, guint64 size,
1.113 - gboolean move, GstBuffer ** buffer);
1.114 -static void gst_nuv_demux_reset (GstNuvDemux * nuv);
1.115 -static gboolean gst_nuv_demux_handle_sink_event (GstPad * sinkpad,
1.116 - GstEvent * event);
1.117 -static gboolean gst_nuv_demux_handle_audio_src_event (GstPad * sinkpad,
1.118 - GstEvent * event);
1.119 -static gboolean gst_nuv_demux_handle_video_src_event (GstPad * sinkpad,
1.120 - GstEvent * event);
1.121 -static void gst_nuv_demux_destoy_src_pad (GstNuvDemux * nuv);
1.122 -static void gst_nuv_demux_send_eos (GstNuvDemux * nuv);
1.123 -
1.124 -/* GObject methods */
1.125 -GST_BOILERPLATE (GstNuvDemux, gst_nuv_demux, GstElement, GST_TYPE_ELEMENT);
1.126 -
1.127 -#if G_BYTE_ORDER == G_BIG_ENDIAN
1.128 -static inline gdouble
1.129 -_gdouble_swap_le_be (gdouble * d)
1.130 -{
1.131 - union
1.132 - {
1.133 - guint64 i;
1.134 - gdouble d;
1.135 - } u;
1.136 -
1.137 - u.d = *d;
1.138 - u.i = GUINT64_SWAP_LE_BE (u.i);
1.139 - return u.d;
1.140 -}
1.141 -
1.142 -#define READ_DOUBLE_FROM_LE(d) (_gdouble_swap_le_be((gdouble* ) d))
1.143 -#else /* G_BYTE_ORDER != G_BIG_ENDIAN */
1.144 -#define READ_DOUBLE_FROM_LE(d) *((gdouble* ) (d))
1.145 -#endif /* G_BYTE_ORDER != G_BIG_ENDIAN */
1.146 -
1.147 -static void
1.148 -gst_nuv_demux_base_init (gpointer klass)
1.149 -{
1.150 - GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
1.151 -
1.152 - gst_element_class_add_pad_template (element_class,
1.153 - gst_static_pad_template_get (&audio_src_template));
1.154 -
1.155 - gst_element_class_add_pad_template (element_class,
1.156 - gst_static_pad_template_get (&video_src_template));
1.157 -
1.158 - gst_element_class_add_pad_template (element_class,
1.159 - gst_static_pad_template_get (&sink_template));
1.160 - gst_element_class_set_details (element_class, &gst_nuv_demux_details);
1.161 -}
1.162 -
1.163 -static void
1.164 -gst_nuv_demux_class_init (GstNuvDemuxClass * klass)
1.165 -{
1.166 - GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
1.167 - GObjectClass *gobject_class = (GObjectClass *) klass;
1.168 -
1.169 - GST_DEBUG_CATEGORY_INIT (nuvdemux_debug, "nuvdemux",
1.170 - 0, "Demuxer for NUV streams");
1.171 -
1.172 - parent_class = g_type_class_peek_parent (klass);
1.173 -
1.174 - gobject_class->finalize = gst_nuv_demux_finalize;
1.175 - gstelement_class->change_state = gst_nuv_demux_change_state;
1.176 -}
1.177 -
1.178 -static void
1.179 -gst_nuv_demux_init (GstNuvDemux * nuv, GstNuvDemuxClass * nuv_class)
1.180 -{
1.181 - nuv->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink");
1.182 -
1.183 - gst_pad_set_activate_function (nuv->sinkpad, gst_nuv_demux_sink_activate);
1.184 -
1.185 - gst_pad_set_activatepull_function (nuv->sinkpad,
1.186 - gst_nuv_demux_sink_activate_pull);
1.187 -
1.188 - gst_pad_set_chain_function (nuv->sinkpad,
1.189 - GST_DEBUG_FUNCPTR (gst_nuv_demux_chain));
1.190 -
1.191 - gst_pad_set_event_function (nuv->sinkpad, gst_nuv_demux_handle_sink_event);
1.192 -
1.193 - gst_element_add_pad (GST_ELEMENT (nuv), nuv->sinkpad);
1.194 -
1.195 - gst_nuv_demux_index_init( &nuv->index_entries );
1.196 -
1.197 - nuv->adapter = NULL;
1.198 - nuv->mpeg_buffer = NULL;
1.199 - nuv->h = NULL;
1.200 - nuv->eh = NULL;
1.201 - nuv->fh = NULL;
1.202 - gst_nuv_demux_reset (nuv);
1.203 -}
1.204 -
1.205 -static void
1.206 -gst_nuv_demux_finalize (GObject * object)
1.207 -{
1.208 - GstNuvDemux *nuv = GST_NUV_DEMUX (object);
1.209 -
1.210 - if (nuv->mpeg_buffer != NULL) {
1.211 - gst_buffer_unref (nuv->mpeg_buffer);
1.212 - }
1.213 -
1.214 - if ( nuv->index_entries != NULL ) {
1.215 - gst_nuv_demux_index_clean( &nuv->index_entries );
1.216 - nuv->index_entries = NULL;
1.217 - }
1.218 -
1.219 - gst_nuv_demux_destoy_src_pad (nuv);
1.220 - gst_nuv_demux_reset (nuv);
1.221 - if (nuv->adapter != NULL) {
1.222 - gst_object_unref (nuv->adapter);
1.223 - }
1.224 - G_OBJECT_CLASS (parent_class)->finalize (object);
1.225 -}
1.226 -
1.227 -
1.228 -/*****************************************************************************
1.229 - * Indexes (timecode offset conversion) functions
1.230 - *****************************************************************************/
1.231 -
1.232 -static void
1.233 -gst_nuv_demux_index_init( nuv_demux_index **p_idx )
1.234 -{
1.235 - *p_idx = g_new0( nuv_demux_index, 1 );
1.236 - (*p_idx)->i_idx = 0;
1.237 - (*p_idx)->i_idx_max = 0;
1.238 -}
1.239 -
1.240 -static void
1.241 -gst_nuv_demux_index_clean( nuv_demux_index **p_idx )
1.242 -{
1.243 - if ( *p_idx != NULL ) {
1.244 - g_free( *p_idx );
1.245 - *p_idx = NULL;
1.246 - }
1.247 -
1.248 -}
1.249 -
1.250 -static void
1.251 -gst_nuv_demux_index_append( GstNuvDemux *nuv, gint64 i_time, gint64 i_offset )
1.252 -{
1.253 - nuv_demux_index *p_idx = nuv->index_entries;
1.254 -
1.255 - //if ( p_idx == NULL )
1.256 - // return;
1.257 -
1.258 - /* Be sure to append new entry (we don't insert point) */
1.259 - if( p_idx != NULL && p_idx->i_idx > 0 && p_idx->idx[p_idx->i_idx-1].i_time >= i_time )
1.260 - return;
1.261 -
1.262 - /* */
1.263 - if( p_idx->i_idx >= p_idx->i_idx_max )
1.264 - {
1.265 - if( p_idx->i_idx >= DEMUX_INDEX_SIZE_MAX )
1.266 - {
1.267 - /* Avoid too big index */
1.268 - const gint64 i_length = p_idx->idx[p_idx->i_idx-1].i_time -
1.269 - p_idx->idx[0].i_time;
1.270 - const gint i_count = DEMUX_INDEX_SIZE_MAX/2;
1.271 - gint i, j;
1.272 -
1.273 - /* We try to reduce the resolution of the index by a factor 2 */
1.274 - for( i = 1, j = 1; i < p_idx->i_idx; i++ )
1.275 - {
1.276 - if( p_idx->idx[i].i_time < j * i_length / i_count )
1.277 - continue;
1.278 -
1.279 - p_idx->idx[j++] = p_idx->idx[i];
1.280 - }
1.281 - p_idx->i_idx = j;
1.282 -
1.283 - if( p_idx->i_idx > 3 * DEMUX_INDEX_SIZE_MAX / 4 )
1.284 - {
1.285 - /* We haven't created enough space
1.286 - * (This method won't create a good index but work for sure) */
1.287 - for( i = 0; i < p_idx->i_idx/2; i++ )
1.288 - p_idx->idx[i] = p_idx->idx[2*i];
1.289 - p_idx->i_idx /= 2;
1.290 - }
1.291 - }
1.292 - else
1.293 - {
1.294 - p_idx->i_idx_max += 1000;
1.295 - }
1.296 - }
1.297 -
1.298 - /* */
1.299 - p_idx->idx[p_idx->i_idx].i_time = i_time;
1.300 - p_idx->idx[p_idx->i_idx].i_offset = i_offset;
1.301 -
1.302 - p_idx->i_idx++;
1.303 -}
1.304 -
1.305 -static gint64
1.306 -gst_nuv_demux_index_convert_time( GstNuvDemux *nuv, gint64 i_time )
1.307 -{
1.308 - nuv_demux_index *p_idx = nuv->index_entries;
1.309 -
1.310 - g_return_val_if_fail( p_idx != NULL , i_time );
1.311 -
1.312 - gint i_min = 0;
1.313 - gint i_max = p_idx->i_idx-1;
1.314 -
1.315 - /* Empty index */
1.316 - if( p_idx->i_idx <= 0 )
1.317 - return -1;
1.318 -
1.319 - /* Special border case */
1.320 - if( i_time <= p_idx->idx[0].i_time )
1.321 - return p_idx->idx[0].i_offset;
1.322 - if( i_time >= p_idx->idx[i_max].i_time )
1.323 - return p_idx->idx[i_max].i_offset;
1.324 -
1.325 - /* Dicho */
1.326 - for( ;; )
1.327 - {
1.328 - gint i_med;
1.329 -
1.330 - if( i_max - i_min <= 1 )
1.331 - break;
1.332 -
1.333 - i_med = (i_min+i_max)/2;
1.334 - if( p_idx->idx[i_med].i_time < i_time )
1.335 - i_min = i_med;
1.336 - else if( p_idx->idx[i_med].i_time > i_time )
1.337 - i_max = i_med;
1.338 - else
1.339 - return p_idx->idx[i_med].i_offset;
1.340 - }
1.341 -
1.342 - /* return nearest in time */
1.343 - if( i_time - p_idx->idx[i_min].i_time < p_idx->idx[i_max].i_time - i_time )
1.344 - return p_idx->idx[i_min].i_offset;
1.345 - else
1.346 - return p_idx->idx[i_max].i_offset;
1.347 -}
1.348 -
1.349 -/*****************************************************************************
1.350 - * Utils functions
1.351 - *****************************************************************************/
1.352 -
1.353 -static gboolean
1.354 -gst_nuv_demux_handle_sink_event (GstPad * sinkpad, GstEvent * event)
1.355 -{
1.356 - gboolean res = FALSE;
1.357 -
1.358 - switch (GST_EVENT_TYPE (event)) {
1.359 - case GST_EVENT_NEWSEGMENT:
1.360 - res = TRUE;
1.361 - break;
1.362 - default:
1.363 - return gst_pad_event_default (sinkpad, event);
1.364 - break;
1.365 - }
1.366 -
1.367 - gst_event_unref (event);
1.368 - return res;
1.369 -}
1.370 -
1.371 -/* HeaderLoad:
1.372 - */
1.373 -static GstFlowReturn
1.374 -gst_nuv_demux_header_load (GstNuvDemux * nuv, nuv_header ** h_ret)
1.375 -{
1.376 - GstBuffer *buffer = NULL;
1.377 - GstFlowReturn res = gst_nuv_demux_read_bytes (nuv, 72, TRUE, &buffer);
1.378 -
1.379 - if (res != GST_FLOW_OK)
1.380 - return res;
1.381 -
1.382 - nuv_header *h = g_new0 (nuv_header, 1);
1.383 -
1.384 - memcpy (h->id, buffer->data, 12);
1.385 - memcpy (h->version, buffer->data + 12, 5);
1.386 - h->i_width = GST_READ_UINT32_LE (&buffer->data[20]);
1.387 - h->i_height = GST_READ_UINT32_LE (&buffer->data[24]);
1.388 - h->i_width_desired = GST_READ_UINT32_LE (&buffer->data[28]);
1.389 - h->i_height_desired = GST_READ_UINT32_LE (&buffer->data[32]);
1.390 - h->i_mode = buffer->data[36];
1.391 - h->d_aspect = READ_DOUBLE_FROM_LE (&buffer->data[40]);
1.392 - h->d_fps = READ_DOUBLE_FROM_LE (&buffer->data[48]);
1.393 - h->i_video_blocks = GST_READ_UINT32_LE (&buffer->data[56]);
1.394 - h->i_audio_blocks = GST_READ_UINT32_LE (&buffer->data[60]);
1.395 - h->i_text_blocks = GST_READ_UINT32_LE (&buffer->data[64]);
1.396 - h->i_keyframe_distance = GST_READ_UINT32_LE (&buffer->data[68]);
1.397 -
1.398 - GST_DEBUG_OBJECT (nuv,
1.399 - "nuv: h=%s v=%s %dx%d a=%f fps=%f v=%d a=%d t=%d kfd=%d", h->id,
1.400 - h->version, h->i_width, h->i_height, h->d_aspect, h->d_fps,
1.401 - h->i_video_blocks, h->i_audio_blocks, h->i_text_blocks,
1.402 - h->i_keyframe_distance);
1.403 -
1.404 - *h_ret = h;
1.405 - gst_buffer_unref (buffer);
1.406 - return res;
1.407 -}
1.408 -
1.409 -static GstFlowReturn
1.410 -gst_nuv_demux_stream_header_data (GstNuvDemux * nuv)
1.411 -{
1.412 - GstFlowReturn res = gst_nuv_demux_header_load (nuv, &nuv->h);
1.413 -
1.414 - if (res == GST_FLOW_OK)
1.415 - nuv->state = GST_NUV_DEMUX_EXTRA_DATA;
1.416 - return res;
1.417 -}
1.418 -
1.419 -/*
1.420 - * Read NUV file tag
1.421 - */
1.422 -static GstFlowReturn
1.423 -gst_nuv_demux_stream_file_header (GstNuvDemux * nuv)
1.424 -{
1.425 - GstFlowReturn res = GST_FLOW_OK;
1.426 - GstBuffer *file_header = NULL;
1.427 -
1.428 - res = gst_nuv_demux_read_bytes (nuv, 12, FALSE, &file_header);
1.429 - if (res != GST_FLOW_OK) {
1.430 - return res;
1.431 - } else {
1.432 - if (strncmp ((gchar *) file_header->data, "MythTVVideo", 11) ||
1.433 - strncmp ((gchar *) file_header->data, "NuppelVideo", 11)) {
1.434 - nuv->state = GST_NUV_DEMUX_HEADER_DATA;
1.435 - } else {
1.436 - GST_DEBUG_OBJECT (nuv, "error parsing file header");
1.437 - nuv->state = GST_NUV_DEMUX_INVALID_DATA;
1.438 - res = GST_FLOW_ERROR;
1.439 - }
1.440 - }
1.441 - if (file_header != NULL) {
1.442 - gst_buffer_unref (file_header);
1.443 - }
1.444 - return res;
1.445 -}
1.446 -
1.447 -/* FrameHeaderLoad:
1.448 - */
1.449 -static GstFlowReturn
1.450 -gst_nuv_demux_frame_header_load (GstNuvDemux * nuv, nuv_frame_header ** h_ret)
1.451 -{
1.452 - unsigned char *data;
1.453 - nuv_frame_header *h;
1.454 - GstBuffer *buf = NULL;
1.455 -
1.456 - GstFlowReturn res = gst_nuv_demux_read_bytes (nuv, 12, TRUE, &buf);
1.457 -
1.458 - if (res != GST_FLOW_OK) {
1.459 - if (buf != NULL) {
1.460 - gst_buffer_unref (buf);
1.461 - }
1.462 - return res;
1.463 - }
1.464 -
1.465 - h = g_new0 (nuv_frame_header, 1);
1.466 - data = buf->data;
1.467 -
1.468 - h->i_type = data[0];
1.469 - h->i_compression = data[1];
1.470 - h->i_keyframe = data[2];
1.471 - h->i_filters = data[3];
1.472 -
1.473 - h->i_timecode = GST_READ_UINT32_LE (&data[4]);
1.474 -
1.475 -
1.476 - h->i_length = GST_READ_UINT32_LE (&data[8]);
1.477 - GST_DEBUG_OBJECT (nuv, "frame hdr: t=%c c=%c k=%d f=0x%x timecode=%d l=%d",
1.478 - h->i_type,
1.479 - h->i_compression ? h->i_compression : ' ',
1.480 - h->i_keyframe ? h->i_keyframe : ' ',
1.481 - h->i_filters, h->i_timecode, h->i_length);
1.482 -
1.483 - *h_ret = h;
1.484 - gst_buffer_unref (buf);
1.485 - return GST_FLOW_OK;
1.486 -}
1.487 -
1.488 -static GstFlowReturn
1.489 -gst_nuv_demux_extended_header_load (GstNuvDemux * nuv,
1.490 - nuv_extended_header ** h_ret)
1.491 -{
1.492 - unsigned char *data;
1.493 - GstBuffer *buff = NULL;
1.494 - nuv_extended_header *h;
1.495 -
1.496 -
1.497 - GstFlowReturn res = gst_nuv_demux_read_bytes (nuv, 512, TRUE, &buff);
1.498 -
1.499 - if (res != GST_FLOW_OK) {
1.500 - if (buff != NULL) {
1.501 - gst_buffer_unref (buff);
1.502 - }
1.503 - return res;
1.504 - }
1.505 -
1.506 - h = g_new0 (nuv_extended_header, 1);
1.507 - data = buff->data;
1.508 - h->i_version = GST_READ_UINT32_LE (&data[0]);
1.509 - h->i_video_fcc = GST_MAKE_FOURCC (data[4], data[5], data[6], data[7]);
1.510 - h->i_audio_fcc = GST_MAKE_FOURCC (data[8], data[9], data[10], data[11]);
1.511 - h->i_audio_sample_rate = GST_READ_UINT32_LE (&data[12]);
1.512 - h->i_audio_bits_per_sample = GST_READ_UINT32_LE (&data[16]);
1.513 - h->i_audio_channels = GST_READ_UINT32_LE (&data[20]);
1.514 - h->i_audio_compression_ratio = GST_READ_UINT32_LE (&data[24]);
1.515 - h->i_audio_quality = GST_READ_UINT32_LE (&data[28]);
1.516 - h->i_rtjpeg_quality = GST_READ_UINT32_LE (&data[32]);
1.517 - h->i_rtjpeg_luma_filter = GST_READ_UINT32_LE (&data[36]);
1.518 - h->i_rtjpeg_chroma_filter = GST_READ_UINT32_LE (&data[40]);
1.519 - h->i_lavc_bitrate = GST_READ_UINT32_LE (&data[44]);
1.520 - h->i_lavc_qmin = GST_READ_UINT32_LE (&data[48]);
1.521 - h->i_lavc_qmin = GST_READ_UINT32_LE (&data[52]);
1.522 - h->i_lavc_maxqdiff = GST_READ_UINT32_LE (&data[56]);
1.523 - h->i_seekable_offset = GST_READ_UINT64_LE (&data[60]);
1.524 - h->i_keyframe_adjust_offset = GST_READ_UINT64_LE (&data[68]);
1.525 -
1.526 - GST_DEBUG_OBJECT (nuv,
1.527 - "ex hdr: v=%d vffc=%4.4s afcc=%4.4s %dHz %dbits ach=%d acr=%d aq=%d"
1.528 - "rtjpeg q=%d lf=%d lc=%d lavc br=%d qmin=%d qmax=%d maxqdiff=%d seekableoff=%lld keyfao=%lld",
1.529 - h->i_version, (gchar *) & h->i_video_fcc, (gchar *) & h->i_audio_fcc,
1.530 - h->i_audio_sample_rate, h->i_audio_bits_per_sample, h->i_audio_channels,
1.531 - h->i_audio_compression_ratio, h->i_audio_quality, h->i_rtjpeg_quality,
1.532 - h->i_rtjpeg_luma_filter, h->i_rtjpeg_chroma_filter, h->i_lavc_bitrate,
1.533 - h->i_lavc_qmin, h->i_lavc_qmax, h->i_lavc_maxqdiff, h->i_seekable_offset,
1.534 - h->i_keyframe_adjust_offset);
1.535 -
1.536 - *h_ret = h;
1.537 - gst_buffer_unref (buff);
1.538 - return res;
1.539 -}
1.540 -
1.541 -static gboolean
1.542 -gst_nuv_demux_handle_audio_src_event (GstPad * pad, GstEvent * event)
1.543 -{
1.544 - gst_event_unref (event);
1.545 - return FALSE;
1.546 -}
1.547 -
1.548 -static gboolean
1.549 -gst_nuv_demux_handle_video_src_event (GstPad * pad, GstEvent * event)
1.550 -{
1.551 - gst_event_unref (event);
1.552 - return FALSE;
1.553 -}
1.554 -
1.555 -static void
1.556 -gst_nuv_demux_create_pads (GstNuvDemux * nuv)
1.557 -{
1.558 - if (nuv->h->i_video_blocks != 0) {
1.559 - GstCaps *video_caps = NULL;
1.560 -
1.561 - nuv->src_video_pad =
1.562 - gst_pad_new_from_static_template (&video_src_template, "video_src");
1.563 -
1.564 - video_caps = gst_caps_new_simple ("video/x-divx",
1.565 - "divxversion", G_TYPE_INT, 4,
1.566 - "width", G_TYPE_INT, nuv->h->i_width,
1.567 - "height", G_TYPE_INT, nuv->h->i_height,
1.568 - "framerate", GST_TYPE_FRACTION, (gint) (nuv->h->d_fps * 1000.0f), 1000,
1.569 - "pixel-aspect-ratio", GST_TYPE_FRACTION,
1.570 - (gint) (nuv->h->d_aspect * 1000.0f), 1000, NULL);
1.571 -
1.572 - gst_pad_use_fixed_caps (nuv->src_video_pad);
1.573 - gst_pad_set_caps (nuv->src_video_pad, video_caps);
1.574 -
1.575 - gst_pad_set_event_function (nuv->src_video_pad,
1.576 - gst_nuv_demux_handle_video_src_event);
1.577 - gst_pad_set_active (nuv->src_video_pad, TRUE);
1.578 - gst_element_add_pad (GST_ELEMENT (nuv), nuv->src_video_pad);
1.579 -
1.580 - gst_caps_unref (video_caps);
1.581 - }
1.582 -
1.583 - if (nuv->h->i_audio_blocks != 0) {
1.584 - GstCaps *audio_caps = NULL;
1.585 -
1.586 - nuv->src_audio_pad =
1.587 - gst_pad_new_from_static_template (&audio_src_template, "audio_src");
1.588 -
1.589 - audio_caps = gst_caps_new_simple ("audio/mpeg",
1.590 - "rate", G_TYPE_INT, nuv->eh->i_audio_sample_rate,
1.591 - "format", GST_TYPE_FOURCC, nuv->eh->i_audio_fcc,
1.592 - "channels", G_TYPE_INT, nuv->eh->i_audio_channels,
1.593 - "mpegversion", G_TYPE_INT, nuv->eh->i_version, NULL);
1.594 -
1.595 - gst_pad_use_fixed_caps (nuv->src_audio_pad);
1.596 - gst_pad_set_caps (nuv->src_audio_pad, audio_caps);
1.597 -
1.598 - gst_pad_set_event_function (nuv->src_audio_pad,
1.599 - gst_nuv_demux_handle_audio_src_event);
1.600 - gst_pad_set_active (nuv->src_audio_pad, TRUE);
1.601 - gst_element_add_pad (GST_ELEMENT (nuv), nuv->src_audio_pad);
1.602 -
1.603 - gst_caps_unref (audio_caps);
1.604 - }
1.605 -
1.606 - gst_element_no_more_pads (GST_ELEMENT (nuv));
1.607 -}
1.608 -
1.609 -static GstFlowReturn
1.610 -gst_nuv_demux_read_head_frame (GstNuvDemux * nuv)
1.611 -{
1.612 - GstFlowReturn ret = GST_FLOW_OK;
1.613 -
1.614 - ret = gst_nuv_demux_frame_header_load (nuv, &nuv->fh);
1.615 - if (ret != GST_FLOW_OK)
1.616 - return ret;
1.617 -
1.618 - nuv->state = GST_NUV_DEMUX_MOVI;
1.619 - return ret;
1.620 -}
1.621 -
1.622 -static GstFlowReturn
1.623 -gst_nuv_demux_stream_data (GstNuvDemux * nuv)
1.624 -{
1.625 - GstFlowReturn ret = GST_FLOW_OK;
1.626 - GstBuffer *buf = NULL;
1.627 - nuv_frame_header *h = nuv->fh;
1.628 -
1.629 - gint64 table_timecode = 0;
1.630 -
1.631 - if (h->i_type == 'R')
1.632 - goto done;
1.633 -
1.634 - table_timecode = h->i_timecode;
1.635 -
1.636 - /* append the frame's header timecode field, and the actual offset */
1.637 - if ( h->i_type == 'V' )
1.638 - gst_nuv_demux_index_append( nuv, h->i_timecode, nuv->video_offset );
1.639 - else if ( h->i_type == 'A' )
1.640 - gst_nuv_demux_index_append( nuv, h->i_timecode, nuv->audio_offset );
1.641 -
1.642 - if (h->i_length > 0) {
1.643 - ret = gst_nuv_demux_read_bytes (nuv, h->i_length, TRUE, &buf);
1.644 - if (ret != GST_FLOW_OK)
1.645 - return ret;
1.646 -
1.647 - /* search for a valid timecode in the indexes list (find the nearest valid timecode) */
1.648 - if ( h->i_timecode < 0 ) {
1.649 - /* convert this actual timecode to a valid index in the timecode's table */
1.650 - gint64 pos = gst_nuv_demux_index_convert_time( nuv, h->i_timecode );
1.651 -
1.652 - /* just get the timecode from the timecode's table */
1.653 - table_timecode = nuv->index_entries->idx[pos].i_time * GST_MSECOND;
1.654 - } else {
1.655 - table_timecode = h->i_timecode * GST_MSECOND;
1.656 - }
1.657 -
1.658 - GST_BUFFER_TIMESTAMP (buf) = table_timecode;
1.659 - }
1.660 -
1.661 - switch (h->i_type) {
1.662 - case 'V':
1.663 - {
1.664 - if (h->i_length == 0)
1.665 - break;
1.666 -
1.667 - if ( !gst_pad_is_linked( nuv->src_video_pad ) )
1.668 - break;
1.669 -
1.670 - //GST_PAD_STREAM_LOCK(nuv->src_video_pad);
1.671 -
1.672 - GST_BUFFER_SIZE (buf) = h->i_length;
1.673 - gst_buffer_set_caps (buf, GST_PAD_CAPS (nuv->src_video_pad));
1.674 - ret = gst_pad_push (nuv->src_video_pad, buf);
1.675 - nuv->video_offset += h->i_length;
1.676 -
1.677 - //GST_PAD_STREAM_UNLOCK(nuv->src_video_pad);
1.678 - break;
1.679 - }
1.680 - case 'A':
1.681 - {
1.682 - if (h->i_length == 0)
1.683 - break;
1.684 -
1.685 - if ( !gst_pad_is_linked( nuv->src_audio_pad ) )
1.686 - break;
1.687 -
1.688 - //GST_PAD_STREAM_LOCK(nuv->src_audio_pad);
1.689 -
1.690 - GST_BUFFER_SIZE (buf) = h->i_length;
1.691 - gst_buffer_set_caps (buf, GST_PAD_CAPS (nuv->src_audio_pad));
1.692 - ret = gst_pad_push (nuv->src_audio_pad, buf);
1.693 - nuv->audio_offset += h->i_length;
1.694 -
1.695 - //GST_PAD_STREAM_UNLOCK(nuv->src_audio_pad);
1.696 - break;
1.697 - }
1.698 - case 'S':
1.699 - {
1.700 - switch (h->i_compression) {
1.701 - case 'V':
1.702 - if ( !gst_pad_is_linked( nuv->src_video_pad ) )
1.703 - break;
1.704 -
1.705 - //GST_PAD_STREAM_LOCK(nuv->src_video_pad);
1.706 - gst_pad_push_event (nuv->src_video_pad,
1.707 - gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME, table_timecode,
1.708 - GST_CLOCK_TIME_NONE, 0));
1.709 - //GST_PAD_STREAM_UNLOCK(nuv->src_video_pad);
1.710 - break;
1.711 - case 'A':
1.712 - if ( !gst_pad_is_linked( nuv->src_audio_pad ) )
1.713 - break;
1.714 -
1.715 - //GST_PAD_STREAM_LOCK(nuv->src_audio_pad);
1.716 - gst_pad_push_event (nuv->src_audio_pad,
1.717 - gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME, table_timecode,
1.718 - GST_CLOCK_TIME_NONE, 0));
1.719 - //GST_PAD_STREAM_UNLOCK(nuv->src_audio_pad);
1.720 - break;
1.721 - default:
1.722 - break;
1.723 - }
1.724 - }
1.725 - default:
1.726 - if (buf != NULL)
1.727 - gst_buffer_unref (buf);
1.728 -
1.729 - break;
1.730 - }
1.731 -
1.732 -done:
1.733 - nuv->state = GST_NUV_DEMUX_FRAME_HEADER;
1.734 - g_free (nuv->fh);
1.735 - nuv->fh = NULL;
1.736 - return ret;
1.737 -}
1.738 -
1.739 -static GstFlowReturn
1.740 -gst_nuv_demux_stream_mpeg_data (GstNuvDemux * nuv)
1.741 -{
1.742 - GstFlowReturn ret = GST_FLOW_OK;
1.743 -
1.744 - /* ffmpeg extra data */
1.745 - ret =
1.746 - gst_nuv_demux_read_bytes (nuv, nuv->mpeg_data_size, TRUE,
1.747 - &nuv->mpeg_buffer);
1.748 - if (ret != GST_FLOW_OK) {
1.749 - return ret; //GST_FLOW_ERROR;
1.750 - }
1.751 - GST_BUFFER_SIZE (nuv->mpeg_buffer) = nuv->mpeg_data_size;
1.752 - nuv->state = GST_NUV_DEMUX_EXTEND_HEADER;
1.753 - return ret;
1.754 -}
1.755 -
1.756 -static GstFlowReturn
1.757 -gst_nuv_demux_stream_extra_data (GstNuvDemux * nuv)
1.758 -{
1.759 - GstFlowReturn ret = GST_FLOW_OK;
1.760 -
1.761 - /* Load 'D' */
1.762 - nuv_frame_header *h;
1.763 -
1.764 - ret = gst_nuv_demux_frame_header_load (nuv, &h);
1.765 - if (ret != GST_FLOW_OK)
1.766 - return ret;
1.767 -
1.768 - if (h->i_type != 'D') {
1.769 - g_free (h);
1.770 - return GST_FLOW_ERROR;
1.771 - }
1.772 -
1.773 - if (h->i_length > 0) {
1.774 - if (h->i_compression == 'F') {
1.775 - nuv->state = GST_NUV_DEMUX_MPEG_DATA;
1.776 - } else {
1.777 - g_free (h);
1.778 - return GST_FLOW_ERROR;
1.779 - }
1.780 - } else {
1.781 - nuv->state = GST_NUV_DEMUX_EXTEND_HEADER;
1.782 - }
1.783 -
1.784 - g_free (h);
1.785 - h = NULL;
1.786 - return ret;
1.787 -}
1.788 -
1.789 -static GstFlowReturn
1.790 -gst_nuv_demux_stream_extend_header_data (GstNuvDemux * nuv)
1.791 -{
1.792 - GstFlowReturn ret = GST_FLOW_OK;
1.793 -
1.794 - ret = gst_nuv_demux_extended_header_load (nuv, &nuv->eh);
1.795 - if (ret != GST_FLOW_OK)
1.796 - return ret;
1.797 -
1.798 - gst_nuv_demux_create_pads (nuv);
1.799 - nuv->state = GST_NUV_DEMUX_FRAME_HEADER;
1.800 - return ret;
1.801 -}
1.802 -
1.803 -static GstFlowReturn
1.804 -gst_nuv_demux_stream_extend_header (GstNuvDemux * nuv)
1.805 -{
1.806 - GstBuffer *buf = NULL;
1.807 - GstFlowReturn res = GST_FLOW_OK;
1.808 -
1.809 - res = gst_nuv_demux_read_bytes (nuv, 1, FALSE, &buf);
1.810 - if (res != GST_FLOW_OK) {
1.811 - if (buf != NULL) {
1.812 - gst_buffer_unref (buf);
1.813 - }
1.814 - return res;
1.815 - }
1.816 -
1.817 - if (buf->data[0] == 'X') {
1.818 - gst_buffer_unref (buf);
1.819 - buf = NULL;
1.820 - nuv_frame_header *h = NULL;
1.821 -
1.822 - res = gst_nuv_demux_frame_header_load (nuv, &h);
1.823 - if (res != GST_FLOW_OK)
1.824 - return res;
1.825 -
1.826 - if (h->i_length != 512) {
1.827 - g_free (h);
1.828 - return GST_FLOW_ERROR;
1.829 - }
1.830 - g_free (h);
1.831 - h = NULL;
1.832 - nuv->state = GST_NUV_DEMUX_EXTEND_HEADER_DATA;
1.833 - } else {
1.834 - nuv->state = GST_NUV_DEMUX_INVALID_DATA;
1.835 - g_object_unref (buf);
1.836 - GST_ELEMENT_WARNING (nuv, STREAM, FAILED,
1.837 - (_("incomplete NUV support")), ("incomplete NUV support"));
1.838 - return GST_FLOW_ERROR;
1.839 - }
1.840 - return res;
1.841 -}
1.842 -
1.843 -static GstFlowReturn
1.844 -gst_nuv_demux_play (GstPad * pad)
1.845 -{
1.846 - GstFlowReturn res = GST_FLOW_OK;
1.847 - GstNuvDemux *nuv = GST_NUV_DEMUX (GST_PAD_PARENT (pad));
1.848 -
1.849 - switch (nuv->state) {
1.850 - case GST_NUV_DEMUX_START:
1.851 - res = gst_nuv_demux_stream_file_header (nuv);
1.852 - if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) {
1.853 - goto pause;
1.854 - }
1.855 - if (nuv->state != GST_NUV_DEMUX_HEADER_DATA)
1.856 - break;
1.857 -
1.858 - case GST_NUV_DEMUX_HEADER_DATA:
1.859 - res = gst_nuv_demux_stream_header_data (nuv);
1.860 - if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) {
1.861 - goto pause;
1.862 - }
1.863 - if (nuv->state != GST_NUV_DEMUX_EXTRA_DATA)
1.864 - break;
1.865 -
1.866 - case GST_NUV_DEMUX_EXTRA_DATA:
1.867 - res = gst_nuv_demux_stream_extra_data (nuv);
1.868 - if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) {
1.869 - goto pause;
1.870 - }
1.871 - if (nuv->state != GST_NUV_DEMUX_MPEG_DATA)
1.872 - break;
1.873 -
1.874 - case GST_NUV_DEMUX_MPEG_DATA:
1.875 - res = gst_nuv_demux_stream_mpeg_data (nuv);
1.876 - if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) {
1.877 - goto pause;
1.878 - }
1.879 -
1.880 - if (nuv->state != GST_NUV_DEMUX_EXTEND_HEADER)
1.881 - break;
1.882 -
1.883 - case GST_NUV_DEMUX_EXTEND_HEADER:
1.884 - res = gst_nuv_demux_stream_extend_header (nuv);
1.885 - if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) {
1.886 - goto pause;
1.887 - }
1.888 - if (nuv->state != GST_NUV_DEMUX_EXTEND_HEADER_DATA)
1.889 - break;
1.890 -
1.891 - case GST_NUV_DEMUX_EXTEND_HEADER_DATA:
1.892 - res = gst_nuv_demux_stream_extend_header_data (nuv);
1.893 - if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) {
1.894 - goto pause;
1.895 - }
1.896 -
1.897 - if (nuv->state != GST_NUV_DEMUX_FRAME_HEADER)
1.898 - break;
1.899 -
1.900 - case GST_NUV_DEMUX_FRAME_HEADER:
1.901 - res = gst_nuv_demux_read_head_frame (nuv);
1.902 - if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) {
1.903 - goto pause;
1.904 - }
1.905 - if (nuv->state != GST_NUV_DEMUX_MOVI)
1.906 - break;
1.907 -
1.908 - case GST_NUV_DEMUX_MOVI:
1.909 - res = gst_nuv_demux_stream_data (nuv);
1.910 - if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA) && (res != GST_FLOW_CUSTOM_ERROR)) {
1.911 - goto pause;
1.912 - }
1.913 - break;
1.914 - case GST_NUV_DEMUX_INVALID_DATA:
1.915 - goto pause;
1.916 - break;
1.917 - default:
1.918 - g_assert_not_reached ();
1.919 - }
1.920 -
1.921 - GST_DEBUG_OBJECT (nuv, "state: %d res:%s", nuv->state,
1.922 - gst_flow_get_name (res));
1.923 -
1.924 - return GST_FLOW_OK;
1.925 -
1.926 -pause:
1.927 - GST_LOG_OBJECT (nuv, "pausing task, reason %s", gst_flow_get_name (res));
1.928 - gst_pad_pause_task (nuv->sinkpad);
1.929 - if (GST_FLOW_IS_FATAL (res)) {
1.930 - GST_ELEMENT_ERROR (nuv, STREAM, FAILED,
1.931 - (_("Internal data stream error.")),
1.932 - ("streaming stopped, reason %s", gst_flow_get_name (res)));
1.933 -
1.934 - gst_nuv_demux_send_eos (nuv);
1.935 - }
1.936 - return res;
1.937 -}
1.938 -
1.939 -static void
1.940 -gst_nuv_demux_send_eos (GstNuvDemux * nuv)
1.941 -{
1.942 - gst_element_post_message (GST_ELEMENT (nuv),
1.943 - gst_message_new_segment_done (GST_OBJECT (nuv), GST_FORMAT_TIME, -1));
1.944 -
1.945 - if (nuv->src_video_pad)
1.946 - gst_pad_push_event (nuv->src_video_pad, gst_event_new_eos ());
1.947 - if (nuv->src_audio_pad)
1.948 - gst_pad_push_event (nuv->src_audio_pad, gst_event_new_eos ());
1.949 -}
1.950 -
1.951 -static GstFlowReturn
1.952 -gst_nuv_demux_read_bytes (GstNuvDemux * nuv, guint64 size, gboolean move,
1.953 - GstBuffer ** buffer)
1.954 -{
1.955 - GstFlowReturn ret = GST_FLOW_OK;
1.956 -
1.957 - if (size == 0) {
1.958 - *buffer = gst_buffer_new ();
1.959 - return ret;
1.960 - }
1.961 -
1.962 - if (nuv->mode == 0) {
1.963 - ret = gst_pad_pull_range (nuv->sinkpad, nuv->offset, size, buffer);
1.964 - if (ret == GST_FLOW_OK) {
1.965 - if (move) {
1.966 - nuv->offset += size;
1.967 - }
1.968 - /* got eos */
1.969 - } else if (ret == GST_FLOW_UNEXPECTED) {
1.970 - gst_nuv_demux_send_eos (nuv);
1.971 - return GST_FLOW_WRONG_STATE;
1.972 - }
1.973 - } else {
1.974 - if (gst_adapter_available (nuv->adapter) < size)
1.975 - return GST_FLOW_ERROR_NO_DATA;
1.976 -
1.977 - if (move) {
1.978 - *buffer = gst_adapter_take_buffer (nuv->adapter, size);
1.979 - } else {
1.980 - guint8 *data = NULL;
1.981 -
1.982 - data = (guint8 *) gst_adapter_peek (nuv->adapter, size);
1.983 - *buffer = gst_buffer_new ();
1.984 - gst_buffer_set_data (*buffer, data, size);
1.985 - }
1.986 - }
1.987 -
1.988 -
1.989 - return ret;
1.990 -}
1.991 -
1.992 -static gboolean
1.993 -gst_nuv_demux_sink_activate (GstPad * sinkpad)
1.994 -{
1.995 - gboolean res = TRUE;
1.996 - GstNuvDemux *nuv = GST_NUV_DEMUX (gst_pad_get_parent (sinkpad));
1.997 -
1.998 - if (gst_pad_check_pull_range (sinkpad)) {
1.999 - nuv->mode = 0;
1.1000 - if (nuv->adapter) {
1.1001 - gst_adapter_clear (nuv->adapter);
1.1002 - g_object_unref (nuv->adapter);
1.1003 - nuv->adapter = NULL;
1.1004 - }
1.1005 - res = gst_pad_activate_pull (sinkpad, TRUE);
1.1006 - } else {
1.1007 - nuv->mode = 1;
1.1008 - if (nuv->adapter) {
1.1009 - gst_adapter_clear (nuv->adapter);
1.1010 - } else {
1.1011 - nuv->adapter = gst_adapter_new ();
1.1012 - }
1.1013 - res = gst_pad_activate_push (sinkpad, TRUE);
1.1014 - }
1.1015 -
1.1016 - g_object_unref (nuv);
1.1017 - return res;
1.1018 -}
1.1019 -
1.1020 -static gboolean
1.1021 -gst_nuv_demux_sink_activate_pull (GstPad * sinkpad, gboolean active)
1.1022 -{
1.1023 - GstNuvDemux *nuv = GST_NUV_DEMUX (gst_pad_get_parent (sinkpad));
1.1024 -
1.1025 - if (active) {
1.1026 - gst_pad_start_task (sinkpad, (GstTaskFunction) gst_nuv_demux_loop, sinkpad);
1.1027 - } else {
1.1028 - gst_pad_stop_task (sinkpad);
1.1029 - }
1.1030 - gst_object_unref (nuv);
1.1031 -
1.1032 - return TRUE;
1.1033 -}
1.1034 -
1.1035 -static GstFlowReturn
1.1036 -gst_nuv_demux_chain (GstPad * pad, GstBuffer * buf)
1.1037 -{
1.1038 - GstNuvDemux *nuv = GST_NUV_DEMUX (gst_pad_get_parent (pad));
1.1039 -
1.1040 - gst_adapter_push (nuv->adapter, buf);
1.1041 -
1.1042 - return gst_nuv_demux_play (pad);
1.1043 -}
1.1044 -
1.1045 -static void
1.1046 -gst_nuv_demux_loop (GstPad * pad)
1.1047 -{
1.1048 - gst_nuv_demux_play (pad);
1.1049 -}
1.1050 -
1.1051 -static void
1.1052 -gst_nuv_demux_reset (GstNuvDemux * nuv)
1.1053 -{
1.1054 - nuv->state = GST_NUV_DEMUX_START;
1.1055 - nuv->mode = 0;
1.1056 - nuv->offset = 0;
1.1057 - nuv->video_offset = 0;
1.1058 - nuv->audio_offset = 0;
1.1059 -
1.1060 - if (nuv->adapter != NULL)
1.1061 - gst_adapter_clear (nuv->adapter);
1.1062 -
1.1063 - if (nuv->mpeg_buffer != NULL) {
1.1064 - gst_buffer_unref (nuv->mpeg_buffer);
1.1065 - nuv->mpeg_buffer = NULL;
1.1066 - }
1.1067 -
1.1068 - g_free (nuv->h);
1.1069 - nuv->h = NULL;
1.1070 -
1.1071 - g_free (nuv->eh);
1.1072 - nuv->eh = NULL;
1.1073 -
1.1074 - g_free (nuv->fh);
1.1075 - nuv->fh = NULL;
1.1076 -}
1.1077 -
1.1078 -static void
1.1079 -gst_nuv_demux_destoy_src_pad (GstNuvDemux * nuv)
1.1080 -{
1.1081 - if (nuv->src_video_pad) {
1.1082 - gst_element_remove_pad (GST_ELEMENT (nuv), nuv->src_video_pad);
1.1083 - nuv->src_video_pad = NULL;
1.1084 - }
1.1085 -
1.1086 - if (nuv->src_audio_pad) {
1.1087 - gst_element_remove_pad (GST_ELEMENT (nuv), nuv->src_audio_pad);
1.1088 - nuv->src_audio_pad = NULL;
1.1089 - }
1.1090 -}
1.1091 -
1.1092 -static GstStateChangeReturn
1.1093 -gst_nuv_demux_change_state (GstElement * element, GstStateChange transition)
1.1094 -{
1.1095 - GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
1.1096 -
1.1097 - switch (transition) {
1.1098 - case GST_STATE_CHANGE_READY_TO_PAUSED:
1.1099 - break;
1.1100 - default:
1.1101 - break;
1.1102 - }
1.1103 -
1.1104 - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1.1105 - if (ret == GST_STATE_CHANGE_FAILURE)
1.1106 - goto done;
1.1107 -
1.1108 - switch (transition) {
1.1109 - case GST_STATE_CHANGE_PAUSED_TO_READY:
1.1110 - gst_nuv_demux_destoy_src_pad (GST_NUV_DEMUX (element));
1.1111 - gst_nuv_demux_reset (GST_NUV_DEMUX (element));
1.1112 - break;
1.1113 - default:
1.1114 - break;
1.1115 - }
1.1116 -
1.1117 -done:
1.1118 - return ret;
1.1119 -}
1.1120 -
1.1121 -static gboolean
1.1122 -plugin_init (GstPlugin * plugin)
1.1123 -{
1.1124 -#ifdef ENABLE_NLS
1.1125 - setlocale (LC_ALL, "");
1.1126 - bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
1.1127 -#endif /* ENABLE_NLS */
1.1128 -
1.1129 - if (!gst_element_register (plugin, "nuvdemux", GST_RANK_SECONDARY,
1.1130 - GST_TYPE_NUV_DEMUX)) {
1.1131 - return FALSE;
1.1132 - }
1.1133 - return TRUE;
1.1134 -}
1.1135 -
1.1136 -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
1.1137 - GST_VERSION_MINOR,
1.1138 - "nuvdemux",
1.1139 - "Demuxes and muxes audio and video",
1.1140 - plugin_init, VERSION, "LGPL", "NuvDemux", "")