mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-03-30 12:49:40 +00:00
rawparse: port to 0.11
This commit is contained in:
parent
7c4dfc7d7c
commit
cc7918de19
6 changed files with 315 additions and 384 deletions
|
@ -306,7 +306,7 @@ GST_PLUGINS_NONPORTED=" aiff asfmux \
|
|||
hdvparse hls id3tag inter interlace ivfparse jpegformat jp2kdecimator \
|
||||
kate liveadder legacyresample librfb mpegtsmux \
|
||||
mpegpsmux mve mxf mythtv nsf nuvdemux \
|
||||
patchdetect pnm rawparse real \
|
||||
patchdetect pnm real \
|
||||
sdi siren speed subenc stereo tta videofilters \
|
||||
videomeasure videosignal vmnc \
|
||||
decklink fbdev linsys shm vcd \
|
||||
|
|
|
@ -28,14 +28,17 @@
|
|||
# include "config.h"
|
||||
#endif
|
||||
|
||||
/* FIXME 0.11: suppress warnings for deprecated API such as g_value_array stuff
|
||||
* for now with newer GLib versions (>= 2.31.0) */
|
||||
#define GLIB_DISABLE_DEPRECATION_WARNINGS
|
||||
|
||||
#include "gstaudioparse.h"
|
||||
|
||||
#include <gst/audio/multichannel.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GST_AUDIO_PARSE_FORMAT_INT,
|
||||
GST_AUDIO_PARSE_FORMAT_FLOAT,
|
||||
GST_AUDIO_PARSE_FORMAT_RAW,
|
||||
GST_AUDIO_PARSE_FORMAT_MULAW,
|
||||
GST_AUDIO_PARSE_FORMAT_ALAW
|
||||
} GstAudioParseFormat;
|
||||
|
@ -63,24 +66,20 @@ enum
|
|||
{
|
||||
PROP_0,
|
||||
PROP_FORMAT,
|
||||
PROP_RAW_FORMAT,
|
||||
PROP_RATE,
|
||||
PROP_CHANNELS,
|
||||
PROP_ENDIANNESS,
|
||||
PROP_WIDTH,
|
||||
PROP_DEPTH,
|
||||
PROP_SIGNED,
|
||||
PROP_INTERLEAVED,
|
||||
PROP_CHANNEL_POSITIONS
|
||||
};
|
||||
|
||||
|
||||
#define GST_AUDIO_PARSE_FORMAT (gst_audio_parse_format_get_type ())
|
||||
static GType
|
||||
gst_audio_parse_format_get_type (void)
|
||||
{
|
||||
static GType audio_parse_format_type = 0;
|
||||
static const GEnumValue format_types[] = {
|
||||
{GST_AUDIO_PARSE_FORMAT_INT, "Integer", "int"},
|
||||
{GST_AUDIO_PARSE_FORMAT_FLOAT, "Floating Point", "float"},
|
||||
{GST_AUDIO_PARSE_FORMAT_RAW, "Raw", "raw"},
|
||||
{GST_AUDIO_PARSE_FORMAT_ALAW, "A-Law", "alaw"},
|
||||
{GST_AUDIO_PARSE_FORMAT_MULAW, "\302\265-Law", "mulaw"},
|
||||
{0, NULL, NULL}
|
||||
|
@ -94,68 +93,17 @@ gst_audio_parse_format_get_type (void)
|
|||
return audio_parse_format_type;
|
||||
}
|
||||
|
||||
#define GST_AUDIO_PARSE_ENDIANNESS (gst_audio_parse_endianness_get_type ())
|
||||
static GType
|
||||
gst_audio_parse_endianness_get_type (void)
|
||||
{
|
||||
static GType audio_parse_endianness_type = 0;
|
||||
static const GEnumValue endian_types[] = {
|
||||
{GST_AUDIO_PARSE_ENDIANNESS_LITTLE, "Little Endian", "little"},
|
||||
{GST_AUDIO_PARSE_ENDIANNESS_BIG, "Big Endian", "big"},
|
||||
{0, NULL, NULL}
|
||||
};
|
||||
|
||||
if (!audio_parse_endianness_type) {
|
||||
audio_parse_endianness_type =
|
||||
g_enum_register_static ("GstAudioParseEndianness", endian_types);
|
||||
}
|
||||
|
||||
return audio_parse_endianness_type;
|
||||
}
|
||||
|
||||
GST_BOILERPLATE (GstAudioParse, gst_audio_parse, GstRawParse,
|
||||
GST_TYPE_RAW_PARSE);
|
||||
|
||||
static void
|
||||
gst_audio_parse_base_init (gpointer g_class)
|
||||
{
|
||||
GstRawParseClass *rp_class = GST_RAW_PARSE_CLASS (g_class);
|
||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
|
||||
GstCaps *caps;
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (gst_audio_parse_debug, "audioparse", 0,
|
||||
"audioparse element");
|
||||
|
||||
gst_element_class_set_details_simple (gstelement_class, "Audio Parse",
|
||||
"Filter/Audio",
|
||||
"Converts stream into audio frames",
|
||||
"Sebastian Dröge <sebastian.droege@collabora.co.uk>");
|
||||
|
||||
caps =
|
||||
gst_caps_from_string ("audio/x-raw-int,"
|
||||
" depth=(int) [ 1, 32 ],"
|
||||
" width=(int) { 8, 16, 24, 32 },"
|
||||
" endianness=(int) { LITTLE_ENDIAN, BIG_ENDIAN }, "
|
||||
" signed=(bool) { TRUE, FALSE },"
|
||||
" rate=(int) [ 1, MAX ],"
|
||||
" channels=(int) [ 1, MAX ]; "
|
||||
"audio/x-raw-float,"
|
||||
" width=(int) { 32, 64 },"
|
||||
" endianness=(int) { LITTLE_ENDIAN, BIG_ENDIAN }, "
|
||||
" rate=(int)[1,MAX], channels=(int)[1,MAX]; "
|
||||
"audio/x-alaw, rate=(int)[1,MAX], channels=(int)[1,MAX]; "
|
||||
"audio/x-mulaw, rate=(int)[1,MAX], channels=(int)[1,MAX]");
|
||||
|
||||
gst_raw_parse_class_set_src_pad_template (rp_class, caps);
|
||||
gst_raw_parse_class_set_multiple_frames_per_buffer (rp_class, TRUE);
|
||||
gst_caps_unref (caps);
|
||||
}
|
||||
#define gst_audio_parse_parent_class parent_class
|
||||
G_DEFINE_TYPE (GstAudioParse, gst_audio_parse, GST_TYPE_RAW_PARSE);
|
||||
|
||||
static void
|
||||
gst_audio_parse_class_init (GstAudioParseClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
|
||||
GstRawParseClass *rp_class = GST_RAW_PARSE_CLASS (klass);
|
||||
GstCaps *caps;
|
||||
|
||||
gobject_class->set_property = gst_audio_parse_set_property;
|
||||
gobject_class->get_property = gst_audio_parse_get_property;
|
||||
|
@ -166,37 +114,26 @@ gst_audio_parse_class_init (GstAudioParseClass * klass)
|
|||
g_object_class_install_property (gobject_class, PROP_FORMAT,
|
||||
g_param_spec_enum ("format", "Format",
|
||||
"Format of audio samples in raw stream", GST_AUDIO_PARSE_FORMAT,
|
||||
GST_AUDIO_PARSE_FORMAT_INT,
|
||||
GST_AUDIO_PARSE_FORMAT_RAW,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_RAW_FORMAT,
|
||||
g_param_spec_enum ("raw-format", "Raw Format",
|
||||
"Format of audio samples in raw stream", GST_TYPE_AUDIO_FORMAT,
|
||||
GST_AUDIO_FORMAT_S16, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_RATE,
|
||||
g_param_spec_int ("rate", "Rate", "Rate of audio samples in raw stream",
|
||||
1, INT_MAX, 44100, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_CHANNELS,
|
||||
g_param_spec_int ("channels", "Channels",
|
||||
"Number of channels in raw stream", 1, INT_MAX, 2,
|
||||
"Number of channels in raw stream", 1, 64, 2,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_WIDTH,
|
||||
g_param_spec_int ("width", "Width",
|
||||
"Width of audio samples in raw stream", 1, INT_MAX, 16,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_DEPTH,
|
||||
g_param_spec_int ("depth", "Depth",
|
||||
"Depth of audio samples in raw stream", 1, INT_MAX, 16,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_SIGNED,
|
||||
g_param_spec_boolean ("signed", "signed",
|
||||
"Sign of audio samples in raw stream", TRUE,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_ENDIANNESS,
|
||||
g_param_spec_enum ("endianness", "Endianness",
|
||||
"Endianness of audio samples in raw stream",
|
||||
GST_AUDIO_PARSE_ENDIANNESS, G_BYTE_ORDER,
|
||||
g_object_class_install_property (gobject_class, PROP_INTERLEAVED,
|
||||
g_param_spec_boolean ("interleaved", "Interleaved Layout",
|
||||
"True if audio has interleaved layout", TRUE,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_CHANNEL_POSITIONS,
|
||||
|
@ -208,17 +145,32 @@ gst_audio_parse_class_init (GstAudioParseClass * klass)
|
|||
GST_AUDIO_CHANNEL_POSITION_NONE,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS),
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
gst_element_class_set_details_simple (gstelement_class, "Audio Parse",
|
||||
"Filter/Audio",
|
||||
"Converts stream into audio frames",
|
||||
"Sebastian Dröge <sebastian.droege@collabora.co.uk>");
|
||||
|
||||
caps = gst_caps_from_string (GST_AUDIO_CAPS_MAKE (GST_AUDIO_FORMATS_ALL)
|
||||
", layout = (string) { interleaved, non-interleaved }; "
|
||||
"audio/x-alaw, rate=(int)[1,MAX], channels=(int)[1,MAX]; "
|
||||
"audio/x-mulaw, rate=(int)[1,MAX], channels=(int)[1,MAX]");
|
||||
|
||||
gst_raw_parse_class_set_src_pad_template (rp_class, caps);
|
||||
gst_raw_parse_class_set_multiple_frames_per_buffer (rp_class, TRUE);
|
||||
gst_caps_unref (caps);
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (gst_audio_parse_debug, "audioparse", 0,
|
||||
"audioparse element");
|
||||
}
|
||||
|
||||
static void
|
||||
gst_audio_parse_init (GstAudioParse * ap, GstAudioParseClass * g_class)
|
||||
gst_audio_parse_init (GstAudioParse * ap)
|
||||
{
|
||||
ap->format = GST_AUDIO_PARSE_FORMAT_INT;
|
||||
ap->format = GST_AUDIO_PARSE_FORMAT_RAW;
|
||||
ap->raw_format = GST_AUDIO_FORMAT_S16;
|
||||
ap->channels = 2;
|
||||
ap->width = 16;
|
||||
ap->depth = 16;
|
||||
ap->signedness = TRUE;
|
||||
ap->endianness = G_BYTE_ORDER;
|
||||
ap->interleaved = TRUE;
|
||||
|
||||
gst_audio_parse_update_frame_size (ap);
|
||||
gst_raw_parse_set_fps (GST_RAW_PARSE (ap), 44100, 1);
|
||||
|
@ -236,23 +188,17 @@ gst_audio_parse_set_property (GObject * object, guint prop_id,
|
|||
case PROP_FORMAT:
|
||||
ap->format = g_value_get_enum (value);
|
||||
break;
|
||||
case PROP_RAW_FORMAT:
|
||||
ap->raw_format = g_value_get_enum (value);
|
||||
break;
|
||||
case PROP_RATE:
|
||||
gst_raw_parse_set_fps (GST_RAW_PARSE (ap), g_value_get_int (value), 1);
|
||||
break;
|
||||
case PROP_CHANNELS:
|
||||
ap->channels = g_value_get_int (value);
|
||||
break;
|
||||
case PROP_WIDTH:
|
||||
ap->width = g_value_get_int (value);
|
||||
break;
|
||||
case PROP_DEPTH:
|
||||
ap->depth = g_value_get_int (value);
|
||||
break;
|
||||
case PROP_SIGNED:
|
||||
ap->signedness = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_ENDIANNESS:
|
||||
ap->endianness = g_value_get_enum (value);
|
||||
case PROP_INTERLEAVED:
|
||||
ap->interleaved = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_CHANNEL_POSITIONS:
|
||||
if (ap->channel_positions)
|
||||
|
@ -278,6 +224,9 @@ gst_audio_parse_get_property (GObject * object, guint prop_id, GValue * value,
|
|||
case PROP_FORMAT:
|
||||
g_value_set_enum (value, ap->format);
|
||||
break;
|
||||
case PROP_RAW_FORMAT:
|
||||
g_value_set_enum (value, ap->raw_format);
|
||||
break;
|
||||
case PROP_RATE:{
|
||||
gint fps_n, fps_d;
|
||||
|
||||
|
@ -288,17 +237,8 @@ gst_audio_parse_get_property (GObject * object, guint prop_id, GValue * value,
|
|||
case PROP_CHANNELS:
|
||||
g_value_set_int (value, ap->channels);
|
||||
break;
|
||||
case PROP_WIDTH:
|
||||
g_value_set_int (value, ap->width);
|
||||
break;
|
||||
case PROP_DEPTH:
|
||||
g_value_set_int (value, ap->depth);
|
||||
break;
|
||||
case PROP_SIGNED:
|
||||
g_value_set_boolean (value, ap->signedness);
|
||||
break;
|
||||
case PROP_ENDIANNESS:
|
||||
g_value_set_enum (value, ap->endianness);
|
||||
case PROP_INTERLEAVED:
|
||||
g_value_set_boolean (value, ap->interleaved);
|
||||
break;
|
||||
case PROP_CHANNEL_POSITIONS:
|
||||
g_value_set_boxed (value, ap->channel_positions);
|
||||
|
@ -319,6 +259,9 @@ gst_audio_parse_finalize (GObject * object)
|
|||
ap->channel_positions = NULL;
|
||||
}
|
||||
|
||||
g_free (ap->channel_pos);
|
||||
g_free (ap->channel_order);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
|
@ -332,11 +275,18 @@ gst_audio_parse_update_frame_size (GstAudioParse * ap)
|
|||
case GST_AUDIO_PARSE_FORMAT_MULAW:
|
||||
width = 8;
|
||||
break;
|
||||
case GST_AUDIO_PARSE_FORMAT_INT:
|
||||
case GST_AUDIO_PARSE_FORMAT_FLOAT:
|
||||
case GST_AUDIO_PARSE_FORMAT_RAW:
|
||||
default:
|
||||
width = ap->width;
|
||||
{
|
||||
GstAudioInfo info;
|
||||
|
||||
gst_audio_info_init (&info);
|
||||
/* rate, etc do not really matter here */
|
||||
gst_audio_info_set_format (&info, ap->raw_format, 44100, ap->channels,
|
||||
NULL);
|
||||
width = GST_AUDIO_INFO_WIDTH (&info);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
framesize = (width / 8) * ap->channels;
|
||||
|
@ -344,13 +294,12 @@ gst_audio_parse_update_frame_size (GstAudioParse * ap)
|
|||
gst_raw_parse_set_framesize (GST_RAW_PARSE (ap), framesize);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_audio_parse_check_channel_positions (GValueArray * positions)
|
||||
static GstAudioChannelPosition *
|
||||
gst_audio_parse_get_channel_positions (GValueArray * positions)
|
||||
{
|
||||
gint i;
|
||||
guint channels;
|
||||
GstAudioChannelPosition *pos;
|
||||
gboolean ret;
|
||||
|
||||
channels = positions->n_values;
|
||||
pos = g_new (GstAudioChannelPosition, positions->n_values);
|
||||
|
@ -361,86 +310,89 @@ gst_audio_parse_check_channel_positions (GValueArray * positions)
|
|||
pos[i] = g_value_get_enum (v);
|
||||
}
|
||||
|
||||
ret = gst_audio_check_channel_positions (pos, channels);
|
||||
g_free (pos);
|
||||
|
||||
return ret;
|
||||
return pos;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_audio_parse_set_channel_positions (GstAudioParse * ap, GstStructure * s)
|
||||
gst_audio_parse_setup_channel_positions (GstAudioParse * ap)
|
||||
{
|
||||
GValue pos_array = { 0, };
|
||||
gint i;
|
||||
GstAudioChannelPosition *pos, *to;
|
||||
|
||||
if (!ap->channel_positions && ap->channels <= 2) {
|
||||
/* Implicit mapping for 1- and 2-channel audio is okay */
|
||||
g_free (ap->channel_pos);
|
||||
g_free (ap->channel_order);
|
||||
ap->channel_pos = NULL;
|
||||
ap->channel_order = NULL;
|
||||
|
||||
if (!ap->channel_positions) {
|
||||
GST_DEBUG_OBJECT (ap, "no channel positions");
|
||||
/* implicit mapping for 1- and 2-channel audio is okay */
|
||||
/* will come up with one in other cases also */
|
||||
return;
|
||||
}
|
||||
|
||||
g_value_init (&pos_array, GST_TYPE_ARRAY);
|
||||
|
||||
if (ap->channel_positions
|
||||
&& ap->channels == ap->channel_positions->n_values
|
||||
&& gst_audio_parse_check_channel_positions (ap->channel_positions)) {
|
||||
GST_DEBUG_OBJECT (ap, "Using provided channel positions");
|
||||
for (i = 0; i < ap->channels; i++)
|
||||
gst_value_array_append_value (&pos_array,
|
||||
g_value_array_get_nth (ap->channel_positions, i));
|
||||
} else {
|
||||
/* >2 channels and no explicit mapping */
|
||||
GValue pos_none = { 0, };
|
||||
|
||||
GST_WARNING_OBJECT (ap, "Using NONE channel positions");
|
||||
|
||||
g_value_init (&pos_none, GST_TYPE_AUDIO_CHANNEL_POSITION);
|
||||
g_value_set_enum (&pos_none, GST_AUDIO_CHANNEL_POSITION_NONE);
|
||||
|
||||
for (i = 0; i < ap->channels; i++)
|
||||
gst_value_array_append_value (&pos_array, &pos_none);
|
||||
|
||||
g_value_unset (&pos_none);
|
||||
pos = gst_audio_parse_get_channel_positions (ap->channel_positions);
|
||||
if (ap->channels != ap->channel_positions->n_values ||
|
||||
!gst_audio_check_valid_channel_positions (pos, ap->channels, FALSE)) {
|
||||
GST_DEBUG_OBJECT (ap, "invalid channel position");
|
||||
g_free (pos);
|
||||
return;
|
||||
}
|
||||
gst_structure_set_value (s, "channel-positions", &pos_array);
|
||||
g_value_unset (&pos_array);
|
||||
|
||||
/* ok, got something we can work with now */
|
||||
to = g_new (GstAudioChannelPosition, ap->channels);
|
||||
memcpy (to, pos, ap->channels * sizeof (to[0]));
|
||||
gst_audio_channel_positions_to_valid_order (to, ap->channels);
|
||||
|
||||
ap->channel_pos = pos;
|
||||
ap->channel_order = to;
|
||||
}
|
||||
|
||||
static GstCaps *
|
||||
gst_audio_parse_get_caps (GstRawParse * rp)
|
||||
{
|
||||
GstAudioParse *ap = GST_AUDIO_PARSE (rp);
|
||||
GstCaps *caps;
|
||||
|
||||
GstCaps *caps, *ncaps;
|
||||
GstAudioInfo info;
|
||||
gint fps_n, fps_d;
|
||||
const GValue *val;
|
||||
|
||||
gst_raw_parse_get_fps (rp, &fps_n, &fps_d);
|
||||
gst_audio_parse_setup_channel_positions (ap);
|
||||
|
||||
/* yes, even when format not raw */
|
||||
gst_audio_info_init (&info);
|
||||
gst_audio_info_set_format (&info, ap->raw_format, fps_n, ap->channels,
|
||||
ap->channel_order);
|
||||
info.layout = ap->interleaved ? GST_AUDIO_LAYOUT_INTERLEAVED :
|
||||
GST_AUDIO_LAYOUT_NON_INTERLEAVED;
|
||||
caps = gst_audio_info_to_caps (&info);
|
||||
|
||||
switch (ap->format) {
|
||||
case GST_AUDIO_PARSE_FORMAT_INT:
|
||||
caps = gst_caps_new_simple ("audio/x-raw-int",
|
||||
"rate", G_TYPE_INT, fps_n,
|
||||
"channels", G_TYPE_INT, ap->channels,
|
||||
"width", G_TYPE_INT, ap->width,
|
||||
"depth", G_TYPE_INT, ap->depth,
|
||||
"signed", G_TYPE_BOOLEAN, ap->signedness,
|
||||
"endianness", G_TYPE_INT, ap->endianness, NULL);
|
||||
break;
|
||||
case GST_AUDIO_PARSE_FORMAT_FLOAT:
|
||||
caps = gst_caps_new_simple ("audio/x-raw-float",
|
||||
"rate", G_TYPE_INT, fps_n,
|
||||
"channels", G_TYPE_INT, ap->channels,
|
||||
"width", G_TYPE_INT, ap->width,
|
||||
"endianness", G_TYPE_INT, ap->endianness, NULL);
|
||||
case GST_AUDIO_PARSE_FORMAT_RAW:
|
||||
break;
|
||||
case GST_AUDIO_PARSE_FORMAT_ALAW:
|
||||
caps = gst_caps_new_simple ("audio/x-alaw",
|
||||
ncaps = gst_caps_new_simple ("audio/x-alaw",
|
||||
"rate", G_TYPE_INT, fps_n,
|
||||
"channels", G_TYPE_INT, ap->channels, NULL);
|
||||
/* pick mask stuff from faked raw format */
|
||||
val = gst_structure_get_value (gst_caps_get_structure (caps, 0),
|
||||
"channel-mask");
|
||||
if (val)
|
||||
gst_caps_set_value (ncaps, "channel-mask", val);
|
||||
gst_caps_unref (caps);
|
||||
caps = ncaps;
|
||||
break;
|
||||
case GST_AUDIO_PARSE_FORMAT_MULAW:
|
||||
caps = gst_caps_new_simple ("audio/x-mulaw",
|
||||
ncaps = gst_caps_new_simple ("audio/x-mulaw",
|
||||
"rate", G_TYPE_INT, fps_n,
|
||||
"channels", G_TYPE_INT, ap->channels, NULL);
|
||||
/* pick mask stuff from faked raw format */
|
||||
val = gst_structure_get_value (gst_caps_get_structure (caps, 0),
|
||||
"channel-mask");
|
||||
if (val)
|
||||
gst_caps_set_value (ncaps, "channel-mask", val);
|
||||
gst_caps_unref (caps);
|
||||
caps = ncaps;
|
||||
break;
|
||||
default:
|
||||
caps = gst_caps_new_empty ();
|
||||
|
@ -448,7 +400,5 @@ gst_audio_parse_get_caps (GstRawParse * rp)
|
|||
break;
|
||||
}
|
||||
|
||||
gst_audio_parse_set_channel_positions (ap, gst_caps_get_structure (caps, 0));
|
||||
|
||||
return caps;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <gst/gst.h>
|
||||
#include <gst/base/gstbasetransform.h>
|
||||
#include <gst/base/gstadapter.h>
|
||||
#include <gst/audio/audio.h>
|
||||
|
||||
#include "gstrawparse.h"
|
||||
|
||||
|
@ -48,12 +49,13 @@ struct _GstAudioParse
|
|||
|
||||
/* properties */
|
||||
gint format;
|
||||
GstAudioFormat raw_format;
|
||||
gint channels;
|
||||
gint width;
|
||||
gint depth;
|
||||
gint signedness;
|
||||
gint endianness;
|
||||
gboolean interleaved;
|
||||
GValueArray *channel_positions;
|
||||
|
||||
GstAudioChannelPosition *channel_pos;
|
||||
GstAudioChannelPosition *channel_order;
|
||||
};
|
||||
|
||||
struct _GstAudioParseClass
|
||||
|
|
|
@ -41,20 +41,23 @@
|
|||
|
||||
static void gst_raw_parse_dispose (GObject * object);
|
||||
|
||||
static gboolean gst_raw_parse_sink_activate (GstPad * sinkpad);
|
||||
static gboolean gst_raw_parse_sink_activatepull (GstPad * sinkpad,
|
||||
gboolean active);
|
||||
static gboolean gst_raw_parse_sink_activate (GstPad * sinkpad,
|
||||
GstObject * parent);
|
||||
static gboolean gst_raw_parse_sink_activatemode (GstPad * sinkpad,
|
||||
GstObject * parent, GstPadMode mode, gboolean active);
|
||||
static void gst_raw_parse_loop (GstElement * element);
|
||||
static GstStateChangeReturn gst_raw_parse_change_state (GstElement * element,
|
||||
GstStateChange transition);
|
||||
static GstFlowReturn gst_raw_parse_chain (GstPad * pad, GstBuffer * buffer);
|
||||
static gboolean gst_raw_parse_sink_event (GstPad * pad, GstEvent * event);
|
||||
static gboolean gst_raw_parse_src_event (GstPad * pad, GstEvent * event);
|
||||
static const GstQueryType *gst_raw_parse_src_query_type (GstPad * pad);
|
||||
static gboolean gst_raw_parse_src_query (GstPad * pad, GstQuery * query);
|
||||
static gboolean gst_raw_parse_convert (GstRawParse * rp,
|
||||
GstFormat src_format, gint64 src_value,
|
||||
GstFormat dest_format, gint64 * dest_value);
|
||||
static GstFlowReturn gst_raw_parse_chain (GstPad * pad, GstObject * parent,
|
||||
GstBuffer * buffer);
|
||||
static gboolean gst_raw_parse_sink_event (GstPad * pad, GstObject * parent,
|
||||
GstEvent * event);
|
||||
static gboolean gst_raw_parse_src_event (GstPad * pad, GstObject * parent,
|
||||
GstEvent * event);
|
||||
static gboolean gst_raw_parse_src_query (GstPad * pad, GstObject * parent,
|
||||
GstQuery * query);
|
||||
static gboolean gst_raw_parse_convert (GstRawParse * rp, GstFormat src_format,
|
||||
gint64 src_value, GstFormat dest_format, gint64 * dest_value);
|
||||
static gboolean gst_raw_parse_handle_seek_pull (GstRawParse * rp,
|
||||
GstEvent * event);
|
||||
|
||||
|
@ -69,18 +72,29 @@ GST_STATIC_PAD_TEMPLATE ("sink",
|
|||
GST_DEBUG_CATEGORY_STATIC (gst_raw_parse_debug);
|
||||
#define GST_CAT_DEFAULT gst_raw_parse_debug
|
||||
|
||||
GST_BOILERPLATE (GstRawParse, gst_raw_parse, GstElement, GST_TYPE_ELEMENT);
|
||||
static void gst_raw_parse_class_init (GstRawParseClass * klass);
|
||||
static void gst_raw_parse_init (GstRawParse * clip, GstRawParseClass * g_class);
|
||||
|
||||
static void
|
||||
gst_raw_parse_base_init (gpointer g_class)
|
||||
static GstElementClass *parent_class;
|
||||
|
||||
/* we can't use G_DEFINE_ABSTRACT_TYPE because we need the klass in the _init
|
||||
* method to get to the padtemplates */
|
||||
GType
|
||||
gst_raw_parse_get_type (void)
|
||||
{
|
||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
|
||||
static volatile gsize raw_parse_type = 0;
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (gst_raw_parse_debug, "rawparse", 0,
|
||||
"rawparse element");
|
||||
if (g_once_init_enter (&raw_parse_type)) {
|
||||
GType _type;
|
||||
|
||||
gst_element_class_add_pad_template (gstelement_class,
|
||||
gst_static_pad_template_get (&gst_raw_parse_sink_pad_template));
|
||||
_type = g_type_register_static_simple (GST_TYPE_ELEMENT,
|
||||
"GstRawParse", sizeof (GstRawParseClass),
|
||||
(GClassInitFunc) gst_raw_parse_class_init, sizeof (GstRawParse),
|
||||
(GInstanceInitFunc) gst_raw_parse_init, G_TYPE_FLAG_ABSTRACT);
|
||||
|
||||
g_once_init_leave (&raw_parse_type, _type);
|
||||
}
|
||||
return raw_parse_type;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -89,10 +103,18 @@ gst_raw_parse_class_init (GstRawParseClass * klass)
|
|||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
|
||||
|
||||
parent_class = g_type_class_peek_parent (klass);
|
||||
|
||||
gobject_class->dispose = gst_raw_parse_dispose;
|
||||
|
||||
gstelement_class->change_state =
|
||||
GST_DEBUG_FUNCPTR (gst_raw_parse_change_state);
|
||||
|
||||
gst_element_class_add_pad_template (gstelement_class,
|
||||
gst_static_pad_template_get (&gst_raw_parse_sink_pad_template));
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (gst_raw_parse_debug, "rawparse", 0,
|
||||
"rawparse element");
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -110,8 +132,8 @@ gst_raw_parse_init (GstRawParse * rp, GstRawParseClass * g_class)
|
|||
GST_DEBUG_FUNCPTR (gst_raw_parse_sink_event));
|
||||
gst_pad_set_activate_function (rp->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_raw_parse_sink_activate));
|
||||
gst_pad_set_activatepull_function (rp->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_raw_parse_sink_activatepull));
|
||||
gst_pad_set_activatemode_function (rp->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_raw_parse_sink_activatemode));
|
||||
gst_element_add_pad (GST_ELEMENT (rp), rp->sinkpad);
|
||||
|
||||
src_pad_template = gst_element_class_get_pad_template (element_class, "src");
|
||||
|
@ -125,8 +147,6 @@ gst_raw_parse_init (GstRawParse * rp, GstRawParseClass * g_class)
|
|||
|
||||
gst_pad_set_event_function (rp->srcpad,
|
||||
GST_DEBUG_FUNCPTR (gst_raw_parse_src_event));
|
||||
gst_pad_set_query_type_function (rp->srcpad,
|
||||
GST_DEBUG_FUNCPTR (gst_raw_parse_src_query_type));
|
||||
gst_pad_set_query_function (rp->srcpad,
|
||||
GST_DEBUG_FUNCPTR (gst_raw_parse_src_query));
|
||||
gst_element_add_pad (GST_ELEMENT (rp), rp->srcpad);
|
||||
|
@ -218,7 +238,7 @@ gst_raw_parse_push_buffer (GstRawParse * rp, GstBuffer * buffer)
|
|||
|
||||
rpclass = GST_RAW_PARSE_GET_CLASS (rp);
|
||||
|
||||
nframes = GST_BUFFER_SIZE (buffer) / rp->framesize;
|
||||
nframes = gst_buffer_get_size (buffer) / rp->framesize;
|
||||
|
||||
if (rp->segment.rate < 0) {
|
||||
rp->n_frames -= nframes;
|
||||
|
@ -238,7 +258,6 @@ gst_raw_parse_push_buffer (GstRawParse * rp, GstBuffer * buffer)
|
|||
GST_BUFFER_TIMESTAMP (buffer) = rp->segment.start;
|
||||
GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
|
||||
}
|
||||
gst_buffer_set_caps (buffer, GST_PAD_CAPS (rp->srcpad));
|
||||
|
||||
if (rpclass->set_buffer_flags) {
|
||||
rpclass->set_buffer_flags (rp, buffer);
|
||||
|
@ -250,11 +269,11 @@ gst_raw_parse_push_buffer (GstRawParse * rp, GstBuffer * buffer)
|
|||
}
|
||||
|
||||
if (rp->segment.rate >= 0) {
|
||||
rp->offset += GST_BUFFER_SIZE (buffer);
|
||||
rp->offset += gst_buffer_get_size (buffer);
|
||||
rp->n_frames += nframes;
|
||||
}
|
||||
|
||||
rp->segment.last_stop = GST_BUFFER_TIMESTAMP (buffer);
|
||||
rp->segment.position = GST_BUFFER_TIMESTAMP (buffer);
|
||||
|
||||
GST_LOG_OBJECT (rp, "Pushing buffer with time %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
|
||||
|
@ -265,9 +284,9 @@ gst_raw_parse_push_buffer (GstRawParse * rp, GstBuffer * buffer)
|
|||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_raw_parse_chain (GstPad * pad, GstBuffer * buffer)
|
||||
gst_raw_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
|
||||
{
|
||||
GstRawParse *rp = GST_RAW_PARSE (gst_pad_get_parent (pad));
|
||||
GstRawParse *rp = GST_RAW_PARSE (parent);
|
||||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
GstRawParseClass *rp_class = GST_RAW_PARSE_GET_CLASS (rp);
|
||||
guint buffersize;
|
||||
|
@ -298,7 +317,6 @@ gst_raw_parse_chain (GstPad * pad, GstBuffer * buffer)
|
|||
break;
|
||||
}
|
||||
done:
|
||||
gst_object_unref (rp);
|
||||
|
||||
return ret;
|
||||
|
||||
|
@ -323,11 +341,6 @@ gst_raw_parse_loop (GstElement * element)
|
|||
if (!gst_raw_parse_set_src_caps (rp))
|
||||
goto no_caps;
|
||||
|
||||
if (rp->close_segment) {
|
||||
GST_DEBUG_OBJECT (rp, "sending close segment");
|
||||
gst_pad_push_event (rp->srcpad, rp->close_segment);
|
||||
rp->close_segment = NULL;
|
||||
}
|
||||
if (rp->start_segment) {
|
||||
GST_DEBUG_OBJECT (rp, "sending start segment");
|
||||
gst_pad_push_event (rp->srcpad, rp->start_segment);
|
||||
|
@ -343,13 +356,12 @@ gst_raw_parse_loop (GstElement * element)
|
|||
if (rp->offset + size > rp->upstream_length) {
|
||||
GstFormat fmt = GST_FORMAT_BYTES;
|
||||
|
||||
if (!gst_pad_query_peer_duration (rp->sinkpad, &fmt,
|
||||
&rp->upstream_length)) {
|
||||
if (!gst_pad_peer_query_duration (rp->sinkpad, fmt, &rp->upstream_length)) {
|
||||
GST_WARNING_OBJECT (rp,
|
||||
"Could not get upstream duration, trying to pull frame by frame");
|
||||
size = rp->framesize;
|
||||
} else if (rp->upstream_length < rp->offset + rp->framesize) {
|
||||
ret = GST_FLOW_UNEXPECTED;
|
||||
ret = GST_FLOW_EOS;
|
||||
goto pause;
|
||||
} else if (rp->offset + size > rp->upstream_length) {
|
||||
size = rp->upstream_length - rp->offset;
|
||||
|
@ -358,7 +370,7 @@ gst_raw_parse_loop (GstElement * element)
|
|||
}
|
||||
} else {
|
||||
if (rp->offset == 0) {
|
||||
ret = GST_FLOW_UNEXPECTED;
|
||||
ret = GST_FLOW_EOS;
|
||||
goto pause;
|
||||
} else if (rp->offset < size) {
|
||||
size -= rp->offset;
|
||||
|
@ -376,17 +388,18 @@ gst_raw_parse_loop (GstElement * element)
|
|||
goto pause;
|
||||
}
|
||||
|
||||
if (GST_BUFFER_SIZE (buffer) < size) {
|
||||
if (gst_buffer_get_size (buffer) < size) {
|
||||
GST_DEBUG_OBJECT (rp, "Short read at offset %" G_GINT64_FORMAT
|
||||
", got only %u of %u bytes", rp->offset, GST_BUFFER_SIZE (buffer),
|
||||
", got only %u of %u bytes", rp->offset, gst_buffer_get_size (buffer),
|
||||
size);
|
||||
|
||||
if (size > rp->framesize) {
|
||||
GST_BUFFER_SIZE (buffer) -= GST_BUFFER_SIZE (buffer) % rp->framesize;
|
||||
gst_buffer_set_size (buffer, gst_buffer_get_size (buffer) -
|
||||
gst_buffer_get_size (buffer) % rp->framesize);
|
||||
} else {
|
||||
gst_buffer_unref (buffer);
|
||||
buffer = NULL;
|
||||
ret = GST_FLOW_UNEXPECTED;
|
||||
ret = GST_FLOW_EOS;
|
||||
goto pause;
|
||||
}
|
||||
}
|
||||
|
@ -411,7 +424,7 @@ pause:
|
|||
GST_LOG_OBJECT (rp, "pausing task, reason %s", reason);
|
||||
gst_pad_pause_task (rp->sinkpad);
|
||||
|
||||
if (ret == GST_FLOW_UNEXPECTED) {
|
||||
if (ret == GST_FLOW_EOS) {
|
||||
if (rp->segment.flags & GST_SEEK_FLAG_SEGMENT) {
|
||||
GstClockTime stop;
|
||||
|
||||
|
@ -427,7 +440,7 @@ pause:
|
|||
GST_LOG_OBJECT (rp, "Sending EOS, at end of stream");
|
||||
gst_pad_push_event (rp->srcpad, gst_event_new_eos ());
|
||||
}
|
||||
} else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_UNEXPECTED) {
|
||||
} else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
|
||||
GST_ELEMENT_ERROR (rp, STREAM, FAILED,
|
||||
("Internal data stream error."),
|
||||
("stream stopped, reason %s", reason));
|
||||
|
@ -438,50 +451,68 @@ pause:
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_raw_parse_sink_activate (GstPad * sinkpad)
|
||||
gst_raw_parse_sink_activate (GstPad * sinkpad, GstObject * parent)
|
||||
{
|
||||
if (gst_pad_check_pull_range (sinkpad)) {
|
||||
GST_RAW_PARSE (GST_PAD_PARENT (sinkpad))->mode = GST_PAD_ACTIVATE_PULL;
|
||||
return gst_pad_activate_pull (sinkpad, TRUE);
|
||||
GstQuery *query;
|
||||
gboolean pull_mode = FALSE;
|
||||
|
||||
query = gst_query_new_scheduling ();
|
||||
|
||||
if (gst_pad_peer_query (sinkpad, query))
|
||||
pull_mode = gst_query_has_scheduling_mode (query, GST_PAD_MODE_PULL);
|
||||
|
||||
gst_query_unref (query);
|
||||
|
||||
if (pull_mode) {
|
||||
GST_DEBUG ("going to pull mode");
|
||||
return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
|
||||
} else {
|
||||
GST_RAW_PARSE (GST_PAD_PARENT (sinkpad))->mode = GST_PAD_ACTIVATE_PUSH;
|
||||
return gst_pad_activate_push (sinkpad, TRUE);
|
||||
GST_DEBUG ("going to push (streaming) mode");
|
||||
return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_raw_parse_sink_activatepull (GstPad * sinkpad, gboolean active)
|
||||
gst_raw_parse_sink_activatemode (GstPad * sinkpad, GstObject * parent,
|
||||
GstPadMode mode, gboolean active)
|
||||
{
|
||||
GstRawParse *rp = GST_RAW_PARSE (gst_pad_get_parent (sinkpad));
|
||||
GstRawParse *rp = GST_RAW_PARSE (parent);
|
||||
gboolean result;
|
||||
|
||||
if (active) {
|
||||
GstFormat format;
|
||||
gint64 duration;
|
||||
switch (mode) {
|
||||
case GST_PAD_MODE_PULL:
|
||||
if (active) {
|
||||
GstFormat format;
|
||||
gint64 duration;
|
||||
|
||||
/* get the duration in bytes */
|
||||
format = GST_FORMAT_BYTES;
|
||||
result = gst_pad_query_peer_duration (sinkpad, &format, &duration);
|
||||
if (result) {
|
||||
GST_DEBUG_OBJECT (rp, "got duration %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (duration));
|
||||
rp->upstream_length = duration;
|
||||
/* convert to time */
|
||||
gst_raw_parse_convert (rp, format, duration, GST_FORMAT_TIME, &duration);
|
||||
} else {
|
||||
rp->upstream_length = -1;
|
||||
duration = -1;
|
||||
}
|
||||
gst_segment_set_duration (&rp->segment, GST_FORMAT_TIME, duration);
|
||||
/* get the duration in bytes */
|
||||
format = GST_FORMAT_BYTES;
|
||||
result = gst_pad_peer_query_duration (sinkpad, format, &duration);
|
||||
if (result) {
|
||||
GST_DEBUG_OBJECT (rp, "got duration %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (duration));
|
||||
rp->upstream_length = duration;
|
||||
/* convert to time */
|
||||
gst_raw_parse_convert (rp, format, duration, GST_FORMAT_TIME,
|
||||
&duration);
|
||||
} else {
|
||||
rp->upstream_length = -1;
|
||||
duration = -1;
|
||||
}
|
||||
rp->segment.duration = duration;
|
||||
|
||||
result = gst_raw_parse_handle_seek_pull (rp, NULL);
|
||||
} else {
|
||||
result = gst_pad_stop_task (sinkpad);
|
||||
result = gst_raw_parse_handle_seek_pull (rp, NULL);
|
||||
rp->mode = mode;
|
||||
} else {
|
||||
result = gst_pad_stop_task (sinkpad);
|
||||
}
|
||||
return result;
|
||||
case GST_PAD_MODE_PUSH:
|
||||
rp->mode = mode;
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gst_object_unref (rp);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static GstStateChangeReturn
|
||||
|
@ -493,7 +524,7 @@ gst_raw_parse_change_state (GstElement * element, GstStateChange transition)
|
|||
switch (transition) {
|
||||
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
||||
gst_segment_init (&rp->segment, GST_FORMAT_TIME);
|
||||
rp->segment.last_stop = 0;
|
||||
rp->segment.position = 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -614,9 +645,9 @@ done:
|
|||
|
||||
|
||||
static gboolean
|
||||
gst_raw_parse_sink_event (GstPad * pad, GstEvent * event)
|
||||
gst_raw_parse_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
|
||||
{
|
||||
GstRawParse *rp = GST_RAW_PARSE (gst_pad_get_parent (pad));
|
||||
GstRawParse *rp = GST_RAW_PARSE (parent);
|
||||
gboolean ret;
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
|
@ -626,54 +657,44 @@ gst_raw_parse_sink_event (GstPad * pad, GstEvent * event)
|
|||
gst_raw_parse_reset (rp);
|
||||
ret = gst_pad_push_event (rp->srcpad, event);
|
||||
break;
|
||||
case GST_EVENT_NEWSEGMENT:
|
||||
case GST_EVENT_SEGMENT:
|
||||
{
|
||||
GstClockTimeDiff start, stop, time;
|
||||
gdouble rate, arate;
|
||||
gboolean update;
|
||||
GstFormat format;
|
||||
GstSegment segment;
|
||||
|
||||
/* Only happens in push mode */
|
||||
|
||||
gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
|
||||
&start, &stop, &time);
|
||||
|
||||
if (format == GST_FORMAT_TIME) {
|
||||
gst_segment_set_newsegment_full (&rp->segment, update, rate, arate,
|
||||
GST_FORMAT_TIME, start, stop, time);
|
||||
ret = gst_pad_push_event (rp->srcpad, event);
|
||||
} else {
|
||||
gst_event_copy_segment (event, &segment);
|
||||
|
||||
if (segment.format != GST_FORMAT_TIME) {
|
||||
gst_event_unref (event);
|
||||
|
||||
ret =
|
||||
gst_raw_parse_convert (rp, format, start, GST_FORMAT_TIME, &start);
|
||||
ret &= gst_raw_parse_convert (rp, format, time, GST_FORMAT_TIME, &time);
|
||||
ret &= gst_raw_parse_convert (rp, format, stop, GST_FORMAT_TIME, &stop);
|
||||
gst_raw_parse_convert (rp, segment.format, segment.start,
|
||||
GST_FORMAT_TIME, (gint64 *) & segment.start);
|
||||
ret &= gst_raw_parse_convert (rp, segment.format, segment.time,
|
||||
GST_FORMAT_TIME, (gint64 *) & segment.time);
|
||||
ret &= gst_raw_parse_convert (rp, segment.format, segment.stop,
|
||||
GST_FORMAT_TIME, (gint64 *) & segment.stop);
|
||||
if (!ret) {
|
||||
GST_ERROR_OBJECT (rp,
|
||||
"Failed converting to GST_FORMAT_TIME format (%d)", format);
|
||||
"Failed converting to GST_FORMAT_TIME format (%d)",
|
||||
segment.format);
|
||||
break;
|
||||
}
|
||||
|
||||
gst_segment_set_newsegment_full (&rp->segment, update, rate, arate,
|
||||
GST_FORMAT_TIME, start, stop, time);
|
||||
|
||||
/* create new segment with the fields converted to time */
|
||||
event = gst_event_new_new_segment_full (update, rate, arate,
|
||||
GST_FORMAT_TIME, start, stop, time);
|
||||
|
||||
ret = gst_pad_push_event (rp->srcpad, event);
|
||||
event = gst_event_new_segment (&segment);
|
||||
}
|
||||
|
||||
gst_segment_copy_into (&segment, &rp->segment);
|
||||
|
||||
ret = gst_pad_push_event (rp->srcpad, event);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ret = gst_pad_event_default (rp->sinkpad, event);
|
||||
ret = gst_pad_event_default (rp->sinkpad, parent, event);
|
||||
break;
|
||||
}
|
||||
|
||||
gst_object_unref (rp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -785,12 +806,12 @@ gst_raw_parse_handle_seek_pull (GstRawParse * rp, GstEvent * event)
|
|||
|
||||
if (event) {
|
||||
/* configure the seek values */
|
||||
gst_segment_set_seek (&seeksegment, rate, format, flags,
|
||||
gst_segment_do_seek (&seeksegment, rate, format, flags,
|
||||
start_type, start, stop_type, stop, NULL);
|
||||
}
|
||||
|
||||
/* get the desired position */
|
||||
last_stop = seeksegment.last_stop;
|
||||
last_stop = seeksegment.position;
|
||||
|
||||
GST_LOG_OBJECT (rp, "seeking to %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (last_stop));
|
||||
|
@ -803,21 +824,8 @@ gst_raw_parse_handle_seek_pull (GstRawParse * rp, GstEvent * event)
|
|||
/* prepare for streaming */
|
||||
if (flush) {
|
||||
GST_LOG_OBJECT (rp, "stop flush");
|
||||
gst_pad_push_event (rp->sinkpad, gst_event_new_flush_stop ());
|
||||
gst_pad_push_event (rp->srcpad, gst_event_new_flush_stop ());
|
||||
} else if (ret && rp->running) {
|
||||
/* we are running the current segment and doing a non-flushing seek,
|
||||
* close the segment first based on the last_stop. */
|
||||
GST_DEBUG_OBJECT (rp, "prepare close segment %" G_GINT64_FORMAT
|
||||
" to %" G_GINT64_FORMAT, rp->segment.start, rp->segment.last_stop);
|
||||
|
||||
/* queue the segment for sending in the stream thread */
|
||||
if (rp->close_segment)
|
||||
gst_event_unref (rp->close_segment);
|
||||
rp->close_segment =
|
||||
gst_event_new_new_segment_full (TRUE,
|
||||
rp->segment.rate, rp->segment.applied_rate, rp->segment.format,
|
||||
rp->segment.start, rp->segment.last_stop, rp->segment.time);
|
||||
gst_pad_push_event (rp->sinkpad, gst_event_new_flush_stop (TRUE));
|
||||
gst_pad_push_event (rp->srcpad, gst_event_new_flush_stop (TRUE));
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
|
@ -836,7 +844,7 @@ gst_raw_parse_handle_seek_pull (GstRawParse * rp, GstEvent * event)
|
|||
if (rp->segment.flags & GST_SEEK_FLAG_SEGMENT) {
|
||||
gst_element_post_message (GST_ELEMENT_CAST (rp),
|
||||
gst_message_new_segment_start (GST_OBJECT_CAST (rp),
|
||||
rp->segment.format, rp->segment.last_stop));
|
||||
rp->segment.format, rp->segment.position));
|
||||
}
|
||||
|
||||
/* for deriving a stop position for the playback segment from the seek
|
||||
|
@ -851,25 +859,11 @@ gst_raw_parse_handle_seek_pull (GstRawParse * rp, GstEvent * event)
|
|||
* next time it is scheduled. */
|
||||
if (rp->start_segment)
|
||||
gst_event_unref (rp->start_segment);
|
||||
|
||||
if (rp->segment.rate >= 0.0) {
|
||||
/* forward, we send data from last_stop to stop */
|
||||
rp->start_segment =
|
||||
gst_event_new_new_segment_full (FALSE,
|
||||
rp->segment.rate, rp->segment.applied_rate, rp->segment.format,
|
||||
rp->segment.last_stop, stop, rp->segment.time);
|
||||
} else {
|
||||
/* reverse, we send data from last_stop to start */
|
||||
rp->start_segment =
|
||||
gst_event_new_new_segment_full (FALSE,
|
||||
rp->segment.rate, rp->segment.applied_rate, rp->segment.format,
|
||||
rp->segment.start, rp->segment.last_stop, rp->segment.time);
|
||||
}
|
||||
rp->start_segment = gst_event_new_segment (&rp->segment);
|
||||
}
|
||||
rp->discont = TRUE;
|
||||
|
||||
GST_LOG_OBJECT (rp, "start streaming");
|
||||
rp->running = TRUE;
|
||||
gst_pad_start_task (rp->sinkpad, (GstTaskFunction) gst_raw_parse_loop, rp);
|
||||
|
||||
GST_PAD_STREAM_UNLOCK (rp->sinkpad);
|
||||
|
@ -885,46 +879,30 @@ convert_failed:
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_raw_parse_src_event (GstPad * pad, GstEvent * event)
|
||||
gst_raw_parse_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
|
||||
{
|
||||
GstRawParse *rp = GST_RAW_PARSE (gst_pad_get_parent (pad));
|
||||
GstRawParse *rp = GST_RAW_PARSE (parent);
|
||||
gboolean ret;
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_SEEK:
|
||||
if (rp->mode == GST_PAD_ACTIVATE_PUSH)
|
||||
if (rp->mode == GST_PAD_MODE_PUSH)
|
||||
ret = gst_raw_parse_handle_seek_push (rp, event);
|
||||
else
|
||||
ret = gst_raw_parse_handle_seek_pull (rp, event);
|
||||
break;
|
||||
default:
|
||||
ret = gst_pad_event_default (rp->srcpad, event);
|
||||
ret = gst_pad_event_default (rp->srcpad, parent, event);
|
||||
break;
|
||||
}
|
||||
|
||||
gst_object_unref (rp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const GstQueryType *
|
||||
gst_raw_parse_src_query_type (GstPad * pad)
|
||||
{
|
||||
static const GstQueryType types[] = {
|
||||
GST_QUERY_POSITION,
|
||||
GST_QUERY_DURATION,
|
||||
GST_QUERY_CONVERT,
|
||||
GST_QUERY_SEEKING,
|
||||
0
|
||||
};
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_raw_parse_src_query (GstPad * pad, GstQuery * query)
|
||||
gst_raw_parse_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
|
||||
{
|
||||
GstRawParse *rp = GST_RAW_PARSE (gst_pad_get_parent (pad));
|
||||
GstRawParse *rp = GST_RAW_PARSE (parent);
|
||||
gboolean ret = FALSE;
|
||||
|
||||
GST_DEBUG ("src_query %s", gst_query_type_get_name (GST_QUERY_TYPE (query)));
|
||||
|
@ -939,7 +917,7 @@ gst_raw_parse_src_query (GstPad * pad, GstQuery * query)
|
|||
|
||||
gst_query_parse_position (query, &format, NULL);
|
||||
|
||||
time = rp->segment.last_stop;
|
||||
time = rp->segment.position;
|
||||
ret = gst_raw_parse_convert (rp, GST_FORMAT_TIME, time, format, &value);
|
||||
|
||||
gst_query_set_position (query, format, value);
|
||||
|
@ -1001,7 +979,7 @@ gst_raw_parse_src_query (GstPad * pad, GstQuery * query)
|
|||
if (fmt != GST_FORMAT_TIME && fmt != GST_FORMAT_DEFAULT
|
||||
&& fmt != GST_FORMAT_BYTES) {
|
||||
gst_query_set_seeking (query, fmt, FALSE, -1, -1);
|
||||
} else if (rp->mode == GST_PAD_ACTIVATE_PUSH) {
|
||||
} else if (rp->mode == GST_PAD_MODE_PUSH) {
|
||||
GstQuery *peerquery = gst_query_new_seeking (GST_FORMAT_BYTES);
|
||||
gboolean seekable;
|
||||
|
||||
|
@ -1018,12 +996,11 @@ gst_raw_parse_src_query (GstPad * pad, GstQuery * query)
|
|||
}
|
||||
default:
|
||||
/* else forward upstream */
|
||||
ret = gst_pad_peer_query (rp->sinkpad, query);
|
||||
ret = gst_pad_query_default (rp->sinkpad, parent, query);
|
||||
break;
|
||||
}
|
||||
|
||||
done:
|
||||
gst_object_unref (rp);
|
||||
return ret;
|
||||
|
||||
/* ERRORS */
|
||||
|
@ -1040,6 +1017,7 @@ gst_raw_parse_set_framesize (GstRawParse * rp, int framesize)
|
|||
g_return_if_fail (GST_IS_RAW_PARSE (rp));
|
||||
g_return_if_fail (!rp->negotiated);
|
||||
|
||||
GST_DEBUG_OBJECT (rp, "framesize %d", framesize);
|
||||
rp->framesize = framesize;
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ struct _GstRawParse
|
|||
GstPad *sinkpad;
|
||||
GstPad *srcpad;
|
||||
|
||||
GstPadActivateMode mode;
|
||||
GstPadMode mode;
|
||||
GstAdapter *adapter;
|
||||
|
||||
gint framesize;
|
||||
|
@ -66,8 +66,6 @@ struct _GstRawParse
|
|||
gint64 offset;
|
||||
|
||||
GstSegment segment;
|
||||
gboolean running;
|
||||
GstEvent *close_segment;
|
||||
GstEvent *start_segment;
|
||||
|
||||
gboolean negotiated;
|
||||
|
|
|
@ -57,39 +57,16 @@ enum
|
|||
PROP_TOP_FIELD_FIRST
|
||||
};
|
||||
|
||||
GST_BOILERPLATE (GstVideoParse, gst_video_parse, GstRawParse,
|
||||
GST_TYPE_RAW_PARSE);
|
||||
|
||||
static void
|
||||
gst_video_parse_base_init (gpointer g_class)
|
||||
{
|
||||
GstRawParseClass *rp_class = GST_RAW_PARSE_CLASS (g_class);
|
||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
|
||||
GstCaps *caps;
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (gst_video_parse_debug, "videoparse", 0,
|
||||
"videoparse element");
|
||||
|
||||
gst_element_class_set_details_simple (gstelement_class, "Video Parse",
|
||||
"Filter/Video",
|
||||
"Converts stream into video frames",
|
||||
"David Schleef <ds@schleef.org>, "
|
||||
"Sebastian Dröge <sebastian.droege@collabora.co.uk>");
|
||||
|
||||
caps =
|
||||
gst_caps_from_string
|
||||
("video/x-raw-rgb; video/x-raw-yuv; video/x-raw-gray; video/x-raw-bayer");
|
||||
|
||||
gst_raw_parse_class_set_src_pad_template (rp_class, caps);
|
||||
gst_raw_parse_class_set_multiple_frames_per_buffer (rp_class, FALSE);
|
||||
gst_caps_unref (caps);
|
||||
}
|
||||
#define gst_video_parse_parent_class parent_class
|
||||
G_DEFINE_TYPE (GstVideoParse, gst_video_parse, GST_TYPE_RAW_PARSE);
|
||||
|
||||
static void
|
||||
gst_video_parse_class_init (GstVideoParseClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
|
||||
GstRawParseClass *rp_class = GST_RAW_PARSE_CLASS (klass);
|
||||
GstCaps *caps;
|
||||
|
||||
gobject_class->set_property = gst_video_parse_set_property;
|
||||
gobject_class->get_property = gst_video_parse_get_property;
|
||||
|
@ -123,10 +100,25 @@ gst_video_parse_class_init (GstVideoParseClass * klass)
|
|||
g_param_spec_boolean ("top-field-first", "Top field first",
|
||||
"True if top field is earlier than bottom field", TRUE,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
gst_element_class_set_details_simple (gstelement_class, "Video Parse",
|
||||
"Filter/Video",
|
||||
"Converts stream into video frames",
|
||||
"David Schleef <ds@schleef.org>, "
|
||||
"Sebastian Dröge <sebastian.droege@collabora.co.uk>");
|
||||
|
||||
caps = gst_caps_from_string ("video/x-raw; video/x-raw-bayer");
|
||||
|
||||
gst_raw_parse_class_set_src_pad_template (rp_class, caps);
|
||||
gst_raw_parse_class_set_multiple_frames_per_buffer (rp_class, FALSE);
|
||||
gst_caps_unref (caps);
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (gst_video_parse_debug, "videoparse", 0,
|
||||
"videoparse element");
|
||||
}
|
||||
|
||||
static void
|
||||
gst_video_parse_init (GstVideoParse * vp, GstVideoParseClass * g_class)
|
||||
gst_video_parse_init (GstVideoParse * vp)
|
||||
{
|
||||
vp->width = 320;
|
||||
vp->height = 240;
|
||||
|
@ -221,8 +213,11 @@ void
|
|||
gst_video_parse_update_frame_size (GstVideoParse * vp)
|
||||
{
|
||||
gint framesize;
|
||||
GstVideoInfo info;
|
||||
|
||||
framesize = gst_video_format_get_size (vp->format, vp->width, vp->height);
|
||||
gst_video_info_init (&info);
|
||||
gst_video_info_set_format (&info, vp->format, vp->width, vp->height);
|
||||
framesize = GST_VIDEO_INFO_SIZE (&info);
|
||||
|
||||
gst_raw_parse_set_framesize (GST_RAW_PARSE (vp), framesize);
|
||||
}
|
||||
|
@ -231,15 +226,23 @@ static GstCaps *
|
|||
gst_video_parse_get_caps (GstRawParse * rp)
|
||||
{
|
||||
GstVideoParse *vp = GST_VIDEO_PARSE (rp);
|
||||
GstVideoInfo info;
|
||||
GstCaps *caps;
|
||||
|
||||
gint fps_n, fps_d;
|
||||
|
||||
gst_raw_parse_get_fps (rp, &fps_n, &fps_d);
|
||||
|
||||
caps =
|
||||
gst_video_format_new_caps_interlaced (vp->format, vp->width, vp->height,
|
||||
fps_n, fps_d, vp->par_n, vp->par_d, vp->interlaced);
|
||||
gst_video_info_init (&info);
|
||||
gst_video_info_set_format (&info, vp->format, vp->width, vp->height);
|
||||
info.fps_n = fps_n;
|
||||
info.fps_d = fps_d;
|
||||
info.par_n = vp->par_n;
|
||||
info.par_d = vp->par_d;
|
||||
info.interlace_mode = vp->interlaced ?
|
||||
GST_VIDEO_INTERLACE_MODE_INTERLEAVED :
|
||||
GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
|
||||
|
||||
caps = gst_video_info_to_caps (&info);
|
||||
|
||||
return caps;
|
||||
}
|
||||
|
@ -251,9 +254,9 @@ gst_video_parse_set_buffer_flags (GstRawParse * rp, GstBuffer * buffer)
|
|||
|
||||
if (vp->interlaced) {
|
||||
if (vp->top_field_first) {
|
||||
GST_BUFFER_FLAG_SET (buffer, GST_VIDEO_BUFFER_TFF);
|
||||
GST_BUFFER_FLAG_SET (buffer, GST_VIDEO_BUFFER_FLAG_TFF);
|
||||
} else {
|
||||
GST_BUFFER_FLAG_UNSET (buffer, GST_VIDEO_BUFFER_TFF);
|
||||
GST_BUFFER_FLAG_UNSET (buffer, GST_VIDEO_BUFFER_FLAG_TFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue