mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-26 10:10:32 +00:00
oggmux: create vp8 header data if not provided in caps
vp8 stream header shouldn't be assumed to be provided in caps always as this would repeat the same code in all demuxers/encoders. Instead, make oggmux generate them if they are not supplied. https://bugzilla.gnome.org/show_bug.cgi?id=722682
This commit is contained in:
parent
0b30fdbfbe
commit
e00c306571
3 changed files with 167 additions and 10 deletions
|
@ -1008,6 +1008,11 @@ gst_ogg_mux_queue_pads (GstOggMux * ogg_mux, gboolean * popped)
|
|||
/* fallback on the packet */
|
||||
pad->have_type = gst_ogg_stream_setup_map (&pad->map, &packet);
|
||||
}
|
||||
if (!pad->have_type) {
|
||||
/* fallback 2 to try to get the mapping from the caps */
|
||||
pad->have_type =
|
||||
gst_ogg_stream_setup_map_from_caps (&pad->map, caps);
|
||||
}
|
||||
if (!pad->have_type) {
|
||||
GST_ERROR_OBJECT (data->pad,
|
||||
"mapper didn't recognise input stream " "(pad caps: %"
|
||||
|
@ -1097,6 +1102,7 @@ gst_ogg_mux_get_headers (GstOggPadData * pad)
|
|||
GstCaps *caps;
|
||||
const GValue *streamheader;
|
||||
GstPad *thepad;
|
||||
GstBuffer *header;
|
||||
|
||||
thepad = pad->collect.pad;
|
||||
|
||||
|
@ -1138,6 +1144,9 @@ gst_ogg_mux_get_headers (GstOggPadData * pad)
|
|||
} else if (gst_structure_has_name (structure, "video/x-dirac")) {
|
||||
res = g_list_append (res, pad->buffer);
|
||||
pad->buffer = NULL;
|
||||
} else if (pad->have_type
|
||||
&& (header = gst_ogg_stream_get_headers (&pad->map))) {
|
||||
res = g_list_append (res, header);
|
||||
} else {
|
||||
GST_LOG_OBJECT (thepad, "caps don't have streamheader");
|
||||
}
|
||||
|
|
|
@ -40,6 +40,8 @@ typedef struct _GstOggMap GstOggMap;
|
|||
|
||||
typedef gboolean (*GstOggMapSetupFunc) (GstOggStream * pad,
|
||||
ogg_packet * packet);
|
||||
typedef gboolean (*GstOggMapSetupFromCapsFunc) (GstOggStream * pad,
|
||||
const GstCaps * caps);
|
||||
typedef GstClockTime (*GstOggMapToTimeFunc) (GstOggStream * pad,
|
||||
gint64 granulepos);
|
||||
typedef gint64 (*GstOggMapToGranuleFunc) (GstOggStream * pad,
|
||||
|
@ -66,6 +68,8 @@ typedef void (*GstOggMapExtractTagsFunc) (GstOggStream * pad,
|
|||
typedef gint64 (*GstOggMapGranuleposToKeyGranuleFunc) (GstOggStream * pad,
|
||||
gint64 granulepos);
|
||||
|
||||
typedef GstBuffer *(*GstOggMapGetHeadersFunc) (GstOggStream * pad);
|
||||
|
||||
#define SKELETON_FISBONE_MIN_SIZE 52
|
||||
#define SKELETON_FISHEAD_3_3_MIN_SIZE 112
|
||||
#define SKELETON_FISHEAD_4_0_MIN_SIZE 80
|
||||
|
@ -77,6 +81,7 @@ struct _GstOggMap
|
|||
int min_packet_size;
|
||||
const gchar *media_type;
|
||||
GstOggMapSetupFunc setup_func;
|
||||
GstOggMapSetupFromCapsFunc setup_from_caps_func;
|
||||
GstOggMapToGranuleFunc granulepos_to_granule_func;
|
||||
GstOggMapToGranuleposFunc granule_to_granulepos_func;
|
||||
GstOggMapIsGranuleposKeyFrameFunc is_granulepos_key_frame_func;
|
||||
|
@ -85,6 +90,7 @@ struct _GstOggMap
|
|||
GstOggMapPacketDurationFunc packet_duration_func;
|
||||
GstOggMapGranuleposToKeyGranuleFunc granulepos_to_key_granule_func;
|
||||
GstOggMapExtractTagsFunc extract_tags_func;
|
||||
GstOggMapGetHeadersFunc get_headers_func;
|
||||
};
|
||||
|
||||
extern const GstOggMap mappers[];
|
||||
|
@ -265,6 +271,15 @@ gst_ogg_stream_get_media_type (GstOggStream * pad)
|
|||
return gst_structure_get_name (structure);
|
||||
}
|
||||
|
||||
GstBuffer *
|
||||
gst_ogg_stream_get_headers (GstOggStream * pad)
|
||||
{
|
||||
if (!mappers[pad->map].get_headers_func)
|
||||
return NULL;
|
||||
|
||||
return mappers[pad->map].get_headers_func (pad);
|
||||
}
|
||||
|
||||
/* some generic functions */
|
||||
|
||||
static gboolean
|
||||
|
@ -650,6 +665,50 @@ setup_vp8_mapper (GstOggStream * pad, ogg_packet * packet)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
vp8_fill_header (GstOggStream * pad, const GstCaps * caps, guint8 * data)
|
||||
{
|
||||
gint width, height, par_n, par_d, fps_n, fps_d;
|
||||
GstStructure *structure = gst_caps_get_structure (caps, 0);
|
||||
|
||||
if (!(gst_structure_get_int (structure, "width", &width) &&
|
||||
gst_structure_get_int (structure, "height", &height) &&
|
||||
gst_structure_get_fraction (structure, "framerate", &fps_n,
|
||||
&fps_d))) {
|
||||
GST_DEBUG ("Failed to get width, height or framerate from caps %"
|
||||
GST_PTR_FORMAT, caps);
|
||||
return FALSE;
|
||||
}
|
||||
if (!gst_structure_get_fraction (structure, "pixel-aspect-ratio", &par_n,
|
||||
&par_d)) {
|
||||
par_n = par_d = 1;
|
||||
}
|
||||
|
||||
memcpy (data, "OVP80\1\1", 8);
|
||||
GST_WRITE_UINT16_BE (data + 8, width);
|
||||
GST_WRITE_UINT16_BE (data + 10, height);
|
||||
GST_WRITE_UINT24_BE (data + 12, par_n);
|
||||
GST_WRITE_UINT24_BE (data + 15, par_d);
|
||||
GST_WRITE_UINT32_BE (data + 18, fps_n);
|
||||
GST_WRITE_UINT32_BE (data + 22, fps_d);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
setup_vp8_mapper_from_caps (GstOggStream * pad, const GstCaps * caps)
|
||||
{
|
||||
guint8 data[26];
|
||||
ogg_packet packet;
|
||||
|
||||
if (!vp8_fill_header (pad, caps, data))
|
||||
return FALSE;
|
||||
|
||||
packet.packet = data;
|
||||
packet.bytes = 26;
|
||||
return setup_vp8_mapper (pad, &packet);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_keyframe_vp8 (GstOggStream * pad, gint64 granulepos)
|
||||
{
|
||||
|
@ -742,6 +801,18 @@ extract_tags_vp8 (GstOggStream * pad, ogg_packet * packet)
|
|||
}
|
||||
}
|
||||
|
||||
static GstBuffer *
|
||||
get_headers_vp8 (GstOggStream * pad)
|
||||
{
|
||||
guint8 *data = g_malloc (26);
|
||||
|
||||
if (vp8_fill_header (pad, pad->caps, data)) {
|
||||
return gst_buffer_new_wrapped (data, 26);
|
||||
}
|
||||
g_free (data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* vorbis */
|
||||
|
||||
static gboolean
|
||||
|
@ -2141,6 +2212,7 @@ const GstOggMap mappers[] = {
|
|||
"\200theora", 7, 42,
|
||||
"video/x-theora",
|
||||
setup_theora_mapper,
|
||||
NULL,
|
||||
granulepos_to_granule_theora,
|
||||
granule_to_granulepos_default,
|
||||
is_granulepos_keyframe_theora,
|
||||
|
@ -2148,12 +2220,14 @@ const GstOggMap mappers[] = {
|
|||
is_header_theora,
|
||||
packet_duration_constant,
|
||||
NULL,
|
||||
extract_tags_theora
|
||||
extract_tags_theora,
|
||||
NULL
|
||||
},
|
||||
{
|
||||
"\001vorbis", 7, 22,
|
||||
"audio/x-vorbis",
|
||||
setup_vorbis_mapper,
|
||||
NULL,
|
||||
granulepos_to_granule_default,
|
||||
granule_to_granulepos_default,
|
||||
is_granulepos_keyframe_true,
|
||||
|
@ -2161,12 +2235,14 @@ const GstOggMap mappers[] = {
|
|||
is_header_vorbis,
|
||||
packet_duration_vorbis,
|
||||
NULL,
|
||||
extract_tags_vorbis
|
||||
extract_tags_vorbis,
|
||||
NULL
|
||||
},
|
||||
{
|
||||
"Speex", 5, 80,
|
||||
"audio/x-speex",
|
||||
setup_speex_mapper,
|
||||
NULL,
|
||||
granulepos_to_granule_default,
|
||||
granule_to_granulepos_default,
|
||||
is_granulepos_keyframe_true,
|
||||
|
@ -2174,7 +2250,8 @@ const GstOggMap mappers[] = {
|
|||
is_header_count,
|
||||
packet_duration_constant,
|
||||
NULL,
|
||||
extract_tags_count
|
||||
extract_tags_count,
|
||||
NULL
|
||||
},
|
||||
{
|
||||
"PCM ", 8, 0,
|
||||
|
@ -2184,9 +2261,11 @@ const GstOggMap mappers[] = {
|
|||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
is_header_count,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
{
|
||||
|
@ -2197,15 +2276,18 @@ const GstOggMap mappers[] = {
|
|||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
is_header_count,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
{
|
||||
"Annodex", 7, 0,
|
||||
"application/x-annodex",
|
||||
setup_fishead_mapper,
|
||||
NULL,
|
||||
granulepos_to_granule_default,
|
||||
granule_to_granulepos_default,
|
||||
NULL,
|
||||
|
@ -2213,6 +2295,7 @@ const GstOggMap mappers[] = {
|
|||
is_header_count,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
{
|
||||
|
@ -2223,15 +2306,18 @@ const GstOggMap mappers[] = {
|
|||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
is_header_true,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
{
|
||||
"fLaC", 4, 0,
|
||||
"audio/x-flac",
|
||||
setup_fLaC_mapper,
|
||||
NULL,
|
||||
granulepos_to_granule_default,
|
||||
granule_to_granulepos_default,
|
||||
is_granulepos_keyframe_true,
|
||||
|
@ -2239,12 +2325,14 @@ const GstOggMap mappers[] = {
|
|||
is_header_fLaC,
|
||||
packet_duration_flac,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
{
|
||||
"\177FLAC", 5, 36,
|
||||
"audio/x-flac",
|
||||
setup_flac_mapper,
|
||||
NULL,
|
||||
granulepos_to_granule_default,
|
||||
granule_to_granulepos_default,
|
||||
is_granulepos_keyframe_true,
|
||||
|
@ -2252,7 +2340,8 @@ const GstOggMap mappers[] = {
|
|||
is_header_flac,
|
||||
packet_duration_flac,
|
||||
NULL,
|
||||
extract_tags_flac
|
||||
extract_tags_flac,
|
||||
NULL
|
||||
},
|
||||
{
|
||||
"AnxData", 7, 0,
|
||||
|
@ -2264,12 +2353,15 @@ const GstOggMap mappers[] = {
|
|||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
{
|
||||
"CELT ", 8, 0,
|
||||
"audio/x-celt",
|
||||
setup_celt_mapper,
|
||||
NULL,
|
||||
granulepos_to_granule_default,
|
||||
granule_to_granulepos_default,
|
||||
NULL,
|
||||
|
@ -2277,12 +2369,14 @@ const GstOggMap mappers[] = {
|
|||
is_header_count,
|
||||
packet_duration_constant,
|
||||
NULL,
|
||||
extract_tags_count
|
||||
extract_tags_count,
|
||||
NULL
|
||||
},
|
||||
{
|
||||
"\200kate\0\0\0", 8, 0,
|
||||
"text/x-kate",
|
||||
setup_kate_mapper,
|
||||
NULL,
|
||||
granulepos_to_granule_default,
|
||||
granule_to_granulepos_default,
|
||||
NULL,
|
||||
|
@ -2290,12 +2384,14 @@ const GstOggMap mappers[] = {
|
|||
is_header_count,
|
||||
packet_duration_kate,
|
||||
NULL,
|
||||
extract_tags_kate
|
||||
extract_tags_kate,
|
||||
NULL
|
||||
},
|
||||
{
|
||||
"BBCD\0", 5, 13,
|
||||
"video/x-dirac",
|
||||
setup_dirac_mapper,
|
||||
NULL,
|
||||
granulepos_to_granule_dirac,
|
||||
granule_to_granulepos_dirac,
|
||||
is_keyframe_dirac,
|
||||
|
@ -2303,12 +2399,14 @@ const GstOggMap mappers[] = {
|
|||
is_header_count,
|
||||
packet_duration_constant,
|
||||
granulepos_to_key_granule_dirac,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
{
|
||||
"OVP80\1\1", 7, 4,
|
||||
"video/x-vp8",
|
||||
setup_vp8_mapper,
|
||||
setup_vp8_mapper_from_caps,
|
||||
granulepos_to_granule_vp8,
|
||||
granule_to_granulepos_vp8,
|
||||
is_keyframe_vp8,
|
||||
|
@ -2316,12 +2414,14 @@ const GstOggMap mappers[] = {
|
|||
is_header_vp8,
|
||||
packet_duration_vp8,
|
||||
granulepos_to_key_granule_vp8,
|
||||
extract_tags_vp8
|
||||
extract_tags_vp8,
|
||||
get_headers_vp8
|
||||
},
|
||||
{
|
||||
"OpusHead", 8, 0,
|
||||
"audio/x-opus",
|
||||
setup_opus_mapper,
|
||||
NULL,
|
||||
granulepos_to_granule_opus,
|
||||
granule_to_granulepos_default,
|
||||
NULL,
|
||||
|
@ -2329,12 +2429,14 @@ const GstOggMap mappers[] = {
|
|||
is_header_opus,
|
||||
packet_duration_opus,
|
||||
NULL,
|
||||
extract_tags_opus
|
||||
extract_tags_opus,
|
||||
NULL
|
||||
},
|
||||
{
|
||||
"\001audio\0\0\0", 9, 53,
|
||||
"application/x-ogm-audio",
|
||||
setup_ogmaudio_mapper,
|
||||
NULL,
|
||||
granulepos_to_granule_default,
|
||||
granule_to_granulepos_default,
|
||||
is_granulepos_keyframe_true,
|
||||
|
@ -2342,12 +2444,14 @@ const GstOggMap mappers[] = {
|
|||
is_header_ogm,
|
||||
packet_duration_ogm,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
{
|
||||
"\001video\0\0\0", 9, 53,
|
||||
"application/x-ogm-video",
|
||||
setup_ogmvideo_mapper,
|
||||
NULL,
|
||||
granulepos_to_granule_default,
|
||||
granule_to_granulepos_default,
|
||||
NULL,
|
||||
|
@ -2355,12 +2459,14 @@ const GstOggMap mappers[] = {
|
|||
is_header_ogm,
|
||||
packet_duration_constant,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
{
|
||||
"\001text\0\0\0", 9, 9,
|
||||
"application/x-ogm-text",
|
||||
setup_ogmtext_mapper,
|
||||
NULL,
|
||||
granulepos_to_granule_default,
|
||||
granule_to_granulepos_default,
|
||||
is_granulepos_keyframe_true,
|
||||
|
@ -2368,12 +2474,14 @@ const GstOggMap mappers[] = {
|
|||
is_header_ogm,
|
||||
packet_duration_ogm,
|
||||
NULL,
|
||||
extract_tags_ogm
|
||||
extract_tags_ogm,
|
||||
NULL
|
||||
},
|
||||
{
|
||||
"\200daala", 6, 42,
|
||||
"video/x-daala",
|
||||
setup_daala_mapper,
|
||||
NULL,
|
||||
granulepos_to_granule_daala,
|
||||
granule_to_granulepos_default,
|
||||
is_granulepos_keyframe_daala,
|
||||
|
@ -2381,7 +2489,8 @@ const GstOggMap mappers[] = {
|
|||
is_header_daala,
|
||||
packet_duration_constant,
|
||||
NULL,
|
||||
extract_tags_daala
|
||||
extract_tags_daala,
|
||||
NULL
|
||||
},
|
||||
|
||||
};
|
||||
|
@ -2419,6 +2528,42 @@ gst_ogg_stream_setup_map (GstOggStream * pad, ogg_packet * packet)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_ogg_stream_setup_map_from_caps (GstOggStream * pad, const GstCaps * caps)
|
||||
{
|
||||
int i;
|
||||
gboolean ret;
|
||||
GstStructure *structure;
|
||||
|
||||
g_return_val_if_fail (caps != NULL, FALSE);
|
||||
|
||||
structure = gst_caps_get_structure (caps, 0);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (mappers); i++) {
|
||||
if (mappers[i].setup_from_caps_func &&
|
||||
gst_structure_has_name (structure, mappers[i].media_type)) {
|
||||
|
||||
GST_DEBUG ("found mapper for '%s'", mappers[i].id);
|
||||
|
||||
if (mappers[i].setup_from_caps_func)
|
||||
ret = mappers[i].setup_from_caps_func (pad, caps);
|
||||
else
|
||||
continue;
|
||||
|
||||
if (ret) {
|
||||
GST_DEBUG ("got stream type %" GST_PTR_FORMAT, pad->caps);
|
||||
pad->map = i;
|
||||
return TRUE;
|
||||
} else {
|
||||
GST_WARNING ("mapper '%s' did not accept caps %" GST_PTR_FORMAT,
|
||||
mappers[i].media_type, caps);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_ogg_stream_setup_map_from_caps_headers (GstOggStream * pad,
|
||||
const GstCaps * caps)
|
||||
|
|
|
@ -116,6 +116,8 @@ struct _GstOggStream
|
|||
gboolean gst_ogg_stream_setup_map (GstOggStream * pad, ogg_packet *packet);
|
||||
gboolean gst_ogg_stream_setup_map_from_caps_headers (GstOggStream * pad,
|
||||
const GstCaps * caps);
|
||||
gboolean gst_ogg_stream_setup_map_from_caps (GstOggStream * pad,
|
||||
const GstCaps * caps);
|
||||
GstClockTime gst_ogg_stream_get_end_time_for_granulepos (GstOggStream *pad,
|
||||
gint64 granulepos);
|
||||
GstClockTime gst_ogg_stream_get_start_time_for_granulepos (GstOggStream *pad,
|
||||
|
@ -133,6 +135,7 @@ gboolean gst_ogg_stream_packet_is_key_frame (GstOggStream *pad, ogg_packet *pack
|
|||
gint64 gst_ogg_stream_get_packet_duration (GstOggStream * pad, ogg_packet *packet);
|
||||
void gst_ogg_stream_extract_tags (GstOggStream * pad, ogg_packet * packet);
|
||||
const char *gst_ogg_stream_get_media_type (GstOggStream * pad);
|
||||
GstBuffer *gst_ogg_stream_get_headers (GstOggStream *pad);
|
||||
|
||||
gboolean gst_ogg_map_parse_fisbone (GstOggStream * pad, const guint8 * data, guint size,
|
||||
guint32 * serialno, GstOggSkeleton *type);
|
||||
|
|
Loading…
Reference in a new issue