mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-24 02:31:03 +00:00
Merge branch 'master' into 0.11
Conflicts: ext/flac/gstflacdec.c gst/audioparsers/gstflacparse.c gst/isomp4/qtdemux.c
This commit is contained in:
commit
95f3987332
9 changed files with 496 additions and 10 deletions
|
@ -65,12 +65,14 @@ enum
|
|||
ARG_YPAD,
|
||||
ARG_DELTAX,
|
||||
ARG_DELTAY,
|
||||
ARG_SILENT,
|
||||
ARG_FONT_DESC
|
||||
};
|
||||
|
||||
#define DEFAULT_YPAD 25
|
||||
#define DEFAULT_XPAD 25
|
||||
#define DEFAULT_FONT "sans"
|
||||
#define DEFAULT_SILENT FALSE
|
||||
|
||||
#define GST_CAIRO_TEXT_OVERLAY_DEFAULT_SCALE 20.0
|
||||
|
||||
|
@ -201,6 +203,11 @@ gst_text_overlay_class_init (GstCairoTextOverlayClass * klass)
|
|||
"See documentation of "
|
||||
"pango_font_description_from_string"
|
||||
" for syntax.", "", G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
|
||||
/* FIXME 0.11: rename to "visible" or "text-visible" or "render-text" */
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SILENT,
|
||||
g_param_spec_boolean ("silent", "silent",
|
||||
"Whether to render the text string",
|
||||
DEFAULT_SILENT, G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -267,6 +274,8 @@ gst_text_overlay_init (GstCairoTextOverlay * overlay,
|
|||
overlay->font = g_strdup (DEFAULT_FONT);
|
||||
gst_text_overlay_font_init (overlay);
|
||||
|
||||
overlay->silent = DEFAULT_SILENT;
|
||||
|
||||
overlay->fps_n = 0;
|
||||
overlay->fps_d = 1;
|
||||
|
||||
|
@ -410,6 +419,9 @@ gst_text_overlay_set_property (GObject * object, guint prop_id,
|
|||
gst_text_overlay_font_init (overlay);
|
||||
break;
|
||||
}
|
||||
case ARG_SILENT:
|
||||
overlay->silent = g_value_get_boolean (value);
|
||||
break;
|
||||
default:{
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -431,6 +443,11 @@ gst_text_overlay_render_text (GstCairoTextOverlay * overlay,
|
|||
gchar *string;
|
||||
double x, y;
|
||||
|
||||
if (overlay->silent) {
|
||||
GST_DEBUG_OBJECT (overlay, "Silent mode, not rendering");
|
||||
return;
|
||||
}
|
||||
|
||||
if (textlen < 0)
|
||||
textlen = strlen (text);
|
||||
|
||||
|
|
|
@ -76,6 +76,7 @@ struct _GstCairoTextOverlay {
|
|||
gint slant;
|
||||
gint weight;
|
||||
gdouble scale;
|
||||
gboolean silent;
|
||||
};
|
||||
|
||||
struct _GstCairoTextOverlayClass {
|
||||
|
|
|
@ -527,6 +527,34 @@ gst_flac_parse_frame_header_is_valid (GstFlacParse * flacparse,
|
|||
if (actual_crc != expected_crc)
|
||||
goto error;
|
||||
|
||||
/*
|
||||
The FLAC format documentation says:
|
||||
The "blocking strategy" bit determines how to calculate the sample number
|
||||
of the first sample in the frame. If the bit is 0 (fixed-blocksize), the
|
||||
frame header encodes the frame number as above, and the frame's starting
|
||||
sample number will be the frame number times the blocksize. If it is 1
|
||||
(variable-blocksize), the frame header encodes the frame's starting
|
||||
sample number itself. (In the case of a fixed-blocksize stream, only the
|
||||
last block may be shorter than the stream blocksize; its starting sample
|
||||
number will be calculated as the frame number times the previous frame's
|
||||
blocksize, or zero if it is the first frame).
|
||||
|
||||
Therefore, when in fixed block size mode, we only update the block size
|
||||
the first time, then reuse that block size for subsequent calls.
|
||||
This will also fix a timestamp problem with the last block's timestamp
|
||||
being miscalculated by scaling the block number by a "wrong" block size.
|
||||
*/
|
||||
if (blocking_strategy == 0) {
|
||||
if (flacparse->block_size != 0) {
|
||||
/* after first block */
|
||||
if (flacparse->block_size != block_size) {
|
||||
/* TODO: can we know we're on the last frame, to avoid warning ? */
|
||||
GST_WARNING_OBJECT (flacparse, "Block size is not constant");
|
||||
block_size = flacparse->block_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (set) {
|
||||
flacparse->block_size = block_size;
|
||||
if (!flacparse->samplerate)
|
||||
|
@ -706,7 +734,6 @@ gst_flac_parse_check_valid_frame (GstBaseParse * parse,
|
|||
|
||||
flacparse->offset = GST_BUFFER_OFFSET (buffer);
|
||||
flacparse->blocking_strategy = 0;
|
||||
flacparse->block_size = 0;
|
||||
flacparse->sample_number = 0;
|
||||
|
||||
GST_DEBUG_OBJECT (flacparse, "Found sync code");
|
||||
|
@ -1404,7 +1431,6 @@ gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
|||
|
||||
flacparse->offset = -1;
|
||||
flacparse->blocking_strategy = 0;
|
||||
flacparse->block_size = 0;
|
||||
flacparse->sample_number = 0;
|
||||
res = GST_FLOW_OK;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ libgstflv_la_LDFLAGS = ${GST_PLUGIN_LDFLAGS}
|
|||
libgstflv_la_SOURCES = gstflvdemux.c gstflvmux.c
|
||||
libgstflv_la_LIBTOOLFLAGS = --tag=disable-static
|
||||
|
||||
noinst_HEADERS = gstflvdemux.h gstflvmux.h
|
||||
noinst_HEADERS = gstflvdemux.h gstflvmux.h amfdefs.h
|
||||
|
||||
Android.mk: Makefile.am $(BUILT_SOURCES)
|
||||
androgenizer \
|
||||
|
|
|
@ -85,6 +85,9 @@ G_DEFINE_TYPE (GstFlvDemux, gst_flv_demux, GST_TYPE_ELEMENT);
|
|||
/* 1 byte of tag type + 3 bytes of tag data size */
|
||||
#define FLV_TAG_TYPE_SIZE 4
|
||||
|
||||
/* two seconds - consider pts are resynced to another base if this different */
|
||||
#define RESYNC_THRESHOLD 2000
|
||||
|
||||
static gboolean flv_demux_handle_seek_push (GstFlvDemux * demux,
|
||||
GstEvent * event);
|
||||
static gboolean gst_flv_demux_handle_seek_pull (GstFlvDemux * demux,
|
||||
|
@ -775,6 +778,23 @@ gst_flv_demux_push_tags (GstFlvDemux * demux)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_flv_demux_update_resync (GstFlvDemux * demux, guint32 pts, guint32 * last,
|
||||
GstClockTime * offset)
|
||||
{
|
||||
if (ABS (pts - *last) >= RESYNC_THRESHOLD) {
|
||||
/* Theoretically, we should use substract the duration of the last buffer,
|
||||
but this demuxer sends no durations on buffers, not sure if it cannot
|
||||
know, or just does not care to calculate. */
|
||||
gint32 dpts = pts - *last;
|
||||
*offset -= dpts * GST_MSECOND;
|
||||
GST_WARNING_OBJECT (demux,
|
||||
"Large pts gap (%" G_GINT32_FORMAT " ms), assuming resync, offset now %"
|
||||
GST_TIME_FORMAT "", dpts, GST_TIME_ARGS (*offset));
|
||||
}
|
||||
*last = pts;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_flv_demux_parse_tag_audio (GstFlvDemux * demux, GstBuffer * buffer)
|
||||
{
|
||||
|
@ -969,8 +989,12 @@ gst_flv_demux_parse_tag_audio (GstFlvDemux * demux, GstBuffer * buffer)
|
|||
}
|
||||
}
|
||||
|
||||
/* detect (and deem to be resyncs) large pts gaps */
|
||||
gst_flv_demux_update_resync (demux, pts, &demux->last_audio_pts,
|
||||
&demux->audio_time_offset);
|
||||
|
||||
/* Fill buffer with data */
|
||||
GST_BUFFER_TIMESTAMP (outbuf) = pts * GST_MSECOND;
|
||||
GST_BUFFER_TIMESTAMP (outbuf) = pts * GST_MSECOND + demux->audio_time_offset;
|
||||
GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
|
||||
GST_BUFFER_OFFSET (outbuf) = demux->audio_offset++;
|
||||
GST_BUFFER_OFFSET_END (outbuf) = demux->audio_offset;
|
||||
|
@ -1341,8 +1365,12 @@ gst_flv_demux_parse_tag_video (GstFlvDemux * demux, GstBuffer * buffer)
|
|||
}
|
||||
}
|
||||
|
||||
/* detect (and deem to be resyncs) large pts gaps */
|
||||
gst_flv_demux_update_resync (demux, pts, &demux->last_video_pts,
|
||||
&demux->video_time_offset);
|
||||
|
||||
/* Fill buffer with data */
|
||||
GST_BUFFER_TIMESTAMP (outbuf) = pts * GST_MSECOND;
|
||||
GST_BUFFER_TIMESTAMP (outbuf) = pts * GST_MSECOND + demux->video_time_offset;
|
||||
GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
|
||||
GST_BUFFER_OFFSET (outbuf) = demux->video_offset++;
|
||||
GST_BUFFER_OFFSET_END (outbuf) = demux->video_offset;
|
||||
|
@ -1659,6 +1687,8 @@ gst_flv_demux_cleanup (GstFlvDemux * demux)
|
|||
demux->index_max_time = 0;
|
||||
|
||||
demux->audio_start = demux->video_start = GST_CLOCK_TIME_NONE;
|
||||
demux->last_audio_pts = demux->last_video_pts = 0;
|
||||
demux->audio_time_offset = demux->video_time_offset = 0;
|
||||
|
||||
demux->no_more_pads = FALSE;
|
||||
|
||||
|
|
|
@ -94,6 +94,8 @@ struct _GstFlvDemux
|
|||
gboolean audio_linked;
|
||||
GstBuffer * audio_codec_data;
|
||||
GstClockTime audio_start;
|
||||
guint32 last_audio_pts;
|
||||
GstClockTime audio_time_offset;
|
||||
|
||||
/* Video infos */
|
||||
guint32 w;
|
||||
|
@ -108,6 +110,8 @@ struct _GstFlvDemux
|
|||
gboolean got_par;
|
||||
GstBuffer * video_codec_data;
|
||||
GstClockTime video_start;
|
||||
guint32 last_video_pts;
|
||||
GstClockTime video_time_offset;
|
||||
gdouble framerate;
|
||||
|
||||
gboolean random_access;
|
||||
|
|
|
@ -8831,8 +8831,16 @@ qtdemux_parse_tree (GstQTDemux * qtdemux)
|
|||
/* Moving qt creation time (secs since 1904) to unix time */
|
||||
if (creation_time != 0) {
|
||||
if (creation_time > QTDEMUX_SECONDS_FROM_1904_TO_1970) {
|
||||
GTimeVal now;
|
||||
|
||||
creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
|
||||
datetime = gst_date_time_new_from_unix_epoch_local_time (creation_time);
|
||||
/* some data cleansing sanity */
|
||||
g_get_current_time (&now);
|
||||
if (now.tv_sec + 24 * 3600 < creation_time) {
|
||||
GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
|
||||
} else {
|
||||
datetime = gst_date_time_new_from_unix_epoch_local_time (creation_time);
|
||||
}
|
||||
} else {
|
||||
GST_WARNING_OBJECT (qtdemux, "Can't handle datetimes before 1970 yet, "
|
||||
"please file a bug at http://bugzilla.gnome.org");
|
||||
|
@ -8868,8 +8876,13 @@ qtdemux_parse_tree (GstQTDemux * qtdemux)
|
|||
|
||||
/* set duration in the segment info */
|
||||
gst_qtdemux_get_duration (qtdemux, &duration);
|
||||
if (duration)
|
||||
if (duration) {
|
||||
qtdemux->segment.duration = duration;
|
||||
/* also do not exceed duration; stop is set that way post seek anyway,
|
||||
* and segment activation falls back to duration,
|
||||
* whereas loop only checks stop, so let's align this here as well */
|
||||
qtdemux->segment.stop = duration;
|
||||
}
|
||||
|
||||
/* parse all traks */
|
||||
trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
|
||||
|
|
|
@ -411,10 +411,12 @@ gst_ebml_write_element_push (GstEbmlWrite * ebml, GstBuffer * buf,
|
|||
if (!buf_data)
|
||||
buf_data = GST_BUFFER_DATA (buf);
|
||||
|
||||
if (buf_data_end)
|
||||
if (buf_data_end) {
|
||||
data_size = buf_data_end - buf_data;
|
||||
else
|
||||
GST_BUFFER_SIZE (buf) = data_size;
|
||||
} else {
|
||||
data_size = GST_BUFFER_SIZE (buf);
|
||||
}
|
||||
|
||||
ebml->pos += data_size;
|
||||
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <gst/rtp/gstrtpbuffer.h>
|
||||
|
||||
|
@ -61,9 +63,23 @@ static GstStaticPadTemplate gst_rtp_h263p_pay_sink_template =
|
|||
GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS ("video/x-h263, " "variant = (string) \"itu\" ")
|
||||
GST_STATIC_CAPS ("video/x-h263, " "variant = (string) \"itu\"")
|
||||
);
|
||||
|
||||
/*
|
||||
* We also return these in getcaps() as required by the SDP caps
|
||||
*
|
||||
* width = (int) [16, 4096]
|
||||
* height = (int) [16, 4096]
|
||||
* "annex-f = (boolean) {true, false},"
|
||||
* "annex-i = (boolean) {true, false},"
|
||||
* "annex-j = (boolean) {true, false},"
|
||||
* "annex-l = (boolean) {true, false},"
|
||||
* "annex-t = (boolean) {true, false},"
|
||||
* "annex-v = (boolean) {true, false}")
|
||||
*/
|
||||
|
||||
|
||||
static GstStaticPadTemplate gst_rtp_h263p_pay_src_template =
|
||||
GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
|
@ -87,6 +103,8 @@ static void gst_rtp_h263p_pay_get_property (GObject * object, guint prop_id,
|
|||
|
||||
static gboolean gst_rtp_h263p_pay_setcaps (GstBaseRTPPayload * payload,
|
||||
GstCaps * caps);
|
||||
static GstCaps *gst_rtp_h263p_pay_sink_getcaps (GstBaseRTPPayload * payload,
|
||||
GstPad * pad);
|
||||
static GstFlowReturn gst_rtp_h263p_pay_handle_buffer (GstBaseRTPPayload *
|
||||
payload, GstBuffer * buffer);
|
||||
|
||||
|
@ -109,6 +127,7 @@ gst_rtp_h263p_pay_class_init (GstRtpH263PPayClass * klass)
|
|||
gobject_class->get_property = gst_rtp_h263p_pay_get_property;
|
||||
|
||||
gstbasertppayload_class->set_caps = gst_rtp_h263p_pay_setcaps;
|
||||
gstbasertppayload_class->get_caps = gst_rtp_h263p_pay_sink_getcaps;
|
||||
gstbasertppayload_class->handle_buffer = gst_rtp_h263p_pay_handle_buffer;
|
||||
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass),
|
||||
|
@ -187,6 +206,380 @@ gst_rtp_h263p_pay_setcaps (GstBaseRTPPayload * payload, GstCaps * caps)
|
|||
return res;
|
||||
}
|
||||
|
||||
static void
|
||||
caps_append (GstCaps * caps, GstStructure * in_s, guint x, guint y, guint mpi)
|
||||
{
|
||||
GstStructure *s;
|
||||
|
||||
if (!in_s)
|
||||
return;
|
||||
|
||||
if (mpi < 1 || mpi > 32)
|
||||
return;
|
||||
|
||||
s = gst_structure_copy (in_s);
|
||||
|
||||
gst_structure_set (s,
|
||||
"width", GST_TYPE_INT_RANGE, 1, x,
|
||||
"height", GST_TYPE_INT_RANGE, 1, y,
|
||||
"framerate", GST_TYPE_FRACTION_RANGE, 0, 1, 30000, 1001 * mpi, NULL);
|
||||
|
||||
gst_caps_merge_structure (caps, s);
|
||||
}
|
||||
|
||||
|
||||
static GstCaps *
|
||||
gst_rtp_h263p_pay_sink_getcaps (GstBaseRTPPayload * payload, GstPad * pad)
|
||||
{
|
||||
GstRtpH263PPay *rtph263ppay;
|
||||
GstCaps *caps = gst_caps_new_empty ();
|
||||
GstCaps *peercaps = NULL;
|
||||
GstCaps *intersect = NULL;
|
||||
guint i;
|
||||
|
||||
rtph263ppay = GST_RTP_H263P_PAY (payload);
|
||||
|
||||
peercaps = gst_pad_peer_get_caps (GST_BASE_RTP_PAYLOAD_SRCPAD (payload));
|
||||
if (!peercaps)
|
||||
return
|
||||
gst_caps_copy (gst_pad_get_pad_template_caps
|
||||
(GST_BASE_RTP_PAYLOAD_SINKPAD (payload)));
|
||||
|
||||
intersect = gst_caps_intersect (peercaps,
|
||||
gst_pad_get_pad_template_caps (GST_BASE_RTP_PAYLOAD_SRCPAD (payload)));
|
||||
gst_caps_unref (peercaps);
|
||||
|
||||
if (gst_caps_is_empty (intersect))
|
||||
return intersect;
|
||||
|
||||
for (i = 0; i < gst_caps_get_size (intersect); i++) {
|
||||
GstStructure *s = gst_caps_get_structure (intersect, i);
|
||||
const gchar *encoding_name = gst_structure_get_string (s, "encoding-name");
|
||||
|
||||
if (!strcmp (encoding_name, "H263-2000")) {
|
||||
const gchar *profile_str = gst_structure_get_string (s, "profile");
|
||||
const gchar *level_str = gst_structure_get_string (s, "level");
|
||||
int profile = 0;
|
||||
int level = 0;
|
||||
|
||||
if (profile_str && level_str) {
|
||||
gboolean i = FALSE, j = FALSE, l = FALSE, t = FALSE, f = FALSE,
|
||||
v = FALSE;
|
||||
GstStructure *new_s = gst_structure_new ("video/x-h263",
|
||||
"variant", G_TYPE_STRING, "itu",
|
||||
NULL);
|
||||
|
||||
profile = atoi (profile_str);
|
||||
level = atoi (level_str);
|
||||
|
||||
/* These profiles are defined in the H.263 Annex X */
|
||||
switch (profile) {
|
||||
case 0:
|
||||
/* The Baseline Profile (Profile 0) */
|
||||
break;
|
||||
case 1:
|
||||
/* H.320 Coding Efficiency Version 2 Backward-Compatibility Profile
|
||||
* (Profile 1)
|
||||
* Baseline + Annexes I, J, L.4 and T
|
||||
*/
|
||||
i = j = l = t = TRUE;
|
||||
break;
|
||||
case 2:
|
||||
/* Version 1 Backward-Compatibility Profile (Profile 2)
|
||||
* Baseline + Annex F
|
||||
*/
|
||||
i = j = l = t = f = TRUE;
|
||||
break;
|
||||
case 3:
|
||||
/* Version 2 Interactive and Streaming Wireless Profile
|
||||
* Baseline + Annexes I, J, T
|
||||
*/
|
||||
i = j = t = TRUE;
|
||||
break;
|
||||
case 4:
|
||||
/* Version 3 Interactive and Streaming Wireless Profile (Profile 4)
|
||||
* Baseline + Annexes I, J, T, V, W.6.3.8,
|
||||
*/
|
||||
/* Missing W.6.3.8 */
|
||||
i = j = t = v = TRUE;
|
||||
break;
|
||||
case 5:
|
||||
/* Conversational High Compression Profile (Profile 5)
|
||||
* Baseline + Annexes F, I, J, L.4, T, D, U
|
||||
*/
|
||||
/* Missing D, U */
|
||||
f = i = j = l = t = TRUE;
|
||||
break;
|
||||
case 6:
|
||||
/* Conversational Internet Profile (Profile 6)
|
||||
* Baseline + Annexes F, I, J, L.4, T, D, U and
|
||||
* K with arbitratry slice ordering
|
||||
*/
|
||||
/* Missing D, U, K with arbitratry slice ordering */
|
||||
f = i = j = l = t = TRUE;
|
||||
break;
|
||||
case 7:
|
||||
/* Conversational Interlace Profile (Profile 7)
|
||||
* Baseline + Annexes F, I, J, L.4, T, D, U, W.6.3.11
|
||||
*/
|
||||
/* Missing D, U, W.6.3.11 */
|
||||
f = i = j = l = t = TRUE;
|
||||
break;
|
||||
case 8:
|
||||
/* High Latency Profile (Profile 8)
|
||||
* Baseline + Annexes F, I, J, L.4, T, D, U, P.5, O.1.1 and
|
||||
* K with arbitratry slice ordering
|
||||
*/
|
||||
/* Missing D, U, P.5, O.1.1 */
|
||||
f = i = j = l = t = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (f || i || j || t || l || v) {
|
||||
GValue list = { 0 };
|
||||
GValue vstr = { 0 };
|
||||
|
||||
g_value_init (&list, GST_TYPE_LIST);
|
||||
g_value_init (&vstr, G_TYPE_STRING);
|
||||
|
||||
g_value_set_static_string (&vstr, "h263");
|
||||
gst_value_list_append_value (&list, &vstr);
|
||||
g_value_set_static_string (&vstr, "h263p");
|
||||
gst_value_list_append_value (&list, &vstr);
|
||||
|
||||
if (l || v) {
|
||||
g_value_set_static_string (&vstr, "h263pp");
|
||||
gst_value_list_append_value (&list, &vstr);
|
||||
}
|
||||
g_value_unset (&vstr);
|
||||
|
||||
gst_structure_set_value (new_s, "h263version", &list);
|
||||
g_value_unset (&list);
|
||||
} else {
|
||||
gst_structure_set (new_s, "h263version", G_TYPE_STRING, "h263", NULL);
|
||||
}
|
||||
|
||||
|
||||
if (!f)
|
||||
gst_structure_set (new_s, "annex-f", G_TYPE_BOOLEAN, FALSE, NULL);
|
||||
if (!i)
|
||||
gst_structure_set (new_s, "annex-i", G_TYPE_BOOLEAN, FALSE, NULL);
|
||||
if (!j)
|
||||
gst_structure_set (new_s, "annex-j", G_TYPE_BOOLEAN, FALSE, NULL);
|
||||
if (!t)
|
||||
gst_structure_set (new_s, "annex-t", G_TYPE_BOOLEAN, FALSE, NULL);
|
||||
if (!l)
|
||||
gst_structure_set (new_s, "annex-l", G_TYPE_BOOLEAN, FALSE, NULL);
|
||||
if (!v)
|
||||
gst_structure_set (new_s, "annex-v", G_TYPE_BOOLEAN, FALSE, NULL);
|
||||
|
||||
|
||||
if (level <= 10 || level == 45) {
|
||||
gst_structure_set (new_s,
|
||||
"width", GST_TYPE_INT_RANGE, 1, 176,
|
||||
"height", GST_TYPE_INT_RANGE, 1, 144,
|
||||
"framerate", GST_TYPE_FRACTION_RANGE, 0, 1, 30000, 2002, NULL);
|
||||
gst_caps_merge_structure (caps, new_s);
|
||||
} else if (level <= 20) {
|
||||
GstStructure *s_copy = gst_structure_copy (new_s);
|
||||
|
||||
gst_structure_set (new_s,
|
||||
"width", GST_TYPE_INT_RANGE, 1, 352,
|
||||
"height", GST_TYPE_INT_RANGE, 1, 288,
|
||||
"framerate", GST_TYPE_FRACTION_RANGE, 0, 1, 30000, 2002, NULL);
|
||||
gst_caps_merge_structure (caps, new_s);
|
||||
|
||||
gst_structure_set (s_copy,
|
||||
"width", GST_TYPE_INT_RANGE, 1, 176,
|
||||
"height", GST_TYPE_INT_RANGE, 1, 144,
|
||||
"framerate", GST_TYPE_FRACTION_RANGE, 0, 1, 30000, 1001, NULL);
|
||||
gst_caps_merge_structure (caps, s_copy);
|
||||
} else if (level <= 40) {
|
||||
|
||||
gst_structure_set (new_s,
|
||||
"width", GST_TYPE_INT_RANGE, 1, 352,
|
||||
"height", GST_TYPE_INT_RANGE, 1, 288,
|
||||
"framerate", GST_TYPE_FRACTION_RANGE, 0, 1, 30000, 1001, NULL);
|
||||
gst_caps_merge_structure (caps, new_s);
|
||||
} else if (level <= 50) {
|
||||
GstStructure *s_copy = gst_structure_copy (new_s);
|
||||
|
||||
gst_structure_set (new_s,
|
||||
"width", GST_TYPE_INT_RANGE, 1, 352,
|
||||
"height", GST_TYPE_INT_RANGE, 1, 288,
|
||||
"framerate", GST_TYPE_FRACTION_RANGE, 0, 1, 50, 1, NULL);
|
||||
gst_caps_merge_structure (caps, new_s);
|
||||
|
||||
gst_structure_set (s_copy,
|
||||
"width", GST_TYPE_INT_RANGE, 1, 352,
|
||||
"height", GST_TYPE_INT_RANGE, 1, 240,
|
||||
"framerate", GST_TYPE_FRACTION_RANGE, 0, 1, 60000, 1001, NULL);
|
||||
gst_caps_merge_structure (caps, s_copy);
|
||||
} else if (level <= 60) {
|
||||
GstStructure *s_copy = gst_structure_copy (new_s);
|
||||
|
||||
gst_structure_set (new_s,
|
||||
"width", GST_TYPE_INT_RANGE, 1, 720,
|
||||
"height", GST_TYPE_INT_RANGE, 1, 288,
|
||||
"framerate", GST_TYPE_FRACTION_RANGE, 0, 1, 50, 1, NULL);
|
||||
gst_caps_merge_structure (caps, new_s);
|
||||
|
||||
gst_structure_set (s_copy,
|
||||
"width", GST_TYPE_INT_RANGE, 1, 720,
|
||||
"height", GST_TYPE_INT_RANGE, 1, 240,
|
||||
"framerate", GST_TYPE_FRACTION_RANGE, 0, 1, 60000, 1001, NULL);
|
||||
gst_caps_merge_structure (caps, s_copy);
|
||||
} else if (level <= 70) {
|
||||
GstStructure *s_copy = gst_structure_copy (new_s);
|
||||
|
||||
gst_structure_set (new_s,
|
||||
"width", GST_TYPE_INT_RANGE, 1, 720,
|
||||
"height", GST_TYPE_INT_RANGE, 1, 576,
|
||||
"framerate", GST_TYPE_FRACTION_RANGE, 0, 1, 50, 1, NULL);
|
||||
gst_caps_merge_structure (caps, new_s);
|
||||
|
||||
gst_structure_set (s_copy,
|
||||
"width", GST_TYPE_INT_RANGE, 1, 720,
|
||||
"height", GST_TYPE_INT_RANGE, 1, 480,
|
||||
"framerate", GST_TYPE_FRACTION_RANGE, 0, 1, 60000, 1001, NULL);
|
||||
gst_caps_merge_structure (caps, s_copy);
|
||||
} else {
|
||||
gst_caps_merge_structure (caps, new_s);
|
||||
}
|
||||
|
||||
} else {
|
||||
GstStructure *new_s = gst_structure_new ("video/x-h263",
|
||||
"variant", G_TYPE_STRING, "itu",
|
||||
"h263version", G_TYPE_STRING, "h263",
|
||||
NULL);
|
||||
|
||||
GST_DEBUG_OBJECT (rtph263ppay, "No profile or level specified"
|
||||
" for H263-2000, defaulting to baseline H263");
|
||||
|
||||
gst_caps_merge_structure (caps, new_s);
|
||||
}
|
||||
} else {
|
||||
gboolean f = FALSE, i = FALSE, j = FALSE, t = FALSE;
|
||||
/* FIXME: ffmpeg support the Appendix K too, how do we express it ?
|
||||
* guint k;
|
||||
*/
|
||||
const gchar *str;
|
||||
GstStructure *new_s = gst_structure_new ("video/x-h263",
|
||||
"variant", G_TYPE_STRING, "itu",
|
||||
NULL);
|
||||
gboolean added = FALSE;
|
||||
|
||||
str = gst_structure_get_string (s, "f");
|
||||
if (str && !strcmp (str, "1"))
|
||||
f = TRUE;
|
||||
|
||||
str = gst_structure_get_string (s, "i");
|
||||
if (str && !strcmp (str, "1"))
|
||||
i = TRUE;
|
||||
|
||||
str = gst_structure_get_string (s, "j");
|
||||
if (str && !strcmp (str, "1"))
|
||||
j = TRUE;
|
||||
|
||||
str = gst_structure_get_string (s, "t");
|
||||
if (str && !strcmp (str, "1"))
|
||||
t = TRUE;
|
||||
|
||||
if (f || i || j || t) {
|
||||
GValue list = { 0 };
|
||||
GValue vstr = { 0 };
|
||||
|
||||
g_value_init (&list, GST_TYPE_LIST);
|
||||
g_value_init (&vstr, G_TYPE_STRING);
|
||||
|
||||
g_value_set_static_string (&vstr, "h263");
|
||||
gst_value_list_append_value (&list, &vstr);
|
||||
g_value_set_static_string (&vstr, "h263p");
|
||||
gst_value_list_append_value (&list, &vstr);
|
||||
g_value_unset (&vstr);
|
||||
|
||||
gst_structure_set_value (new_s, "h263version", &list);
|
||||
g_value_unset (&list);
|
||||
} else {
|
||||
gst_structure_set (new_s, "h263version", G_TYPE_STRING, "h263", NULL);
|
||||
}
|
||||
|
||||
if (!f)
|
||||
gst_structure_set (new_s, "annex-f", G_TYPE_BOOLEAN, FALSE, NULL);
|
||||
if (!i)
|
||||
gst_structure_set (new_s, "annex-i", G_TYPE_BOOLEAN, FALSE, NULL);
|
||||
if (!j)
|
||||
gst_structure_set (new_s, "annex-j", G_TYPE_BOOLEAN, FALSE, NULL);
|
||||
if (!t)
|
||||
gst_structure_set (new_s, "annex-t", G_TYPE_BOOLEAN, FALSE, NULL);
|
||||
|
||||
|
||||
str = gst_structure_get_string (s, "custom");
|
||||
if (str) {
|
||||
unsigned int xmax, ymax, mpi;
|
||||
if (sscanf (str, "%u,%u,%u", &xmax, &ymax, &mpi) == 3) {
|
||||
if (xmax % 4 && ymax % 4 && mpi >= 1 && mpi <= 32) {
|
||||
caps_append (caps, new_s, xmax, ymax, mpi);
|
||||
added = TRUE;
|
||||
} else {
|
||||
GST_WARNING_OBJECT (rtph263ppay, "Invalid custom framesize/MPI"
|
||||
" %u x %u at %u, ignoring", xmax, ymax, mpi);
|
||||
}
|
||||
} else {
|
||||
GST_WARNING_OBJECT (rtph263ppay, "Invalid custom framesize/MPI: %s,"
|
||||
" ignoring", str);
|
||||
}
|
||||
}
|
||||
|
||||
str = gst_structure_get_string (s, "16cif");
|
||||
if (str) {
|
||||
int mpi = atoi (str);
|
||||
caps_append (caps, new_s, 1408, 1152, mpi);
|
||||
added = TRUE;
|
||||
}
|
||||
|
||||
str = gst_structure_get_string (s, "4cif");
|
||||
if (str) {
|
||||
int mpi = atoi (str);
|
||||
caps_append (caps, new_s, 704, 576, mpi);
|
||||
added = TRUE;
|
||||
}
|
||||
|
||||
str = gst_structure_get_string (s, "cif");
|
||||
if (str) {
|
||||
int mpi = atoi (str);
|
||||
caps_append (caps, new_s, 352, 288, mpi);
|
||||
added = TRUE;
|
||||
}
|
||||
|
||||
str = gst_structure_get_string (s, "qcif");
|
||||
if (str) {
|
||||
int mpi = atoi (str);
|
||||
caps_append (caps, new_s, 176, 144, mpi);
|
||||
added = TRUE;
|
||||
}
|
||||
|
||||
str = gst_structure_get_string (s, "sqcif");
|
||||
if (str) {
|
||||
int mpi = atoi (str);
|
||||
caps_append (caps, new_s, 128, 96, mpi);
|
||||
added = TRUE;
|
||||
}
|
||||
|
||||
if (added)
|
||||
gst_structure_free (new_s);
|
||||
else
|
||||
gst_caps_merge_structure (caps, new_s);
|
||||
}
|
||||
}
|
||||
|
||||
gst_caps_unref (intersect);
|
||||
|
||||
return caps;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gst_rtp_h263p_pay_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
|
|
Loading…
Reference in a new issue