1.1 --- a/gst-plugins-nuvdemux/nuvdemux/gstnuvdemux.c Tue May 01 17:03:38 2007 +0100
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,1654 +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 -#include <math.h>
1.58 -
1.59 -#include "glib/gi18n.h"
1.60 -#include "gstnuvdemux.h"
1.61 -
1.62 -#define GST_NUV_DEMUX_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_NUV_DEMUX, GstNuvDemuxPrivate))
1.63 -
1.64 -GST_DEBUG_CATEGORY_STATIC (nuvdemux_debug);
1.65 -#define GST_CAT_DEFAULT nuvdemux_debug
1.66 -#define GST_FLOW_ERROR_NO_DATA -101
1.67 -#define GST_FLOW_ERROR_EOS -102
1.68 -
1.69 -enum
1.70 -{
1.71 - NUV_PUSH_MODE = 0,
1.72 - NUV_PULL_MODE
1.73 -};
1.74 -
1.75 -GST_DEBUG_CATEGORY_EXTERN (GST_CAT_EVENT);
1.76 -
1.77 -static const GstElementDetails gst_nuv_demux_details =
1.78 -GST_ELEMENT_DETAILS ("Nuv demuxer",
1.79 - "Codec/Demuxer",
1.80 - "Demultiplex a .nuv file into audio and video",
1.81 - "Renato Araujo Oliveira Filho <renato.filho@indt.org.br>,"
1.82 - "Rosfran Borges <rosfran.borges@indt.org.br>");
1.83 -
1.84 -
1.85 -/* file header */
1.86 -typedef struct
1.87 -{
1.88 - gchar id[12]; /* "NuppelVideo\0" or "MythTVVideo\0" */
1.89 - gchar version[5]; /* "x.xx\0" */
1.90 -
1.91 - gint i_width;
1.92 - gint i_height;
1.93 - gint i_width_desired;
1.94 - gint i_height_desired;
1.95 -
1.96 - gchar i_mode; /* P progressive, I interlaced */
1.97 -
1.98 - gdouble d_aspect; /* 1.0 squared pixel */
1.99 - gdouble d_fps;
1.100 - //fps num/denom
1.101 - gint i_fpsn;
1.102 - gint i_fpsd;
1.103 -
1.104 - gint i_video_blocks; /* 0 no video, -1 unknown */
1.105 - gint i_audio_blocks;
1.106 - gint i_text_blocks;
1.107 -
1.108 - gint i_keyframe_distance;
1.109 -
1.110 -} nuv_header;
1.111 -
1.112 -/* frame header */
1.113 -typedef struct
1.114 -{
1.115 - gchar i_type; /* A: audio, V: video, S: sync; T: test
1.116 - R: Seekpoint (string:RTjjjjjjjj)
1.117 - D: Extra data for codec */
1.118 - gchar i_compression; /* V: 0 uncompressed
1.119 - 1 RTJpeg
1.120 - 2 RTJpeg+lzo
1.121 - N black frame
1.122 - L copy last
1.123 - A: 0 uncompressed (44100 1-bits, 2ch)
1.124 - 1 lzo
1.125 - 2 layer 2
1.126 - 3 layer 3
1.127 - F flac
1.128 - S shorten
1.129 - N null frame loudless
1.130 - L copy last
1.131 - S: B audio and vdeo sync point
1.132 - A audio sync info (timecode == effective
1.133 - dsp frequency*100)
1.134 - V next video sync (timecode == next video
1.135 - frame num)
1.136 - S audio,video,text correlation */
1.137 - gchar i_keyframe; /* 0 keyframe, else no no key frame */
1.138 - guint8 i_filters; /* 0x01: gauss 5 pixel (8,2,2,2,2)/16
1.139 - 0x02: gauss 5 pixel (8,1,1,1,1)/12
1.140 - 0x04: cartoon filter */
1.141 -
1.142 - gint32 i_timecode; /* ms */
1.143 -
1.144 - gint i_length; /* V,A,T: length of following data
1.145 - S: length of packet correl */
1.146 -} nuv_frame_header;
1.147 -
1.148 -
1.149 -/* FIXME Not sure of this one */
1.150 -typedef struct
1.151 -{
1.152 - gint i_version;
1.153 - guint32 i_video_fcc;
1.154 -
1.155 - guint32 i_audio_fcc;
1.156 - gint i_audio_sample_rate;
1.157 - gint i_audio_bits_per_sample;
1.158 - gint i_audio_channels;
1.159 - gint i_audio_compression_ratio;
1.160 - gint i_audio_quality;
1.161 - gint i_rtjpeg_quality;
1.162 - gint i_rtjpeg_luma_filter;
1.163 - gint i_rtjpeg_chroma_filter;
1.164 - gint i_lavc_bitrate;
1.165 - gint i_lavc_qmin;
1.166 - gint i_lavc_qmax;
1.167 - gint i_lavc_maxqdiff;
1.168 - gint64 i_seekable_offset;
1.169 - gint64 i_keyframe_adjust_offset;
1.170 -
1.171 -} nuv_extended_header;
1.172 -
1.173 -typedef struct
1.174 -{
1.175 - gint64 timecode;
1.176 - gint64 offset;
1.177 -
1.178 -} frame_index_data;
1.179 -
1.180 -typedef enum {
1.181 - GST_NUV_DEMUX_START,
1.182 - GST_NUV_DEMUX_HEADER_DATA,
1.183 - GST_NUV_DEMUX_EXTRA_DATA,
1.184 - GST_NUV_DEMUX_MPEG_DATA,
1.185 - GST_NUV_DEMUX_EXTEND_HEADER,
1.186 - GST_NUV_DEMUX_EXTEND_HEADER_DATA,
1.187 - GST_NUV_DEMUX_INDEX_CREATE,
1.188 - GST_NUV_DEMUX_FRAME_HEADER,
1.189 - GST_NUV_DEMUX_MOVI,
1.190 - GST_NUV_DEMUX_INVALID_DATA
1.191 -} GstNuvDemuxState;
1.192 -
1.193 -struct _GstNuvDemuxPrivate {
1.194 - /* used for indicate the mode */
1.195 - guint mode;
1.196 -
1.197 - /* used on push mode */
1.198 - GstAdapter *adapter;
1.199 -
1.200 - /* pads */
1.201 - GstPad *sinkpad;
1.202 - GstPad *src_video_pad;
1.203 - GstPad *src_audio_pad;
1.204 -
1.205 - /* Flow control */
1.206 - GstFlowReturn last_video_return;
1.207 - GstFlowReturn last_audio_return;
1.208 - gboolean more_data;
1.209 - gboolean eos;
1.210 -
1.211 - /* NUV decoding state */
1.212 - GstNuvDemuxState state;
1.213 - guint64 offset;
1.214 -
1.215 - /* duration information */
1.216 - guint64 duration_bytes;
1.217 - guint64 duration_time;
1.218 - guint64 segment_stop;
1.219 - guint64 segment_start;
1.220 -
1.221 - /* segment control info */
1.222 - gboolean new_audio_segment;
1.223 - gboolean new_video_segment;
1.224 -
1.225 - /* Mpeg ExtraData */
1.226 - guint64 mpeg_data_size;
1.227 - GstBuffer *mpeg_buffer;
1.228 -
1.229 - /* Headers */
1.230 - nuv_header h;
1.231 - nuv_extended_header eh;
1.232 - nuv_frame_header fh;
1.233 -
1.234 - /* anothers info */
1.235 - guint64 header_lengh;
1.236 - gint64 time_start;
1.237 - gint64 time_diff;
1.238 - gint64 time_qos;
1.239 - guint64 last_frame_time;
1.240 - GSList *index;
1.241 -};
1.242 -
1.243 -
1.244 -static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
1.245 - GST_PAD_SINK,
1.246 - GST_PAD_ALWAYS,
1.247 - GST_STATIC_CAPS ("video/x-nuv"));
1.248 -
1.249 -static GstStaticPadTemplate audio_src_template =
1.250 -GST_STATIC_PAD_TEMPLATE ("audio_src",
1.251 - GST_PAD_SRC,
1.252 - GST_PAD_SOMETIMES,
1.253 - GST_STATIC_CAPS_ANY);
1.254 -
1.255 -static GstStaticPadTemplate video_src_template =
1.256 -GST_STATIC_PAD_TEMPLATE ("video_src",
1.257 - GST_PAD_SRC,
1.258 - GST_PAD_SOMETIMES,
1.259 - GST_STATIC_CAPS_ANY);
1.260 -
1.261 -static void gst_nuv_demux_dispose (GObject * object);
1.262 -static void gst_nuv_demux_finalize (GObject * object);
1.263 -static GstStateChangeReturn gst_nuv_demux_change_state (GstElement * element,
1.264 - GstStateChange transition);
1.265 -static void gst_nuv_demux_loop (GstPad * pad);
1.266 -static GstFlowReturn gst_nuv_demux_chain (GstPad * pad, GstBuffer * buf);
1.267 -static GstFlowReturn gst_nuv_demux_play (GstPad * pad);
1.268 -static gboolean gst_nuv_demux_sink_activate_pull (GstPad * sinkpad,
1.269 - gboolean active);
1.270 -static gboolean gst_nuv_demux_sink_activate_push (GstPad * pad,
1.271 - gboolean active);
1.272 -static gboolean gst_nuv_demux_sink_activate (GstPad * sinkpad);
1.273 -//static gboolean gst_nuv_demux_sink_event (GstPad *pad, GstEvent *event);
1.274 -static gboolean gst_nuv_demux_srcpad_event (GstPad * pad, GstEvent * event);
1.275 -static frame_index_data * gst_nuv_demux_do_seek_index (GstNuvDemux *nuv, gint64 seek_pos,
1.276 - gint64 segment_stop, GstFormat format);
1.277 -
1.278 -
1.279 -
1.280 -static GstFlowReturn gst_nuv_demux_read_bytes (GstNuvDemux * nuv, guint64 size,
1.281 - gboolean move, GstBuffer ** buffer);
1.282 -static void gst_nuv_demux_reset (GstNuvDemux * nuv);
1.283 -static void gst_nuv_demux_destoy_src_pad (GstNuvDemux * nuv);
1.284 -static void gst_nuv_demux_send_eos (GstNuvDemux * nuv);
1.285 -static void gst_nuv_demux_create_seek_index (GstNuvDemux * nuv);
1.286 -
1.287 -
1.288 -#if (GST_VERSION_MINOR == 10) && (GST_VERSION_MICRO < 6)
1.289 -GstBuffer * gst_adapter_take_buffer (GstAdapter * adapter, guint nbytes);
1.290 -#endif
1.291 -
1.292 -
1.293 -GST_BOILERPLATE (GstNuvDemux, gst_nuv_demux, GstElement, GST_TYPE_ELEMENT);
1.294 -
1.295 -/******************************************************************************
1.296 - * Utils function
1.297 - ******************************************************************************/
1.298 -#if G_BYTE_ORDER == G_BIG_ENDIAN
1.299 -static inline gdouble
1.300 -_gdouble_swap_le_be (gdouble * d)
1.301 -{
1.302 - union
1.303 - {
1.304 - guint64 i;
1.305 - gdouble d;
1.306 - } u;
1.307 -
1.308 - u.d = *d;
1.309 - u.i = GUINT64_SWAP_LE_BE (u.i);
1.310 - return u.d;
1.311 -}
1.312 -
1.313 -#define READ_DOUBLE_FROM_LE(d) (_gdouble_swap_le_be((gdouble* ) d))
1.314 -#else /* G_BYTE_ORDER != G_BIG_ENDIAN */
1.315 -#define READ_DOUBLE_FROM_LE(d) *((gdouble* ) (d))
1.316 -#endif /* G_BYTE_ORDER != G_BIG_ENDIAN */
1.317 -
1.318 -static void
1.319 -double2fraction (double in, int *num, int *denom)
1.320 -{
1.321 - if (in == 29.97) {
1.322 - *num = 30000;
1.323 - *denom = 1001;
1.324 - } else if (in == 23.976) {
1.325 - *num = 24000;
1.326 - *denom = 1001;
1.327 - } else {
1.328 - *denom = 1;
1.329 - while (in - floor(in) >= 0.1) {
1.330 - *denom *= 10;
1.331 - in *= 10.0;
1.332 - }
1.333 - *num = (int)floor(in);
1.334 - }
1.335 -}
1.336 -
1.337 -/* GObject Functions */
1.338 -
1.339 -static void
1.340 -gst_nuv_demux_base_init (gpointer klass)
1.341 -{
1.342 - GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
1.343 -
1.344 - gst_element_class_add_pad_template (element_class,
1.345 - gst_static_pad_template_get (&audio_src_template));
1.346 -
1.347 - gst_element_class_add_pad_template (element_class,
1.348 - gst_static_pad_template_get (&video_src_template));
1.349 -
1.350 - gst_element_class_add_pad_template (element_class,
1.351 - gst_static_pad_template_get (&sink_template));
1.352 - gst_element_class_set_details (element_class, &gst_nuv_demux_details);
1.353 -}
1.354 -
1.355 -static void
1.356 -gst_nuv_demux_class_init (GstNuvDemuxClass * klass)
1.357 -{
1.358 - GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
1.359 - GObjectClass *gobject_class = (GObjectClass *) klass;
1.360 -
1.361 - GST_DEBUG_CATEGORY_INIT (nuvdemux_debug, "nuvdemux",
1.362 - 0, "Demuxer for NUV streams");
1.363 -
1.364 - parent_class = g_type_class_peek_parent (klass);
1.365 -
1.366 - gobject_class->dispose = gst_nuv_demux_dispose;
1.367 - gobject_class->finalize = gst_nuv_demux_finalize;
1.368 - gstelement_class->change_state = gst_nuv_demux_change_state;
1.369 -
1.370 - g_type_class_add_private (gobject_class, sizeof (GstNuvDemuxPrivate));
1.371 -}
1.372 -
1.373 -static void
1.374 -gst_nuv_demux_init (GstNuvDemux * nuv, GstNuvDemuxClass * nuv_class)
1.375 -{
1.376 - nuv->priv = GST_NUV_DEMUX_GET_PRIVATE (nuv);
1.377 - nuv->priv->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink");
1.378 -
1.379 - /* creating adapter */
1.380 - nuv->priv->mode = NUV_PUSH_MODE;
1.381 - nuv->priv->adapter = gst_adapter_new ();
1.382 -
1.383 - nuv->priv->new_audio_segment = TRUE;
1.384 - nuv->priv->new_video_segment = TRUE;
1.385 -
1.386 - gst_pad_set_activate_function (nuv->priv->sinkpad, gst_nuv_demux_sink_activate);
1.387 - gst_pad_set_activatepull_function (nuv->priv->sinkpad,
1.388 - gst_nuv_demux_sink_activate_pull);
1.389 - gst_pad_set_activatepush_function (nuv->priv->sinkpad,
1.390 - gst_nuv_demux_sink_activate_push);
1.391 - gst_pad_set_chain_function (nuv->priv->sinkpad,
1.392 - GST_DEBUG_FUNCPTR (gst_nuv_demux_chain));
1.393 -/*
1.394 - gst_pad_set_event_function (nuv->priv->sinkpad,
1.395 - gst_nuv_demux_sink_event);
1.396 -*/
1.397 -
1.398 - gst_element_add_pad (GST_ELEMENT (nuv), nuv->priv->sinkpad);
1.399 -
1.400 -}
1.401 -
1.402 -static void
1.403 -gst_nuv_demux_dispose (GObject * object)
1.404 -{
1.405 - GstNuvDemux *nuv = GST_NUV_DEMUX (object);
1.406 -
1.407 -
1.408 - if (nuv->priv->mpeg_buffer != NULL) {
1.409 - gst_buffer_unref (nuv->priv->mpeg_buffer);
1.410 - }
1.411 -
1.412 - gst_nuv_demux_reset (GST_NUV_DEMUX (object));
1.413 - gst_nuv_demux_destoy_src_pad (GST_NUV_DEMUX (object));
1.414 -
1.415 - if (nuv->priv->adapter != NULL) {
1.416 - gst_object_unref (nuv->priv->adapter);
1.417 - }
1.418 -}
1.419 -
1.420 -static void
1.421 -gst_nuv_demux_finalize (GObject * object)
1.422 -{
1.423 - G_OBJECT_CLASS (parent_class)->finalize (object);
1.424 -}
1.425 -
1.426 -
1.427 -/* HeaderLoad:
1.428 - */
1.429 -static GstFlowReturn
1.430 -gst_nuv_demux_header_load (GstNuvDemux * nuv, nuv_header *h)
1.431 -{
1.432 - GstBuffer *buffer = NULL;
1.433 - GstFlowReturn res = gst_nuv_demux_read_bytes (nuv, 72, TRUE, &buffer);
1.434 -
1.435 - if ((res != GST_FLOW_OK) || (buffer == NULL)) {
1.436 - goto done;
1.437 - }
1.438 -
1.439 - memcpy (h->id, buffer->data, 12);
1.440 - memcpy (h->version, buffer->data + 12, 5);
1.441 - h->i_width = GST_READ_UINT32_LE (&buffer->data[20]);
1.442 - h->i_height = GST_READ_UINT32_LE (&buffer->data[24]);
1.443 - h->i_width_desired = GST_READ_UINT32_LE (&buffer->data[28]);
1.444 - h->i_height_desired = GST_READ_UINT32_LE (&buffer->data[32]);
1.445 - h->i_mode = GPOINTER_TO_INT (buffer->data[36]);
1.446 - h->d_aspect = READ_DOUBLE_FROM_LE (&buffer->data[40]);
1.447 - h->d_fps = READ_DOUBLE_FROM_LE (&buffer->data[48]);
1.448 - /* get the num and denom values from fps */
1.449 - double2fraction (h->d_fps, &h->i_fpsn, &h->i_fpsd);
1.450 - h->i_video_blocks = GST_READ_UINT32_LE (&buffer->data[56]);
1.451 - h->i_audio_blocks = GST_READ_UINT32_LE (&buffer->data[60]);
1.452 - h->i_text_blocks = GST_READ_UINT32_LE (&buffer->data[64]);
1.453 - h->i_keyframe_distance = GST_READ_UINT32_LE (&buffer->data[68]);
1.454 -
1.455 - GST_DEBUG_OBJECT (nuv,
1.456 - "nuv: h=%s v=%s %dx%d a=%f fps=%f v=%d a=%d t=%d kfd=%d", h->id,
1.457 - h->version, h->i_width, h->i_height, h->d_aspect, h->d_fps,
1.458 - h->i_video_blocks, h->i_audio_blocks, h->i_text_blocks,
1.459 - h->i_keyframe_distance);
1.460 -
1.461 -done:
1.462 - if (buffer != NULL) {
1.463 - gst_buffer_unref (buffer);
1.464 - buffer = NULL;
1.465 - }
1.466 - return res;
1.467 -}
1.468 -
1.469 -static GstFlowReturn
1.470 -gst_nuv_demux_stream_header_data (GstNuvDemux * nuv)
1.471 -{
1.472 - GstFlowReturn res;
1.473 -
1.474 - res = gst_nuv_demux_header_load (nuv, &nuv->priv->h);
1.475 - if (res == GST_FLOW_OK)
1.476 - nuv->priv->state = GST_NUV_DEMUX_EXTRA_DATA;
1.477 - return res;
1.478 -}
1.479 -
1.480 -/*
1.481 - * Read NUV file tag
1.482 - */
1.483 -static GstFlowReturn
1.484 -gst_nuv_demux_stream_file_header (GstNuvDemux * nuv)
1.485 -{
1.486 - GstFlowReturn res = GST_FLOW_OK;
1.487 - GstBuffer *file_header = NULL;
1.488 -
1.489 - res = gst_nuv_demux_read_bytes (nuv, 12, FALSE, &file_header);
1.490 - if (res == GST_FLOW_OK) {
1.491 - if (strncmp ((gchar *) file_header->data, "MythTVVideo", 11) ||
1.492 - strncmp ((gchar *) file_header->data, "NuppelVideo", 11)) {
1.493 - nuv->priv->state = GST_NUV_DEMUX_HEADER_DATA;
1.494 - } else {
1.495 - GST_DEBUG_OBJECT (nuv, "error parsing file header");
1.496 - nuv->priv->state = GST_NUV_DEMUX_INVALID_DATA;
1.497 - res = GST_FLOW_ERROR;
1.498 - }
1.499 - }
1.500 -
1.501 - if (file_header != NULL) {
1.502 - gst_buffer_unref (file_header);
1.503 - file_header = NULL;
1.504 - }
1.505 - return res;
1.506 -}
1.507 -
1.508 -/* FrameHeaderLoad:
1.509 - */
1.510 -static GstFlowReturn
1.511 -gst_nuv_demux_frame_header_load (GstNuvDemux * nuv, nuv_frame_header *h)
1.512 -{
1.513 - unsigned char *data;
1.514 - GstBuffer *buf = NULL;
1.515 -
1.516 - GstFlowReturn res = gst_nuv_demux_read_bytes (nuv, 12, TRUE, &buf);
1.517 -
1.518 - if ((res != GST_FLOW_OK) || (buf == NULL)) {
1.519 - goto done;
1.520 - }
1.521 -
1.522 - data = buf->data;
1.523 -
1.524 - h->i_type = GPOINTER_TO_INT (data[0]);
1.525 - h->i_compression = GPOINTER_TO_INT (data[1]);
1.526 - h->i_keyframe = GPOINTER_TO_INT (data[2]);
1.527 - h->i_filters = GPOINTER_TO_INT (data[3]);
1.528 - h->i_timecode = GST_READ_UINT32_LE (&data[4]);
1.529 - h->i_length = GST_READ_UINT32_LE (&data[8]);
1.530 -
1.531 - GST_DEBUG_OBJECT (nuv, "frame hdr: t=%c c=%c k=%d f=0x%x timecode=%d l=%d",
1.532 - h->i_type,
1.533 - h->i_compression ? h->i_compression : ' ',
1.534 - h->i_keyframe ? h->i_keyframe : ' ',
1.535 - h->i_filters, h->i_timecode, h->i_length);
1.536 -
1.537 -done:
1.538 - if (buf != NULL) {
1.539 - gst_buffer_unref (buf);
1.540 - buf = NULL;
1.541 - }
1.542 -
1.543 - return res;
1.544 -}
1.545 -
1.546 -static GstFlowReturn
1.547 -gst_nuv_demux_extended_header_load (GstNuvDemux * nuv,
1.548 - nuv_extended_header * h)
1.549 -{
1.550 - unsigned char *data;
1.551 - GstBuffer *buff = NULL;
1.552 -
1.553 - GstFlowReturn res = gst_nuv_demux_read_bytes (nuv, 512, TRUE, &buff);
1.554 -
1.555 - if ((res != GST_FLOW_OK) || (buff == NULL)) {
1.556 - goto done;
1.557 - }
1.558 -
1.559 - data = buff->data;
1.560 - h->i_version = GST_READ_UINT32_LE (&data[0]);
1.561 - h->i_video_fcc = GST_MAKE_FOURCC (data[4], data[5], data[6], data[7]);
1.562 - h->i_audio_fcc = GST_MAKE_FOURCC (data[8], data[9], data[10], data[11]);
1.563 - h->i_audio_sample_rate = GST_READ_UINT32_LE (&data[12]);
1.564 - h->i_audio_bits_per_sample = GST_READ_UINT32_LE (&data[16]);
1.565 - h->i_audio_channels = GST_READ_UINT32_LE (&data[20]);
1.566 - h->i_audio_compression_ratio = GST_READ_UINT32_LE (&data[24]);
1.567 - h->i_audio_quality = GST_READ_UINT32_LE (&data[28]);
1.568 - h->i_rtjpeg_quality = GST_READ_UINT32_LE (&data[32]);
1.569 - h->i_rtjpeg_luma_filter = GST_READ_UINT32_LE (&data[36]);
1.570 - h->i_rtjpeg_chroma_filter = GST_READ_UINT32_LE (&data[40]);
1.571 - h->i_lavc_bitrate = GST_READ_UINT32_LE (&data[44]);
1.572 - h->i_lavc_qmin = GST_READ_UINT32_LE (&data[48]);
1.573 - h->i_lavc_qmin = GST_READ_UINT32_LE (&data[52]);
1.574 - h->i_lavc_maxqdiff = GST_READ_UINT32_LE (&data[56]);
1.575 - h->i_seekable_offset = GST_READ_UINT64_LE (&data[60]);
1.576 - h->i_keyframe_adjust_offset = GST_READ_UINT64_LE (&data[68]);
1.577 -
1.578 - GST_DEBUG_OBJECT (nuv,
1.579 - "ex hdr: v=%d vffc=%4.4s afcc=%4.4s %dHz %dbits ach=%d acr=%d aq=%d"
1.580 - "rtjpeg q=%d lf=%d lc=%d lavc br=%d qmin=%d qmax=%d maxqdiff=%d seekableoff=%lld keyfao=%lld",
1.581 - h->i_version, (gchar *) & h->i_video_fcc, (gchar *) & h->i_audio_fcc,
1.582 - h->i_audio_sample_rate, h->i_audio_bits_per_sample, h->i_audio_channels,
1.583 - h->i_audio_compression_ratio, h->i_audio_quality, h->i_rtjpeg_quality,
1.584 - h->i_rtjpeg_luma_filter, h->i_rtjpeg_chroma_filter, h->i_lavc_bitrate,
1.585 - h->i_lavc_qmin, h->i_lavc_qmax, h->i_lavc_maxqdiff, h->i_seekable_offset,
1.586 - h->i_keyframe_adjust_offset);
1.587 -
1.588 -done:
1.589 - if (buff != NULL) {
1.590 - gst_buffer_unref (buff);
1.591 - buff = NULL;
1.592 - }
1.593 - return res;
1.594 -}
1.595 -
1.596 -
1.597 -/* Query Functions */
1.598 -static const GstQueryType *
1.599 -gst_nuv_demux_get_src_query_types (GstPad * pad)
1.600 -{
1.601 - static const GstQueryType src_types[] = {
1.602 - GST_QUERY_POSITION,
1.603 - GST_QUERY_DURATION,
1.604 - 0
1.605 - };
1.606 -
1.607 - return src_types;
1.608 -}
1.609 -
1.610 -static gboolean
1.611 -gst_nuv_demux_handle_src_query (GstPad * pad, GstQuery * query)
1.612 -{
1.613 - gboolean res = FALSE;
1.614 - GstNuvDemux *nuv = GST_NUV_DEMUX (gst_pad_get_parent (pad));
1.615 -
1.616 - switch (GST_QUERY_TYPE (query)) {
1.617 - case GST_QUERY_POSITION:
1.618 - if (GST_CLOCK_TIME_IS_VALID (nuv->priv->last_frame_time)) {
1.619 - gst_query_set_position (query, GST_FORMAT_TIME, nuv->priv->last_frame_time);
1.620 - res = TRUE;
1.621 - }
1.622 - break;
1.623 - case GST_QUERY_DURATION:
1.624 - {
1.625 - if (nuv->priv->duration_time != GST_CLOCK_TIME_NONE) {
1.626 - gst_query_set_duration (query, GST_FORMAT_TIME, nuv->priv->duration_time);
1.627 - res = TRUE;
1.628 - }
1.629 - }
1.630 - break;
1.631 - default:
1.632 - res = FALSE;
1.633 - break;
1.634 - }
1.635 -
1.636 - gst_object_unref (nuv);
1.637 -
1.638 - return res;
1.639 -}
1.640 -
1.641 -static GstPad*
1.642 -gst_nuv_demux_create_pad (GstNuvDemux *nuv, GstCaps *caps, GstStaticPadTemplate *template, const gchar* name)
1.643 -{
1.644 - GstPad *pad = NULL;
1.645 - pad = gst_pad_new_from_static_template (template, name);
1.646 - gst_pad_set_caps (pad, caps);
1.647 - gst_pad_set_active (pad, TRUE);
1.648 - gst_pad_use_fixed_caps (pad);
1.649 - gst_element_add_pad (GST_ELEMENT (nuv), pad);
1.650 -
1.651 - gst_pad_set_event_function (pad,
1.652 - GST_DEBUG_FUNCPTR (gst_nuv_demux_srcpad_event));
1.653 -
1.654 - gst_pad_set_query_type_function (pad,
1.655 - GST_DEBUG_FUNCPTR (gst_nuv_demux_get_src_query_types));
1.656 -
1.657 - gst_pad_set_query_function (pad,
1.658 - GST_DEBUG_FUNCPTR (gst_nuv_demux_handle_src_query));
1.659 -
1.660 -
1.661 - return pad;
1.662 -}
1.663 -
1.664 -static void
1.665 -gst_nuv_demux_create_pads (GstNuvDemux * nuv)
1.666 -{
1.667 - if (nuv->priv->h.i_video_blocks != 0) {
1.668 - GstCaps *video_caps = NULL;
1.669 -
1.670 - video_caps = gst_caps_new_simple ("video/x-divx",
1.671 - "divxversion", G_TYPE_INT, 4,
1.672 - "width", G_TYPE_INT, nuv->priv->h.i_width,
1.673 - "height", G_TYPE_INT, nuv->priv->h.i_height,
1.674 - "framerate", GST_TYPE_FRACTION, nuv->priv->h.i_fpsn, nuv->priv->h.i_fpsd,
1.675 - "format", GST_TYPE_FOURCC, nuv->priv->eh.i_video_fcc,
1.676 - "pixel-aspect-ratio", GST_TYPE_FRACTION,
1.677 - (gint) (nuv->priv->h.d_aspect * 1000.0f), 1000, NULL);
1.678 -
1.679 - nuv->priv->src_video_pad = gst_nuv_demux_create_pad (nuv, video_caps, &video_src_template, "video_src");
1.680 - gst_caps_unref (video_caps);
1.681 - }
1.682 -
1.683 - if (nuv->priv->h.i_audio_blocks != 0) {
1.684 - GstCaps *audio_caps = NULL;
1.685 -
1.686 - audio_caps = gst_caps_new_simple ("audio/mpeg",
1.687 - "rate", G_TYPE_INT, nuv->priv->eh.i_audio_sample_rate,
1.688 - "format", GST_TYPE_FOURCC, nuv->priv->eh.i_audio_fcc,
1.689 - "channels", G_TYPE_INT, nuv->priv->eh.i_audio_channels,
1.690 - "layer", G_TYPE_INT, 3, // fixme: magic number
1.691 - "mpegversion", G_TYPE_INT, nuv->priv->eh.i_version, NULL);
1.692 -
1.693 - nuv->priv->src_audio_pad = gst_nuv_demux_create_pad (nuv, audio_caps, &audio_src_template, "audio_src");
1.694 - gst_caps_unref (audio_caps);
1.695 - }
1.696 -
1.697 - gst_element_no_more_pads (GST_ELEMENT (nuv));
1.698 -}
1.699 -
1.700 -static gboolean
1.701 -gst_nuv_demux_validate_header (nuv_frame_header *h)
1.702 -{
1.703 - gboolean valid = FALSE;
1.704 - //g_usleep (1 * G_USEC_PER_SEC );
1.705 - switch (h->i_type) {
1.706 -/*
1.707 - case 'V':
1.708 - if (h->i_compression == 0 ||
1.709 - h->i_compression == 1 ||
1.710 - h->i_compression == 2 ||
1.711 - h->i_compression == 'N' ||
1.712 - h->i_compression == 'L') {
1.713 - valid = TRUE;
1.714 - }
1.715 - break;
1.716 - case 'A':
1.717 - if (h->i_compression == 0 ||
1.718 - h->i_compression == 1 ||
1.719 - h->i_compression == 2 ||
1.720 - h->i_compression == 3 ||
1.721 - h->i_compression == 'F' ||
1.722 - h->i_compression == 'S' ||
1.723 - h->i_compression == 'N' ||
1.724 - h->i_compression == 'L') {
1.725 - valid = TRUE;
1.726 - }
1.727 - break;
1.728 - case 'S':
1.729 - if (h->i_compression == 'B' ||
1.730 - h->i_compression == 'A' ||
1.731 - h->i_compression == 'V' ||
1.732 - h->i_compression == 'S') {
1.733 - valid = TRUE;
1.734 - }
1.735 - break;
1.736 -*/
1.737 - case 'A':
1.738 - case 'V':
1.739 - case 'S':
1.740 - case 'R':
1.741 - case 'D':
1.742 - case 'Q':
1.743 - valid = TRUE;
1.744 - break;
1.745 - default:
1.746 - valid = FALSE;
1.747 - }
1.748 -
1.749 - return valid;
1.750 -}
1.751 -
1.752 -static GstFlowReturn
1.753 -gst_nuv_demux_read_head_frame (GstNuvDemux * nuv)
1.754 -{
1.755 - GstFlowReturn ret = GST_FLOW_OK;
1.756 - gboolean valid = FALSE;
1.757 -
1.758 - do {
1.759 - ret = gst_nuv_demux_frame_header_load (nuv, &nuv->priv->fh);
1.760 - if (ret != GST_FLOW_OK) {
1.761 - return ret;
1.762 - }
1.763 -
1.764 - if (gst_nuv_demux_validate_header (&nuv->priv->fh) == TRUE)
1.765 - valid = TRUE;
1.766 -
1.767 - } while (valid == FALSE);
1.768 -
1.769 - nuv->priv->state = GST_NUV_DEMUX_MOVI;
1.770 - return ret;
1.771 -}
1.772 -
1.773 -static gboolean
1.774 -gst_nuv_combine_flow (GstNuvDemux *nuv)
1.775 -{
1.776 - GstFlowReturn ret_video = nuv->priv->last_video_return;
1.777 - GstFlowReturn ret_audio = nuv->priv->last_audio_return;
1.778 -
1.779 - if ((ret_video != GST_FLOW_OK) &&
1.780 - (ret_audio != GST_FLOW_OK))
1.781 - return FALSE;
1.782 -
1.783 - if (GST_FLOW_IS_FATAL (ret_video))
1.784 - return FALSE;
1.785 -
1.786 - if (GST_FLOW_IS_FATAL (ret_audio))
1.787 - return FALSE;
1.788 -
1.789 - return TRUE;
1.790 -}
1.791 -
1.792 -static GstFlowReturn
1.793 -gst_nuv_demux_stream_data (GstNuvDemux * nuv)
1.794 -{
1.795 - GstFlowReturn ret = GST_FLOW_OK;
1.796 - GstPad *pad = NULL;
1.797 - guint64 timestamp;
1.798 - GstBuffer *buf = NULL;
1.799 - nuv_frame_header h;
1.800 -
1.801 - h = nuv->priv->fh;
1.802 -
1.803 - if (h.i_type == 'R') {
1.804 - goto done;
1.805 - }
1.806 -
1.807 - if (h.i_length > 0) {
1.808 - ret = gst_nuv_demux_read_bytes (nuv, h.i_length, TRUE, &buf);
1.809 - if ((ret != GST_FLOW_OK) || (buf == NULL)) {
1.810 - goto done;
1.811 - }
1.812 -
1.813 - if ((h.i_timecode < 0)) {
1.814 - h.i_timecode = 0;
1.815 - //goto done;
1.816 - }
1.817 -
1.818 - timestamp = h.i_timecode * GST_MSECOND;
1.819 - GST_BUFFER_TIMESTAMP (buf) = timestamp;
1.820 - }
1.821 - else {
1.822 - goto done;
1.823 - }
1.824 -
1.825 -
1.826 - switch (h.i_type) {
1.827 - case 'V':
1.828 - {
1.829 - pad = nuv->priv->src_video_pad;
1.830 -
1.831 - if (nuv->priv->new_video_segment) {
1.832 -
1.833 - /* send new segment event*/
1.834 - gst_pad_push_event (nuv->priv->src_video_pad,
1.835 - gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME, 0,
1.836 - GST_CLOCK_TIME_NONE, 0));
1.837 -
1.838 - if (nuv->priv->time_start == GST_CLOCK_TIME_NONE) {
1.839 - nuv->priv->time_start = timestamp;
1.840 - }
1.841 - nuv->priv->new_video_segment = FALSE;
1.842 - }
1.843 -
1.844 - break;
1.845 - }
1.846 - case 'A':
1.847 - {
1.848 - pad = nuv->priv->src_audio_pad;
1.849 -
1.850 - if (nuv->priv->new_audio_segment) {
1.851 - /* send new segment event*/
1.852 - gst_pad_push_event (nuv->priv->src_audio_pad,
1.853 - gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME, 0,
1.854 - GST_CLOCK_TIME_NONE, 0));
1.855 -
1.856 - if (nuv->priv->time_start == GST_CLOCK_TIME_NONE) {
1.857 - nuv->priv->time_start = timestamp;
1.858 - }
1.859 - nuv->priv->new_audio_segment = FALSE;
1.860 - }
1.861 -
1.862 - break;
1.863 - }
1.864 - case 'S':
1.865 - {
1.866 - switch (h.i_compression) {
1.867 - case 'V':
1.868 - GST_DEBUG_OBJECT (nuv, "sending new video segment: %d", h.i_timecode);
1.869 - gst_pad_push_event (nuv->priv->src_video_pad,
1.870 - gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME, h.i_timecode * GST_MSECOND,
1.871 - GST_CLOCK_TIME_NONE, 0));
1.872 - break;
1.873 - case 'A':
1.874 - GST_DEBUG_OBJECT (nuv, "sending new audio segment: %d", h.i_timecode);
1.875 - gst_pad_push_event (nuv->priv->src_audio_pad,
1.876 - gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME, 0,
1.877 - GST_CLOCK_TIME_NONE, 0));
1.878 - break;
1.879 - default:
1.880 - break;
1.881 - }
1.882 - goto done;
1.883 - }
1.884 - default:
1.885 - break;
1.886 - }
1.887 -
1.888 - if ((buf != NULL) && (pad != NULL)) {
1.889 - /* pushing the buffer */
1.890 - gst_buffer_set_caps (buf, GST_PAD_CAPS (pad));
1.891 - ret = gst_pad_push (pad, buf);
1.892 - buf = NULL;
1.893 -
1.894 - if (ret != GST_FLOW_OK) {
1.895 - GST_WARNING_OBJECT (nuv, "error: %d pushing on srcpad %s", ret, gst_pad_get_name (pad));
1.896 -
1.897 - if (pad == nuv->priv->src_video_pad) {
1.898 - nuv->priv->last_video_return = ret;
1.899 - }
1.900 - else if (pad == nuv->priv->src_audio_pad) {
1.901 - nuv->priv->last_audio_return = ret;
1.902 - }
1.903 -
1.904 - /* verify anothers flow if is necessary stop task */
1.905 - if (gst_nuv_combine_flow (nuv) != FALSE) {
1.906 - ret = GST_FLOW_OK;
1.907 - } else {
1.908 - GST_WARNING_OBJECT (nuv, "error: on push");
1.909 - }
1.910 -
1.911 - }
1.912 - }
1.913 -
1.914 -done:
1.915 - if (buf != NULL) {
1.916 - gst_buffer_unref (buf);
1.917 - buf = NULL;
1.918 - }
1.919 - if (ret == GST_FLOW_OK) {
1.920 - nuv->priv->state = GST_NUV_DEMUX_FRAME_HEADER;
1.921 - memset (&nuv->priv->fh, 0, sizeof (nuv->priv->fh));
1.922 - }
1.923 - return ret;
1.924 -}
1.925 -
1.926 -static GstFlowReturn
1.927 -gst_nuv_demux_stream_mpeg_data (GstNuvDemux * nuv)
1.928 -{
1.929 - GstFlowReturn ret = GST_FLOW_OK;
1.930 -
1.931 - /* ffmpeg extra data */
1.932 - ret = gst_nuv_demux_read_bytes (nuv, nuv->priv->mpeg_data_size, TRUE,
1.933 - &nuv->priv->mpeg_buffer);
1.934 - if ((ret != GST_FLOW_OK) || (nuv->priv->mpeg_buffer == NULL)) {
1.935 - return ret;
1.936 - }
1.937 -
1.938 - GST_BUFFER_SIZE (nuv->priv->mpeg_buffer) = nuv->priv->mpeg_data_size;
1.939 - nuv->priv->state = GST_NUV_DEMUX_EXTEND_HEADER;
1.940 - return ret;
1.941 -}
1.942 -
1.943 -static GstFlowReturn
1.944 -gst_nuv_demux_stream_extra_data (GstNuvDemux * nuv)
1.945 -{
1.946 - GstFlowReturn ret = GST_FLOW_OK;
1.947 -
1.948 - /* Load 'D' */
1.949 - nuv_frame_header h;
1.950 -
1.951 - ret = gst_nuv_demux_frame_header_load (nuv, &h);
1.952 - if (ret != GST_FLOW_OK)
1.953 - return ret;
1.954 -
1.955 - if (h.i_type != 'D') {
1.956 - GST_WARNING_OBJECT (nuv, "Unsuported rtjpeg");
1.957 - return GST_FLOW_NOT_SUPPORTED;
1.958 - }
1.959 -
1.960 - if (h.i_length > 0) {
1.961 - if (h.i_compression == 'F') {
1.962 - nuv->priv->state = GST_NUV_DEMUX_MPEG_DATA;
1.963 - } else {
1.964 - GST_WARNING_OBJECT (nuv, "only file with extended chunk are supported");
1.965 - return GST_FLOW_NOT_SUPPORTED;
1.966 - }
1.967 - } else {
1.968 - nuv->priv->state = GST_NUV_DEMUX_EXTEND_HEADER;
1.969 - }
1.970 -
1.971 - return ret;
1.972 -}
1.973 -
1.974 -static GstFlowReturn
1.975 -gst_nuv_demux_stream_extend_header_data (GstNuvDemux * nuv)
1.976 -{
1.977 - GstFlowReturn ret = GST_FLOW_OK;
1.978 -
1.979 - ret = gst_nuv_demux_extended_header_load (nuv, &nuv->priv->eh);
1.980 - if (ret != GST_FLOW_OK)
1.981 - return ret;
1.982 -
1.983 - gst_nuv_demux_create_pads (nuv);
1.984 - nuv->priv->state = GST_NUV_DEMUX_INDEX_CREATE;
1.985 - return ret;
1.986 -}
1.987 -
1.988 -static GstFlowReturn
1.989 -gst_nuv_demux_stream_extend_header (GstNuvDemux * nuv)
1.990 -{
1.991 - GstBuffer *buf = NULL;
1.992 - GstFlowReturn res = GST_FLOW_OK;
1.993 -
1.994 - res = gst_nuv_demux_read_bytes (nuv, 1, FALSE, &buf);
1.995 - if ((res != GST_FLOW_OK) || (buf == NULL)) {
1.996 - if (buf != NULL) {
1.997 - gst_buffer_unref (buf);
1.998 - }
1.999 - return res;
1.1000 - }
1.1001 -
1.1002 - if (buf->data[0] == 'X') {
1.1003 - gst_buffer_unref (buf);
1.1004 - buf = NULL;
1.1005 - nuv_frame_header h;
1.1006 -
1.1007 - res = gst_nuv_demux_frame_header_load (nuv, &h);
1.1008 - if (res != GST_FLOW_OK)
1.1009 - return res;
1.1010 -
1.1011 - if (h.i_length != 512) {
1.1012 - return GST_FLOW_ERROR;
1.1013 - }
1.1014 - nuv->priv->state = GST_NUV_DEMUX_EXTEND_HEADER_DATA;
1.1015 - } else {
1.1016 - nuv->priv->state = GST_NUV_DEMUX_INVALID_DATA;
1.1017 - g_object_unref (buf);
1.1018 - GST_ELEMENT_WARNING (nuv, STREAM, FAILED,
1.1019 - (_("incomplete NUV support")), ("incomplete NUV support"));
1.1020 - return GST_FLOW_ERROR;
1.1021 - }
1.1022 - return res;
1.1023 -}
1.1024 -
1.1025 -static void
1.1026 -gst_nuv_demux_create_seek_index (GstNuvDemux * nuv)
1.1027 -{
1.1028 - GstMessage *msg;
1.1029 - nuv_frame_header h;
1.1030 -
1.1031 - while (gst_nuv_demux_frame_header_load (nuv, &h) == GST_FLOW_OK) {
1.1032 - if ((h.i_type == 'V') && (h.i_keyframe == 0)) {
1.1033 - frame_index_data *f = g_new0 (frame_index_data, 1);
1.1034 -
1.1035 - f->offset = nuv->priv->offset - 12;
1.1036 - f->timecode = h.i_timecode * GST_MSECOND;
1.1037 -
1.1038 - nuv->priv->index = g_slist_append (nuv->priv->index, f);
1.1039 - }
1.1040 - if (h.i_type != 'R') {
1.1041 - nuv->priv->offset += h.i_length;
1.1042 - if (h.i_type == 'A' || h.i_type == 'V')
1.1043 - nuv->priv->duration_time = h.i_timecode * GST_MSECOND;
1.1044 - }
1.1045 - }
1.1046 - GST_DEBUG_OBJECT (nuv, "CREATING INDEX: DONE : DURATION Bytes/Sec: %" G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT,
1.1047 - nuv->priv->offset, nuv->priv->duration_time);
1.1048 -
1.1049 - nuv->priv->duration_bytes = nuv->priv->offset;
1.1050 - nuv->priv->offset = nuv->priv->header_lengh;
1.1051 -
1.1052 - msg = gst_message_new_duration (GST_OBJECT (nuv), GST_FORMAT_TIME, nuv->priv->duration_time);
1.1053 - gst_element_post_message (GST_ELEMENT (nuv), msg);
1.1054 -}
1.1055 -
1.1056 -static GstFlowReturn
1.1057 -gst_nuv_demux_play (GstPad * pad)
1.1058 -{
1.1059 - GstFlowReturn res = GST_FLOW_OK;
1.1060 - GstNuvDemux *nuv = GST_NUV_DEMUX (GST_PAD_PARENT (pad));
1.1061 -
1.1062 - switch (nuv->priv->state) {
1.1063 - case GST_NUV_DEMUX_START:
1.1064 - res = gst_nuv_demux_stream_file_header (nuv);
1.1065 - if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) {
1.1066 - goto pause;
1.1067 - }
1.1068 - break;
1.1069 -
1.1070 - case GST_NUV_DEMUX_HEADER_DATA:
1.1071 - res = gst_nuv_demux_stream_header_data (nuv);
1.1072 - if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) {
1.1073 - goto pause;
1.1074 - }
1.1075 - break;
1.1076 -
1.1077 - case GST_NUV_DEMUX_EXTRA_DATA:
1.1078 - res = gst_nuv_demux_stream_extra_data (nuv);
1.1079 - if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) {
1.1080 - goto pause;
1.1081 - }
1.1082 - break;
1.1083 -
1.1084 - case GST_NUV_DEMUX_MPEG_DATA:
1.1085 - res = gst_nuv_demux_stream_mpeg_data (nuv);
1.1086 - if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) {
1.1087 - goto pause;
1.1088 - }
1.1089 - break;
1.1090 -
1.1091 - case GST_NUV_DEMUX_EXTEND_HEADER:
1.1092 - res = gst_nuv_demux_stream_extend_header (nuv);
1.1093 - if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) {
1.1094 - goto pause;
1.1095 - }
1.1096 - break;
1.1097 -
1.1098 - case GST_NUV_DEMUX_EXTEND_HEADER_DATA:
1.1099 - res = gst_nuv_demux_stream_extend_header_data (nuv);
1.1100 - if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) {
1.1101 - goto pause;
1.1102 - }
1.1103 - //store file header size
1.1104 - nuv->priv->header_lengh = nuv->priv->offset;
1.1105 - break;
1.1106 -
1.1107 - case GST_NUV_DEMUX_INDEX_CREATE:
1.1108 - if (nuv->priv->mode == NUV_PULL_MODE) {
1.1109 - gst_nuv_demux_create_seek_index (nuv);
1.1110 - }
1.1111 -
1.1112 - case GST_NUV_DEMUX_FRAME_HEADER:
1.1113 - res = gst_nuv_demux_read_head_frame (nuv);
1.1114 - if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) {
1.1115 - goto pause;
1.1116 - }
1.1117 - break;
1.1118 -
1.1119 - case GST_NUV_DEMUX_MOVI:
1.1120 - res = gst_nuv_demux_stream_data (nuv);
1.1121 - if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) {
1.1122 - goto pause;
1.1123 - }
1.1124 - break;
1.1125 -
1.1126 - case GST_NUV_DEMUX_INVALID_DATA:
1.1127 - goto pause;
1.1128 - break;
1.1129 - default:
1.1130 - g_assert_not_reached ();
1.1131 - }
1.1132 -
1.1133 - return GST_FLOW_OK;
1.1134 -
1.1135 -pause:
1.1136 - GST_LOG_OBJECT (nuv, "pausing task, reason %s", gst_flow_get_name (res));
1.1137 - gst_pad_pause_task (nuv->priv->sinkpad);
1.1138 -
1.1139 - if (res == GST_FLOW_ERROR_EOS) {
1.1140 - gst_nuv_demux_send_eos (nuv);
1.1141 - nuv->priv->eos = TRUE;
1.1142 - res = GST_FLOW_OK;
1.1143 - }
1.1144 -
1.1145 - if (GST_FLOW_IS_FATAL (res)) {
1.1146 - GST_ELEMENT_ERROR (nuv, STREAM, FAILED,
1.1147 - (_("Internal data stream error.")),
1.1148 - ("streaming stopped, reason %s", gst_flow_get_name (res)));
1.1149 -
1.1150 - gst_nuv_demux_send_eos (nuv);
1.1151 - }
1.1152 - return res;
1.1153 -}
1.1154 -
1.1155 -static void
1.1156 -gst_nuv_demux_send_eos (GstNuvDemux * nuv)
1.1157 -{
1.1158 - gst_element_post_message (GST_ELEMENT (nuv),
1.1159 - gst_message_new_segment_done (GST_OBJECT (nuv), GST_FORMAT_TIME, -1));
1.1160 -
1.1161 - if (nuv->priv->src_video_pad)
1.1162 - gst_pad_push_event (nuv->priv->src_video_pad, gst_event_new_eos ());
1.1163 - if (nuv->priv->src_audio_pad)
1.1164 - gst_pad_push_event (nuv->priv->src_audio_pad, gst_event_new_eos ());
1.1165 -}
1.1166 -
1.1167 -static GstFlowReturn
1.1168 -gst_nuv_demux_read_bytes (GstNuvDemux * nuv, guint64 size, gboolean move,
1.1169 - GstBuffer ** buffer)
1.1170 -{
1.1171 - GstFlowReturn ret = GST_FLOW_OK;
1.1172 -
1.1173 - if (size == 0) {
1.1174 - return ret;
1.1175 - }
1.1176 -
1.1177 -
1.1178 - if (nuv->priv->mode == NUV_PULL_MODE) {
1.1179 - ret = gst_pad_pull_range (nuv->priv->sinkpad, nuv->priv->offset, size, buffer);
1.1180 - if (ret == GST_FLOW_OK) {
1.1181 - if (move) {
1.1182 - nuv->priv->offset += size;
1.1183 - }
1.1184 - /* got eos */
1.1185 - } else if (ret == GST_FLOW_UNEXPECTED) {
1.1186 - return GST_FLOW_ERROR_EOS;
1.1187 - }
1.1188 - } else {
1.1189 - if (gst_adapter_available (nuv->priv->adapter) < size) {
1.1190 - nuv->priv->more_data = TRUE;
1.1191 - return GST_FLOW_ERROR_NO_DATA;
1.1192 - }
1.1193 - if (move) {
1.1194 - *buffer = gst_adapter_take_buffer (nuv->priv->adapter, size);
1.1195 - } else {
1.1196 - guint8 *data = NULL;
1.1197 - data = (guint8 *) gst_adapter_peek (nuv->priv->adapter, size);
1.1198 - *buffer = gst_buffer_new ();
1.1199 - gst_buffer_set_data (*buffer, data, size);
1.1200 - }
1.1201 - }
1.1202 - return ret;
1.1203 -}
1.1204 -
1.1205 -static gboolean
1.1206 -gst_nuv_demux_sink_activate (GstPad * sinkpad)
1.1207 -{
1.1208 - gboolean res = TRUE;
1.1209 - GstNuvDemux *nuv = GST_NUV_DEMUX (gst_pad_get_parent (sinkpad));
1.1210 -
1.1211 - if (gst_pad_check_pull_range (sinkpad)) {
1.1212 - gst_adapter_clear (nuv->priv->adapter);
1.1213 - res = gst_pad_activate_pull (sinkpad, TRUE);
1.1214 - } else {
1.1215 - gst_adapter_clear (nuv->priv->adapter);
1.1216 - res = gst_pad_activate_push (sinkpad, TRUE);
1.1217 - }
1.1218 -
1.1219 - g_object_unref (nuv);
1.1220 - return res;
1.1221 -}
1.1222 -
1.1223 -static gboolean
1.1224 -gst_nuv_demux_sink_activate_pull (GstPad * sinkpad, gboolean active)
1.1225 -{
1.1226 - GstNuvDemux *nuv = GST_NUV_DEMUX (gst_pad_get_parent (sinkpad));
1.1227 -
1.1228 - if (active) {
1.1229 - GST_DEBUG_OBJECT (nuv, "activating pull function");
1.1230 - nuv->priv->mode = NUV_PULL_MODE;
1.1231 - gst_adapter_clear (nuv->priv->adapter);
1.1232 -
1.1233 - gst_pad_start_task (sinkpad, (GstTaskFunction) gst_nuv_demux_loop, sinkpad);
1.1234 - } else {
1.1235 - GST_DEBUG_OBJECT (nuv, "deactivating pull function");
1.1236 - gst_pad_stop_task (sinkpad);
1.1237 - }
1.1238 - gst_object_unref (nuv);
1.1239 -
1.1240 - return TRUE;
1.1241 -}
1.1242 -
1.1243 -static gboolean
1.1244 -gst_nuv_demux_sink_activate_push (GstPad * pad, gboolean active)
1.1245 -{
1.1246 - GstNuvDemux *nuv = GST_NUV_DEMUX (gst_pad_get_parent (pad));
1.1247 -
1.1248 - if (active) {
1.1249 - nuv->priv->mode = NUV_PUSH_MODE;
1.1250 - gst_adapter_clear (nuv->priv->adapter);
1.1251 -
1.1252 - GST_DEBUG_OBJECT (nuv, "activating push/chain function");
1.1253 - } else {
1.1254 - GST_DEBUG_OBJECT (nuv, "deactivating push/chain function");
1.1255 - }
1.1256 -
1.1257 - gst_object_unref (nuv);
1.1258 -
1.1259 - return TRUE;
1.1260 -}
1.1261 -
1.1262 -static frame_index_data *
1.1263 -gst_nuv_demux_do_seek_index (GstNuvDemux *nuv, gint64 seek_pos,
1.1264 - gint64 segment_stop, GstFormat format)
1.1265 -{
1.1266 - GSList *l;
1.1267 - frame_index_data *ret = NULL;
1.1268 -
1.1269 - if (nuv->priv->index == NULL) {
1.1270 - return NULL;
1.1271 - }
1.1272 -
1.1273 - /* find keyframe closest to the requested position */
1.1274 - for (l = nuv->priv->index; l != NULL; l = l->next) {
1.1275 - frame_index_data *f = (frame_index_data *) l->data;
1.1276 - gint64 pos = 0;
1.1277 -
1.1278 - if (format == GST_FORMAT_BYTES) {
1.1279 - pos = f->offset;
1.1280 - } else if (format == GST_FORMAT_TIME) {
1.1281 - pos = f->timecode;
1.1282 - } else {
1.1283 - return NULL;
1.1284 - }
1.1285 -
1.1286 - if (pos >= seek_pos) {
1.1287 - ret = f;
1.1288 - break;
1.1289 - }
1.1290 -
1.1291 - if ((segment_stop != -1) && (segment_stop != GST_CLOCK_TIME_NONE) && (pos > segment_stop)) {
1.1292 - break;
1.1293 - }
1.1294 - }
1.1295 -
1.1296 - return ret;
1.1297 -}
1.1298 -
1.1299 -static gboolean
1.1300 -gst_nuv_demux_do_seek (GstNuvDemux *nuv, GstEvent * event)
1.1301 -{
1.1302 - gdouble rate;
1.1303 - GstFormat format;
1.1304 - GstSeekFlags flags;
1.1305 - GstSeekType cur_type;
1.1306 - gint64 cur;
1.1307 - GstSeekType stop_type;
1.1308 - gint64 stop;
1.1309 - gboolean flush;
1.1310 - frame_index_data *entry;
1.1311 - gint64 segment_start;
1.1312 - gint64 segment_stop;
1.1313 - GstEvent *newsegment_event;
1.1314 -
1.1315 - if (nuv->priv->eos) {
1.1316 - return FALSE;
1.1317 - }
1.1318 -
1.1319 - if (nuv->priv->mode == NUV_PUSH_MODE) {
1.1320 - return FALSE;
1.1321 - }
1.1322 -
1.1323 -
1.1324 - gst_event_parse_seek (event, &rate, &format, &flags,
1.1325 - &cur_type, &cur, &stop_type, &stop);
1.1326 -
1.1327 -
1.1328 -
1.1329 -/*
1.1330 - if (format == GST_FORMAT_TIME) {
1.1331 - GST_DEBUG_OBJECT (nuv, "Can only seek on BYTES");
1.1332 - return FALSE;
1.1333 - }
1.1334 -*/
1.1335 -
1.1336 - if (rate <= 0.0) {
1.1337 - GST_DEBUG_OBJECT (nuv, "Can only seek with positive rate");
1.1338 - return FALSE;
1.1339 - }
1.1340 -
1.1341 - if (cur_type == GST_SEEK_TYPE_SET) {
1.1342 - GST_OBJECT_LOCK (nuv);
1.1343 - if (gst_nuv_demux_do_seek_index (nuv, cur, -1, format) == NULL) {
1.1344 - GST_DEBUG_OBJECT (nuv, "No matching seek entry in index");
1.1345 - GST_OBJECT_UNLOCK (nuv);
1.1346 - return FALSE;
1.1347 - }
1.1348 - GST_OBJECT_UNLOCK (nuv);
1.1349 - }
1.1350 -
1.1351 - flush = !!(flags & GST_SEEK_FLAG_FLUSH);
1.1352 -
1.1353 - if (flush) {
1.1354 - gst_pad_push_event (nuv->priv->sinkpad, gst_event_new_flush_start ());
1.1355 - if (nuv->priv->src_video_pad != NULL) {
1.1356 - gst_pad_push_event (nuv->priv->src_video_pad, gst_event_new_flush_start ());
1.1357 - }
1.1358 -
1.1359 - if (nuv->priv->src_audio_pad != NULL) {
1.1360 - gst_pad_push_event (nuv->priv->src_audio_pad, gst_event_new_flush_start ());
1.1361 - }
1.1362 - }
1.1363 - else {
1.1364 - gst_pad_pause_task (nuv->priv->sinkpad);
1.1365 - }
1.1366 -
1.1367 - GST_PAD_STREAM_LOCK (nuv->priv->sinkpad);
1.1368 - GST_OBJECT_LOCK (nuv);
1.1369 -
1.1370 -
1.1371 - if (cur == GST_CLOCK_TIME_NONE)
1.1372 - cur = 0;
1.1373 - if (stop == GST_CLOCK_TIME_NONE)
1.1374 - stop = nuv->priv->duration_time;
1.1375 -
1.1376 - if (cur_type == GST_SEEK_TYPE_SET)
1.1377 - segment_start = cur;
1.1378 - else if (cur_type == GST_SEEK_TYPE_CUR)
1.1379 - segment_start = nuv->priv->segment_start + cur;
1.1380 - else
1.1381 - segment_start = nuv->priv->segment_start;
1.1382 -
1.1383 - if (stop_type == GST_SEEK_TYPE_SET)
1.1384 - segment_stop = stop;
1.1385 - else if (stop_type == GST_SEEK_TYPE_CUR)
1.1386 - segment_stop = nuv->priv->segment_stop + stop;
1.1387 - else
1.1388 - segment_stop = nuv->priv->segment_stop;
1.1389 -
1.1390 - segment_start = CLAMP (segment_start, 0, nuv->priv->duration_time);
1.1391 - segment_stop = CLAMP (segment_stop, 0, nuv->priv->duration_time);
1.1392 -
1.1393 - entry = gst_nuv_demux_do_seek_index (nuv, segment_start,
1.1394 - segment_stop, format);
1.1395 -
1.1396 - if (entry == NULL) {
1.1397 - GST_DEBUG_OBJECT (nuv, "No matching seek entry in index");
1.1398 - goto seek_error;
1.1399 - }
1.1400 -
1.1401 - segment_start = entry->timecode;
1.1402 -
1.1403 - nuv->priv->segment_start = segment_start;
1.1404 - nuv->priv->segment_stop = segment_stop;
1.1405 -
1.1406 - GST_OBJECT_UNLOCK (nuv);
1.1407 -
1.1408 - if (!nuv->priv->eos) {
1.1409 - GstMessage *msg;
1.1410 - msg = gst_message_new_segment_start (GST_OBJECT (nuv), GST_FORMAT_TIME,
1.1411 - nuv->priv->segment_start);
1.1412 -
1.1413 - gst_element_post_message (GST_ELEMENT (nuv), msg);
1.1414 - }
1.1415 -
1.1416 - GST_DEBUG_OBJECT (nuv, "NEW SEGMENT START %" G_GUINT64_FORMAT ", STOP %" G_GUINT64_FORMAT,
1.1417 - segment_start, segment_stop);
1.1418 - newsegment_event = gst_event_new_new_segment (FALSE, rate,
1.1419 - GST_FORMAT_TIME, segment_start, segment_stop, segment_start);
1.1420 -
1.1421 -
1.1422 - if (flush) {
1.1423 - if (nuv->priv->src_video_pad != NULL) {
1.1424 - gst_pad_push_event (nuv->priv->src_video_pad, gst_event_new_flush_stop ());
1.1425 - }
1.1426 -
1.1427 - if (nuv->priv->src_audio_pad != NULL) {
1.1428 - gst_pad_push_event (nuv->priv->src_audio_pad, gst_event_new_flush_stop ());
1.1429 - }
1.1430 -
1.1431 - gst_pad_push_event (nuv->priv->sinkpad, gst_event_new_flush_stop ());
1.1432 - }
1.1433 -
1.1434 -
1.1435 - if (nuv->priv->src_video_pad != NULL) {
1.1436 - gst_pad_push_event (nuv->priv->src_video_pad, gst_event_ref (newsegment_event));
1.1437 - }
1.1438 - if (nuv->priv->src_audio_pad != NULL) {
1.1439 - gst_pad_push_event (nuv->priv->src_audio_pad, gst_event_ref (newsegment_event));
1.1440 - }
1.1441 -
1.1442 - gst_event_unref (newsegment_event);
1.1443 -
1.1444 - nuv->priv->state = GST_NUV_DEMUX_FRAME_HEADER;
1.1445 - nuv->priv->offset = entry->offset;
1.1446 -
1.1447 - gst_pad_start_task (nuv->priv->sinkpad, (GstTaskFunction) gst_nuv_demux_loop,
1.1448 - nuv->priv->sinkpad);
1.1449 -
1.1450 - GST_PAD_STREAM_UNLOCK (nuv->priv->sinkpad);
1.1451 - return TRUE;
1.1452 -
1.1453 -seek_error:
1.1454 - GST_DEBUG_OBJECT (nuv, "Got a seek error");
1.1455 - GST_OBJECT_UNLOCK (nuv);
1.1456 - GST_PAD_STREAM_UNLOCK (nuv->priv->sinkpad);
1.1457 - return FALSE;
1.1458 -
1.1459 -}
1.1460 -
1.1461 -static gboolean
1.1462 -gst_nuv_demux_srcpad_event (GstPad * pad, GstEvent * event)
1.1463 -{
1.1464 - gboolean res = FALSE;
1.1465 - GstNuvDemux *nuv;
1.1466 -
1.1467 - nuv = GST_NUV_DEMUX (gst_pad_get_parent (pad));
1.1468 -
1.1469 - switch (GST_EVENT_TYPE (event)) {
1.1470 - case GST_EVENT_SEEK:
1.1471 - res = gst_nuv_demux_do_seek (nuv, event);
1.1472 - break;
1.1473 - default:
1.1474 - res = FALSE;
1.1475 - break;
1.1476 - }
1.1477 -
1.1478 - gst_object_unref (nuv);
1.1479 - return res;
1.1480 -}
1.1481 -
1.1482 -static GstFlowReturn
1.1483 -gst_nuv_demux_chain (GstPad * pad, GstBuffer * buf)
1.1484 -{
1.1485 - GstFlowReturn ret = GST_FLOW_OK;
1.1486 - GstNuvDemux *nuv = GST_NUV_DEMUX (gst_pad_get_parent (pad));
1.1487 -
1.1488 - if (nuv->priv->mode != NUV_PUSH_MODE)
1.1489 - return ret;
1.1490 -
1.1491 - gst_adapter_push (nuv->priv->adapter, buf);
1.1492 -
1.1493 - while ((ret == GST_FLOW_OK) && (nuv->priv->more_data == FALSE)) {
1.1494 - ret = gst_nuv_demux_play (pad);
1.1495 - }
1.1496 -
1.1497 - nuv->priv->more_data = FALSE;
1.1498 - gst_object_unref (nuv);
1.1499 -
1.1500 - return ret;
1.1501 -}
1.1502 -
1.1503 -static void
1.1504 -gst_nuv_demux_loop (GstPad * pad)
1.1505 -{
1.1506 - gst_nuv_demux_play (pad);
1.1507 -}
1.1508 -
1.1509 -static void
1.1510 -gst_nuv_demux_index_free (gpointer data, gpointer user_data)
1.1511 -{
1.1512 - g_free (data);
1.1513 -}
1.1514 -
1.1515 -static void
1.1516 -gst_nuv_demux_reset (GstNuvDemux * nuv)
1.1517 -{
1.1518 - nuv->priv->eos = FALSE;
1.1519 - nuv->priv->more_data = FALSE;
1.1520 - nuv->priv->state = GST_NUV_DEMUX_START;
1.1521 - nuv->priv->mode = NUV_PUSH_MODE;
1.1522 - nuv->priv->offset = 0;
1.1523 - nuv->priv->time_start = 0;
1.1524 - nuv->priv->time_qos = GST_CLOCK_TIME_NONE;
1.1525 - nuv->priv->duration_bytes = GST_CLOCK_TIME_NONE;
1.1526 - nuv->priv->duration_time = GST_CLOCK_TIME_NONE;
1.1527 - nuv->priv->last_video_return = GST_FLOW_OK;
1.1528 - nuv->priv->last_audio_return = GST_FLOW_OK;
1.1529 - nuv->priv->header_lengh = 0;
1.1530 - nuv->priv->segment_stop = GST_CLOCK_TIME_NONE;
1.1531 - nuv->priv->segment_start = GST_CLOCK_TIME_NONE;
1.1532 -
1.1533 - //clear index list
1.1534 - g_slist_foreach (nuv->priv->index, gst_nuv_demux_index_free, NULL);
1.1535 - g_slist_free (nuv->priv->index);
1.1536 - nuv->priv->index = NULL;
1.1537 -
1.1538 - gst_adapter_clear (nuv->priv->adapter);
1.1539 -
1.1540 - if (nuv->priv->mpeg_buffer != NULL) {
1.1541 - gst_buffer_unref (nuv->priv->mpeg_buffer);
1.1542 - nuv->priv->mpeg_buffer = NULL;
1.1543 - }
1.1544 -}
1.1545 -
1.1546 -static void
1.1547 -gst_nuv_demux_destoy_src_pad (GstNuvDemux * nuv)
1.1548 -{
1.1549 - if (nuv->priv->src_video_pad) {
1.1550 - gst_element_remove_pad (GST_ELEMENT (nuv), nuv->priv->src_video_pad);
1.1551 - nuv->priv->src_video_pad = NULL;
1.1552 - }
1.1553 -
1.1554 - if (nuv->priv->src_audio_pad) {
1.1555 - gst_element_remove_pad (GST_ELEMENT (nuv), nuv->priv->src_audio_pad);
1.1556 - nuv->priv->src_audio_pad = NULL;
1.1557 - }
1.1558 -}
1.1559 -
1.1560 -static GstStateChangeReturn
1.1561 -gst_nuv_demux_change_state (GstElement * element, GstStateChange transition)
1.1562 -{
1.1563 - GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
1.1564 -
1.1565 - switch (transition) {
1.1566 - case GST_STATE_CHANGE_NULL_TO_READY:
1.1567 - gst_nuv_demux_reset (GST_NUV_DEMUX (element));
1.1568 - gst_nuv_demux_destoy_src_pad (GST_NUV_DEMUX (element));
1.1569 - break;
1.1570 - default:
1.1571 - break;
1.1572 - }
1.1573 -
1.1574 - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1.1575 - if (ret == GST_STATE_CHANGE_FAILURE) {
1.1576 - goto done;
1.1577 - }
1.1578 -
1.1579 - switch (transition) {
1.1580 - case GST_STATE_CHANGE_READY_TO_NULL:
1.1581 - gst_nuv_demux_reset (GST_NUV_DEMUX (element));
1.1582 - gst_nuv_demux_destoy_src_pad (GST_NUV_DEMUX (element));
1.1583 - break;
1.1584 - default:
1.1585 - break;
1.1586 - }
1.1587 -
1.1588 -done:
1.1589 - return ret;
1.1590 -}
1.1591 -
1.1592 -#if (GST_VERSION_MINOR == 10) && (GST_VERSION_MICRO < 6)
1.1593 -GstBuffer *
1.1594 -gst_adapter_take_buffer (GstAdapter * adapter, guint nbytes)
1.1595 -{
1.1596 - GstBuffer *buffer;
1.1597 - GstBuffer *cur;
1.1598 - guint8 *data;
1.1599 -
1.1600 - g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL);
1.1601 - g_return_val_if_fail (nbytes > 0, NULL);
1.1602 -
1.1603 - GST_LOG_OBJECT (adapter, "taking buffer of %u bytes", nbytes);
1.1604 -
1.1605 - /* we don't have enough data, return NULL. This is unlikely
1.1606 - * as one usually does an _available() first instead of peeking a
1.1607 - * random size. */
1.1608 - if (G_UNLIKELY (nbytes > adapter->size))
1.1609 - return NULL;
1.1610 -
1.1611 - /* our head buffer has enough data left, return it */
1.1612 - cur = adapter->buflist->data;
1.1613 - if (GST_BUFFER_SIZE (cur) >= nbytes + adapter->skip) {
1.1614 - GST_LOG_OBJECT (adapter, "providing buffer of %d bytes via sub-buffer",
1.1615 - nbytes);
1.1616 - buffer = gst_buffer_create_sub (cur, adapter->skip, nbytes);
1.1617 -
1.1618 - gst_adapter_flush (adapter, nbytes);
1.1619 -
1.1620 - return buffer;
1.1621 - }
1.1622 -
1.1623 - data = gst_adapter_take (adapter, nbytes);
1.1624 - if (data == NULL)
1.1625 - return NULL;
1.1626 -
1.1627 - buffer = gst_buffer_new ();
1.1628 - GST_BUFFER_DATA (buffer) = data;
1.1629 - GST_BUFFER_MALLOCDATA (buffer) = data;
1.1630 - GST_BUFFER_SIZE (buffer) = nbytes;
1.1631 -
1.1632 - return buffer;
1.1633 -}
1.1634 -#endif
1.1635 -
1.1636 -
1.1637 -static gboolean
1.1638 -plugin_init (GstPlugin * plugin)
1.1639 -{
1.1640 -#ifdef ENABLE_NLS
1.1641 - setlocale (LC_ALL, "");
1.1642 - bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
1.1643 -#endif /* ENABLE_NLS */
1.1644 -
1.1645 - if (!gst_element_register (plugin, "nuvdemux", GST_RANK_SECONDARY,
1.1646 - GST_TYPE_NUV_DEMUX)) {
1.1647 - return FALSE;
1.1648 - }
1.1649 - return TRUE;
1.1650 -}
1.1651 -
1.1652 -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
1.1653 - GST_VERSION_MINOR,
1.1654 - "nuvdemux",
1.1655 - "Demuxes and muxes audio and video",
1.1656 - plugin_init, VERSION, "LGPL", "NuvDemux", "")
1.1657 -