mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 20:21:24 +00:00
Merge branch 'master' into 0.11
Conflicts: ext/ogg/gstoggmux.c ext/vorbis/gstvorbisenc.c
This commit is contained in:
commit
232a5a3d0a
5 changed files with 223 additions and 54 deletions
|
@ -491,8 +491,13 @@ gst_ogg_demux_chain_peer (GstOggPad * pad, ogg_packet * packet,
|
|||
}
|
||||
|
||||
/* get timing info for the packet */
|
||||
duration = gst_ogg_stream_get_packet_duration (&pad->map, packet);
|
||||
GST_DEBUG_OBJECT (ogg, "packet duration %" G_GUINT64_FORMAT, duration);
|
||||
if (gst_ogg_stream_packet_is_header (&pad->map, packet)) {
|
||||
duration = 0;
|
||||
GST_DEBUG_OBJECT (ogg, "packet is header");
|
||||
} else {
|
||||
duration = gst_ogg_stream_get_packet_duration (&pad->map, packet);
|
||||
GST_DEBUG_OBJECT (ogg, "packet duration %" G_GUINT64_FORMAT, duration);
|
||||
}
|
||||
|
||||
if (packet->b_o_s) {
|
||||
out_timestamp = GST_CLOCK_TIME_NONE;
|
||||
|
@ -671,13 +676,18 @@ gst_ogg_demux_collect_start_time (GstOggDemux * ogg, GstOggChain * chain)
|
|||
for (i = 0; i < chain->streams->len; i++) {
|
||||
GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i);
|
||||
|
||||
if (pad->map.is_sparse)
|
||||
if (pad->map.is_skeleton)
|
||||
continue;
|
||||
|
||||
/* can do this if the pad start time is not defined */
|
||||
GST_DEBUG_OBJECT (ogg, "Pad %08x (%s) start time is %" GST_TIME_FORMAT,
|
||||
pad->map.serialno, gst_ogg_stream_get_media_type (&pad->map),
|
||||
GST_TIME_ARGS (pad->start_time));
|
||||
if (pad->start_time == GST_CLOCK_TIME_NONE) {
|
||||
start_time = G_MAXUINT64;
|
||||
break;
|
||||
if (!pad->map.is_sparse) {
|
||||
start_time = G_MAXUINT64;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
start_time = MIN (start_time, pad->start_time);
|
||||
}
|
||||
|
@ -734,7 +744,7 @@ gst_ogg_pad_submit_packet (GstOggPad * pad, ogg_packet * packet)
|
|||
if (gst_ogg_map_parse_fisbone (&pad->map, packet->packet, packet->bytes,
|
||||
&serialno, &type)) {
|
||||
|
||||
GST_WARNING_OBJECT (pad->ogg,
|
||||
GST_DEBUG_OBJECT (pad->ogg,
|
||||
"got skeleton packet for stream 0x%08x", serialno);
|
||||
|
||||
skel_pad = gst_ogg_chain_get_stream (pad->chain, serialno);
|
||||
|
@ -2626,7 +2636,7 @@ gst_ogg_demux_read_chain (GstOggDemux * ogg, GstOggChain ** res_chain)
|
|||
GstFlowReturn ret;
|
||||
GstOggChain *chain = NULL;
|
||||
gint64 offset = ogg->offset;
|
||||
ogg_page op;
|
||||
ogg_page og;
|
||||
gboolean done;
|
||||
gint i;
|
||||
|
||||
|
@ -2638,17 +2648,23 @@ gst_ogg_demux_read_chain (GstOggDemux * ogg, GstOggChain ** res_chain)
|
|||
GstOggPad *pad;
|
||||
guint32 serial;
|
||||
|
||||
ret = gst_ogg_demux_get_next_page (ogg, &op, -1, NULL);
|
||||
ret = gst_ogg_demux_get_next_page (ogg, &og, -1, NULL);
|
||||
if (ret != GST_FLOW_OK) {
|
||||
GST_WARNING_OBJECT (ogg, "problem reading BOS page: ret=%d", ret);
|
||||
if (ret == GST_FLOW_UNEXPECTED) {
|
||||
GST_DEBUG_OBJECT (ogg, "Reached EOS, done reading end chain");
|
||||
} else {
|
||||
GST_WARNING_OBJECT (ogg, "problem reading BOS page: ret=%d", ret);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!ogg_page_bos (&op)) {
|
||||
GST_WARNING_OBJECT (ogg, "page is not BOS page");
|
||||
if (!ogg_page_bos (&og)) {
|
||||
GST_INFO_OBJECT (ogg, "page is not BOS page, all streams identified");
|
||||
/* if we did not find a chain yet, assume this is a bogus stream and
|
||||
* ignore it */
|
||||
if (!chain)
|
||||
if (!chain) {
|
||||
GST_WARNING_OBJECT (ogg, "No chain found, no Ogg data in stream ?");
|
||||
ret = GST_FLOW_UNEXPECTED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2657,7 +2673,7 @@ gst_ogg_demux_read_chain (GstOggDemux * ogg, GstOggChain ** res_chain)
|
|||
chain->offset = offset;
|
||||
}
|
||||
|
||||
serial = ogg_page_serialno (&op);
|
||||
serial = ogg_page_serialno (&og);
|
||||
if (gst_ogg_chain_get_stream (chain, serial) != NULL) {
|
||||
GST_WARNING_OBJECT (ogg,
|
||||
"found serial %08x BOS page twice, ignoring", serial);
|
||||
|
@ -2665,7 +2681,7 @@ gst_ogg_demux_read_chain (GstOggDemux * ogg, GstOggChain ** res_chain)
|
|||
}
|
||||
|
||||
pad = gst_ogg_chain_new_stream (chain, serial);
|
||||
gst_ogg_pad_submit_page (pad, &op);
|
||||
gst_ogg_pad_submit_page (pad, &og);
|
||||
}
|
||||
|
||||
if (ret != GST_FLOW_OK || chain == NULL) {
|
||||
|
@ -2704,7 +2720,7 @@ gst_ogg_demux_read_chain (GstOggDemux * ogg, GstOggChain ** res_chain)
|
|||
gboolean known_serial = FALSE;
|
||||
GstFlowReturn ret;
|
||||
|
||||
serial = ogg_page_serialno (&op);
|
||||
serial = ogg_page_serialno (&og);
|
||||
done = TRUE;
|
||||
for (i = 0; i < chain->streams->len; i++) {
|
||||
GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i);
|
||||
|
@ -2718,10 +2734,10 @@ gst_ogg_demux_read_chain (GstOggDemux * ogg, GstOggChain ** res_chain)
|
|||
|
||||
/* submit the page now, this will fill in the start_time when the
|
||||
* internal decoder finds it */
|
||||
gst_ogg_pad_submit_page (pad, &op);
|
||||
gst_ogg_pad_submit_page (pad, &og);
|
||||
|
||||
if (!pad->map.is_skeleton && pad->start_time == -1
|
||||
&& ogg_page_eos (&op)) {
|
||||
&& ogg_page_eos (&og)) {
|
||||
/* got EOS on a pad before we could find its start_time.
|
||||
* We have no chance of finding a start_time for every pad so
|
||||
* stop searching for the other start_time(s).
|
||||
|
@ -2747,7 +2763,7 @@ gst_ogg_demux_read_chain (GstOggDemux * ogg, GstOggChain ** res_chain)
|
|||
}
|
||||
|
||||
if (!done) {
|
||||
ret = gst_ogg_demux_get_next_page (ogg, &op, -1, NULL);
|
||||
ret = gst_ogg_demux_get_next_page (ogg, &og, -1, NULL);
|
||||
if (ret != GST_FLOW_OK)
|
||||
break;
|
||||
}
|
||||
|
@ -2805,7 +2821,7 @@ gst_ogg_demux_read_end_chain (GstOggDemux * ogg, GstOggChain * chain)
|
|||
for (i = 0; i < chain->streams->len; i++) {
|
||||
GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i);
|
||||
|
||||
if (pad->map.is_sparse)
|
||||
if (pad->map.is_skeleton)
|
||||
continue;
|
||||
|
||||
if (pad->map.serialno == ogg_page_serialno (&og)) {
|
||||
|
@ -3677,7 +3693,8 @@ gst_ogg_print (GstOggDemux * ogg)
|
|||
for (j = 0; j < chain->streams->len; j++) {
|
||||
GstOggPad *stream = g_array_index (chain->streams, GstOggPad *, j);
|
||||
|
||||
GST_INFO_OBJECT (ogg, " stream %08x:", stream->map.serialno);
|
||||
GST_INFO_OBJECT (ogg, " stream %08x: %s", stream->map.serialno,
|
||||
gst_ogg_stream_get_media_type (&stream->map));
|
||||
GST_INFO_OBJECT (ogg, " start time: %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (stream->start_time));
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/base/gstcollectpads.h>
|
||||
#include <gst/base/gstbytewriter.h>
|
||||
#include <gst/tag/tag.h>
|
||||
|
||||
#include "gstoggmux.h"
|
||||
|
@ -83,12 +84,15 @@ enum
|
|||
#define DEFAULT_MAX_DELAY G_GINT64_CONSTANT(500000000)
|
||||
#define DEFAULT_MAX_PAGE_DELAY G_GINT64_CONSTANT(500000000)
|
||||
#define DEFAULT_MAX_TOLERANCE G_GINT64_CONSTANT(40000000)
|
||||
#define DEFAULT_SKELETON FALSE
|
||||
|
||||
enum
|
||||
{
|
||||
ARG_0,
|
||||
ARG_MAX_DELAY,
|
||||
ARG_MAX_PAGE_DELAY,
|
||||
ARG_MAX_TOLERANCE
|
||||
ARG_MAX_TOLERANCE,
|
||||
ARG_SKELETON
|
||||
};
|
||||
|
||||
static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
|
||||
|
@ -169,6 +173,11 @@ gst_ogg_mux_class_init (GstOggMuxClass * klass)
|
|||
"Maximum timestamp difference for maintaining perfect granules",
|
||||
0, G_MAXUINT64, DEFAULT_MAX_TOLERANCE,
|
||||
(GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
g_object_class_install_property (gobject_class, ARG_SKELETON,
|
||||
g_param_spec_boolean ("skeleton", "Skeleton",
|
||||
"Whether to include a Skeleton track",
|
||||
DEFAULT_SKELETON,
|
||||
(GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
gstelement_class->change_state = gst_ogg_mux_change_state;
|
||||
|
||||
|
@ -1075,14 +1084,103 @@ gst_ogg_mux_set_header_on_caps (GstCaps * caps, GList * buffers)
|
|||
}
|
||||
|
||||
static void
|
||||
create_header_packet (ogg_packet * packet, GstOggPadData * pad)
|
||||
gst_ogg_mux_create_header_packet_with_flags (ogg_packet * packet,
|
||||
gboolean bos, gboolean eos)
|
||||
{
|
||||
packet->granulepos = 0;
|
||||
/* mark BOS and packet number */
|
||||
packet->b_o_s = (pad->packetno == 0);
|
||||
packet->packetno = pad->packetno++;
|
||||
packet->b_o_s = bos;
|
||||
/* mark EOS */
|
||||
packet->e_o_s = 0;
|
||||
packet->e_o_s = eos;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_ogg_mux_create_header_packet (ogg_packet * packet, GstOggPadData * pad)
|
||||
{
|
||||
gst_ogg_mux_create_header_packet_with_flags (packet, pad->packetno == 0, 0);
|
||||
packet->packetno = pad->packetno++;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_ogg_mux_submit_skeleton_header_packet (GstOggMux * mux,
|
||||
ogg_stream_state * os, GstBuffer * buf, gboolean bos, gboolean eos)
|
||||
{
|
||||
ogg_packet packet;
|
||||
gsize size;
|
||||
|
||||
packet.packet = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
|
||||
packet.bytes = size;
|
||||
gst_ogg_mux_create_header_packet_with_flags (&packet, bos, eos);
|
||||
ogg_stream_packetin (os, &packet);
|
||||
gst_buffer_unref (buf);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_ogg_mux_make_fishead (GstOggMux * mux, ogg_stream_state * os)
|
||||
{
|
||||
GstByteWriter bw;
|
||||
GstBuffer *fishead;
|
||||
|
||||
GST_DEBUG_OBJECT (mux, "Creating fishead");
|
||||
|
||||
gst_byte_writer_init_with_size (&bw, 64, TRUE);
|
||||
gst_byte_writer_put_string_utf8 (&bw, "fishead");
|
||||
gst_byte_writer_put_int16_le (&bw, 3); /* version major */
|
||||
gst_byte_writer_put_int16_le (&bw, 0); /* version minor */
|
||||
gst_byte_writer_put_int64_le (&bw, 0); /* presentation time numerator */
|
||||
gst_byte_writer_put_int64_le (&bw, 1000); /* ...and denominator */
|
||||
gst_byte_writer_put_int64_le (&bw, 0); /* base time numerator */
|
||||
gst_byte_writer_put_int64_le (&bw, 1000); /* ...and denominator */
|
||||
gst_byte_writer_fill (&bw, ' ', 20); /* UTC time */
|
||||
g_assert (gst_byte_writer_get_pos (&bw) == 64);
|
||||
fishead = gst_byte_writer_reset_and_get_buffer (&bw);
|
||||
gst_ogg_mux_submit_skeleton_header_packet (mux, os, fishead, 1, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_ogg_mux_byte_writer_put_string_utf8 (GstByteWriter * bw, const char *s)
|
||||
{
|
||||
gst_byte_writer_put_data (bw, (const guint8 *) s, strlen (s));
|
||||
}
|
||||
|
||||
static void
|
||||
gst_ogg_mux_make_fisbone (GstOggMux * mux, ogg_stream_state * os,
|
||||
GstOggPadData * pad)
|
||||
{
|
||||
GstByteWriter bw;
|
||||
|
||||
GST_DEBUG_OBJECT (mux,
|
||||
"Creating %s fisbone for serial %08x",
|
||||
gst_ogg_stream_get_media_type (&pad->map), pad->map.serialno);
|
||||
|
||||
gst_byte_writer_init (&bw);
|
||||
gst_byte_writer_put_string_utf8 (&bw, "fisbone");
|
||||
gst_byte_writer_put_int32_le (&bw, 44); /* offset to message headers */
|
||||
gst_byte_writer_put_uint32_le (&bw, pad->map.serialno);
|
||||
gst_byte_writer_put_uint32_le (&bw, pad->map.n_header_packets);
|
||||
gst_byte_writer_put_uint64_le (&bw, pad->map.granulerate_n);
|
||||
gst_byte_writer_put_uint64_le (&bw, pad->map.granulerate_d);
|
||||
gst_byte_writer_put_uint64_le (&bw, 0); /* base granule */
|
||||
gst_byte_writer_put_uint32_le (&bw, pad->map.preroll);
|
||||
gst_byte_writer_put_uint8 (&bw, pad->map.granuleshift);
|
||||
gst_byte_writer_fill (&bw, 0, 3); /* padding */
|
||||
/* message header fields - MIME type for now */
|
||||
gst_ogg_mux_byte_writer_put_string_utf8 (&bw, "Content-Type: ");
|
||||
gst_ogg_mux_byte_writer_put_string_utf8 (&bw,
|
||||
gst_ogg_stream_get_media_type (&pad->map));
|
||||
gst_ogg_mux_byte_writer_put_string_utf8 (&bw, "\r\n");
|
||||
|
||||
gst_ogg_mux_submit_skeleton_header_packet (mux, os,
|
||||
gst_byte_writer_reset_and_get_buffer (&bw), 0, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_ogg_mux_make_fistail (GstOggMux * mux, ogg_stream_state * os)
|
||||
{
|
||||
GST_DEBUG_OBJECT (mux, "Creating fistail");
|
||||
|
||||
gst_ogg_mux_submit_skeleton_header_packet (mux, os,
|
||||
gst_buffer_new_and_alloc (0), 0, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1100,6 +1198,8 @@ gst_ogg_mux_send_headers (GstOggMux * mux)
|
|||
GList *hbufs, *hwalk;
|
||||
GstCaps *caps;
|
||||
GstFlowReturn ret;
|
||||
ogg_page page;
|
||||
ogg_stream_state skeleton_stream;
|
||||
|
||||
hbufs = NULL;
|
||||
ret = GST_FLOW_OK;
|
||||
|
@ -1132,7 +1232,6 @@ gst_ogg_mux_send_headers (GstOggMux * mux)
|
|||
GstOggPadData *pad;
|
||||
GstBuffer *buf;
|
||||
ogg_packet packet;
|
||||
ogg_page page;
|
||||
GstPad *thepad;
|
||||
GstCaps *caps;
|
||||
GstStructure *structure;
|
||||
|
@ -1169,7 +1268,7 @@ gst_ogg_mux_send_headers (GstOggMux * mux)
|
|||
packet.packet = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
|
||||
packet.bytes = size;
|
||||
|
||||
create_header_packet (&packet, pad);
|
||||
gst_ogg_mux_create_header_packet (&packet, pad);
|
||||
|
||||
/* swap the packet in */
|
||||
ogg_stream_packetin (&pad->map.stream, &packet);
|
||||
|
@ -1203,6 +1302,16 @@ gst_ogg_mux_send_headers (GstOggMux * mux)
|
|||
gst_caps_unref (caps);
|
||||
}
|
||||
|
||||
/* The Skeleton BOS goes first - even before the video that went first before */
|
||||
if (mux->use_skeleton) {
|
||||
ogg_stream_init (&skeleton_stream, gst_ogg_mux_generate_serialno (mux));
|
||||
gst_ogg_mux_make_fishead (mux, &skeleton_stream);
|
||||
while (ogg_stream_flush (&skeleton_stream, &page) > 0) {
|
||||
GstBuffer *hbuf = gst_ogg_mux_buffer_from_page (mux, &page, FALSE);
|
||||
hbufs = g_list_append (hbufs, hbuf);
|
||||
}
|
||||
}
|
||||
|
||||
GST_LOG_OBJECT (mux, "creating next headers");
|
||||
walk = mux->collect->data;
|
||||
while (walk) {
|
||||
|
@ -1214,6 +1323,9 @@ gst_ogg_mux_send_headers (GstOggMux * mux)
|
|||
|
||||
walk = walk->next;
|
||||
|
||||
if (mux->use_skeleton)
|
||||
gst_ogg_mux_make_fisbone (mux, &skeleton_stream, pad);
|
||||
|
||||
GST_LOG_OBJECT (mux, "looping over headers for pad %s:%s",
|
||||
GST_DEBUG_PAD_NAME (thepad));
|
||||
|
||||
|
@ -1230,7 +1342,7 @@ gst_ogg_mux_send_headers (GstOggMux * mux)
|
|||
packet.packet = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
|
||||
packet.bytes = size;
|
||||
|
||||
create_header_packet (&packet, pad);
|
||||
gst_ogg_mux_create_header_packet (&packet, pad);
|
||||
|
||||
/* swap the packet in */
|
||||
ogg_stream_packetin (&pad->map.stream, &packet);
|
||||
|
@ -1262,6 +1374,21 @@ gst_ogg_mux_send_headers (GstOggMux * mux)
|
|||
g_list_free (pad->map.headers);
|
||||
pad->map.headers = NULL;
|
||||
}
|
||||
|
||||
if (mux->use_skeleton) {
|
||||
/* flush accumulated fisbones, the fistail must be on a separate page */
|
||||
while (ogg_stream_flush (&skeleton_stream, &page) > 0) {
|
||||
GstBuffer *hbuf = gst_ogg_mux_buffer_from_page (mux, &page, FALSE);
|
||||
hbufs = g_list_append (hbufs, hbuf);
|
||||
}
|
||||
gst_ogg_mux_make_fistail (mux, &skeleton_stream);
|
||||
while (ogg_stream_flush (&skeleton_stream, &page) > 0) {
|
||||
GstBuffer *hbuf = gst_ogg_mux_buffer_from_page (mux, &page, FALSE);
|
||||
hbufs = g_list_append (hbufs, hbuf);
|
||||
}
|
||||
ogg_stream_clear (&skeleton_stream);
|
||||
}
|
||||
|
||||
/* hbufs holds all buffers for the headers now */
|
||||
|
||||
/* create caps with the buffers */
|
||||
|
@ -1706,6 +1833,9 @@ gst_ogg_mux_get_property (GObject * object,
|
|||
case ARG_MAX_TOLERANCE:
|
||||
g_value_set_uint64 (value, ogg_mux->max_tolerance);
|
||||
break;
|
||||
case ARG_SKELETON:
|
||||
g_value_set_boolean (value, ogg_mux->use_skeleton);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -1730,6 +1860,9 @@ gst_ogg_mux_set_property (GObject * object,
|
|||
case ARG_MAX_TOLERANCE:
|
||||
ogg_mux->max_tolerance = g_value_get_uint64 (value);
|
||||
break;
|
||||
case ARG_SKELETON:
|
||||
ogg_mux->use_skeleton = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
|
|
@ -127,6 +127,9 @@ struct _GstOggMux
|
|||
pages as delta frames up to the page that has the
|
||||
keyframe */
|
||||
|
||||
|
||||
/* whether to create a skeleton track */
|
||||
gboolean use_skeleton;
|
||||
};
|
||||
|
||||
struct _GstOggMuxClass
|
||||
|
|
|
@ -139,7 +139,8 @@ gst_ogg_stream_granulepos_to_granule (GstOggStream * pad, gint64 granulepos)
|
|||
}
|
||||
|
||||
if (mappers[pad->map].granulepos_to_granule_func == NULL) {
|
||||
GST_WARNING ("Failed to convert granulepos to granule");
|
||||
GST_WARNING ("Failed to convert %s granulepos to granule",
|
||||
gst_ogg_stream_get_media_type (pad));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -168,7 +169,8 @@ gst_ogg_stream_granule_to_granulepos (GstOggStream * pad, gint64 granule,
|
|||
}
|
||||
|
||||
if (mappers[pad->map].granule_to_granulepos_func == NULL) {
|
||||
GST_WARNING ("Failed to convert granule to granulepos");
|
||||
GST_WARNING ("Failed to convert %s granule to granulepos",
|
||||
gst_ogg_stream_get_media_type (pad));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -184,7 +186,8 @@ gst_ogg_stream_granulepos_is_key_frame (GstOggStream * pad, gint64 granulepos)
|
|||
}
|
||||
|
||||
if (mappers[pad->map].is_key_frame_func == NULL) {
|
||||
GST_WARNING ("Failed to determine key frame");
|
||||
GST_WARNING ("Failed to determine keyframeness for %s granulepos",
|
||||
gst_ogg_stream_get_media_type (pad));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -195,7 +198,8 @@ gboolean
|
|||
gst_ogg_stream_packet_is_header (GstOggStream * pad, ogg_packet * packet)
|
||||
{
|
||||
if (mappers[pad->map].is_header_func == NULL) {
|
||||
GST_WARNING ("Failed to determine header");
|
||||
GST_WARNING ("Failed to determine headerness of %s packet",
|
||||
gst_ogg_stream_get_media_type (pad));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -206,7 +210,8 @@ gint64
|
|||
gst_ogg_stream_get_packet_duration (GstOggStream * pad, ogg_packet * packet)
|
||||
{
|
||||
if (mappers[pad->map].packet_duration_func == NULL) {
|
||||
GST_WARNING ("Failed to determine packet duration");
|
||||
GST_WARNING ("Failed to determine %s packet duration",
|
||||
gst_ogg_stream_get_media_type (pad));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1087,7 +1092,7 @@ setup_fishead_mapper (GstOggStream * pad, ogg_packet * packet)
|
|||
pad->is_skeleton = TRUE;
|
||||
pad->is_sparse = TRUE;
|
||||
|
||||
pad->caps = gst_caps_new_simple ("none/none", NULL);
|
||||
pad->caps = gst_caps_new_simple ("application/x-ogg-skeleton", NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -1099,12 +1104,15 @@ gst_ogg_map_parse_fisbone (GstOggStream * pad, const guint8 * data, guint size,
|
|||
GstOggSkeleton stype;
|
||||
guint serial_offset;
|
||||
|
||||
if (size < SKELETON_FISBONE_MIN_SIZE) {
|
||||
if (size != 0 && size < SKELETON_FISBONE_MIN_SIZE) {
|
||||
GST_WARNING ("small fisbone packet of size %d, ignoring", size);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (memcmp (data, "fisbone\0", 8) == 0) {
|
||||
if (size == 0) {
|
||||
/* Skeleton EOS packet is zero bytes */
|
||||
return FALSE;
|
||||
} else if (memcmp (data, "fisbone\0", 8) == 0) {
|
||||
GST_INFO ("got fisbone packet");
|
||||
stype = GST_OGG_SKELETON_FISBONE;
|
||||
serial_offset = 12;
|
||||
|
|
|
@ -1000,12 +1000,12 @@ gst_vorbis_enc_buffer_check_discontinuous (GstVorbisEnc * vorbisenc,
|
|||
vorbisenc->expected_ts != GST_CLOCK_TIME_NONE &&
|
||||
timestamp + duration != vorbisenc->expected_ts) {
|
||||
/* It turns out that a lot of elements don't generate perfect streams due
|
||||
* to rounding errors. So, we permit small errors (< 1/2 a sample) without
|
||||
* to rounding errors. So, we permit small errors (< 3 samples) without
|
||||
* causing a discont.
|
||||
*/
|
||||
int halfsample = GST_SECOND / vorbisenc->frequency / 2;
|
||||
int threesample = GST_SECOND / vorbisenc->frequency * 3;
|
||||
|
||||
if ((GstClockTimeDiff) (timestamp - vorbisenc->expected_ts) > halfsample) {
|
||||
if ((GstClockTimeDiff) (timestamp - vorbisenc->expected_ts) > threesample) {
|
||||
GST_DEBUG_OBJECT (vorbisenc, "Expected TS %" GST_TIME_FORMAT
|
||||
", buffer TS %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (vorbisenc->expected_ts), GST_TIME_ARGS (timestamp));
|
||||
|
@ -1119,30 +1119,38 @@ gst_vorbis_enc_chain (GstPad * pad, GstBuffer * buffer)
|
|||
|
||||
if (vorbisenc->expected_ts != GST_CLOCK_TIME_NONE &&
|
||||
timestamp < vorbisenc->expected_ts) {
|
||||
int threesample = GST_SECOND / vorbisenc->frequency * 3;
|
||||
guint64 diff = vorbisenc->expected_ts - timestamp;
|
||||
guint64 diff_bytes;
|
||||
gsize size;
|
||||
|
||||
GST_WARNING_OBJECT (vorbisenc, "Buffer is older than previous "
|
||||
"timestamp + duration (%" GST_TIME_FORMAT "< %" GST_TIME_FORMAT
|
||||
"), cannot handle. Clipping buffer.",
|
||||
GST_TIME_ARGS (timestamp), GST_TIME_ARGS (vorbisenc->expected_ts));
|
||||
/* Don't freak out on tiny jitters; use the same < 3 sample
|
||||
tolerance as in the discontinuous detection */
|
||||
if ((GstClockTimeDiff) (vorbisenc->expected_ts - timestamp) > threesample) {
|
||||
|
||||
size = gst_buffer_get_size (buffer);
|
||||
GST_WARNING_OBJECT (vorbisenc, "Buffer is older than previous "
|
||||
"timestamp + duration (%" GST_TIME_FORMAT "< %" GST_TIME_FORMAT
|
||||
"), cannot handle. Clipping buffer.",
|
||||
GST_TIME_ARGS (timestamp), GST_TIME_ARGS (vorbisenc->expected_ts));
|
||||
|
||||
diff_bytes =
|
||||
GST_CLOCK_TIME_TO_FRAMES (diff,
|
||||
vorbisenc->frequency) * vorbisenc->channels * sizeof (gfloat);
|
||||
if (diff_bytes >= size) {
|
||||
gst_buffer_unref (buffer);
|
||||
return GST_FLOW_OK;
|
||||
size = gst_buffer_get_size (buffer);
|
||||
|
||||
diff_bytes =
|
||||
GST_CLOCK_TIME_TO_FRAMES (diff,
|
||||
vorbisenc->frequency) * vorbisenc->channels * sizeof (gfloat);
|
||||
if (diff_bytes >= size) {
|
||||
gst_buffer_unref (buffer);
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
buffer = gst_buffer_make_writable (buffer);
|
||||
gst_buffer_resize (buffer, diff_bytes, size - diff_bytes);
|
||||
|
||||
if (GST_BUFFER_DURATION_IS_VALID (buffer))
|
||||
GST_BUFFER_DURATION (buffer) -= diff;
|
||||
}
|
||||
buffer = gst_buffer_make_writable (buffer);
|
||||
gst_buffer_resize (buffer, diff_bytes, size - diff_bytes);
|
||||
|
||||
/* adjust the input timestamp in either case */
|
||||
GST_BUFFER_TIMESTAMP (buffer) += diff;
|
||||
if (GST_BUFFER_DURATION_IS_VALID (buffer))
|
||||
GST_BUFFER_DURATION (buffer) -= diff;
|
||||
}
|
||||
|
||||
if (gst_vorbis_enc_buffer_check_discontinuous (vorbisenc, timestamp,
|
||||
|
|
Loading…
Reference in a new issue