matroskamux: Port to GstAggregator

Co-authored-by: Tim-Philipp Müller <tim@centricular.com>
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7510>
This commit is contained in:
Sebastian Dröge 2024-09-13 10:13:11 +03:00 committed by GStreamer Marge Bot
parent a8f8bbef99
commit 945a7bdfc4
8 changed files with 509 additions and 613 deletions

View file

@ -12446,6 +12446,8 @@
"GstMatroskaMux:timecodescale",
"GstMatroskaMux:version",
"GstMatroskaMux:writing-app",
"GstMatroskaMuxPad",
"GstMatroskaMuxPad:frame-duration",
"GstMatroskaParse",
"GstMatroskaParse!sink",
"GstMatroskaParse!src",

View file

@ -9811,6 +9811,7 @@
"description": "Muxes video/audio/subtitle streams into a matroska stream",
"hierarchy": [
"GstMatroskaMux",
"GstAggregator",
"GstElement",
"GstObject",
"GInitiallyUnowned",
@ -9826,7 +9827,8 @@
"audio_%%u": {
"caps": "audio/mpeg:\n mpegversion: 1\n layer: [ 1, 3 ]\n channels: [ 1, 2147483647 ]\n rate: [ 1, 2147483647 ]\naudio/mpeg:\n mpegversion: { (int)2, (int)4 }\n stream-format: raw\n channels: [ 1, 2147483647 ]\n rate: [ 1, 2147483647 ]\naudio/x-ac3:\n channels: [ 1, 2147483647 ]\n rate: [ 1, 2147483647 ]\naudio/x-eac3:\n channels: [ 1, 2147483647 ]\n rate: [ 1, 2147483647 ]\naudio/x-dts:\n channels: [ 1, 2147483647 ]\n rate: [ 1, 2147483647 ]\naudio/x-vorbis:\n channels: [ 1, 2147483647 ]\n rate: [ 1, 2147483647 ]\naudio/x-flac:\n channels: [ 1, 2147483647 ]\n rate: [ 1, 2147483647 ]\naudio/x-opus:\n channels: [ 1, 8 ]\n rate: { (int)8000, (int)16000, (int)24000, (int)32000, (int)48000 }\naudio/x-speex:\n channels: [ 1, 2147483647 ]\n rate: [ 1, 2147483647 ]\naudio/x-raw:\n format: { U8, S16BE, S16LE, S24BE, S24LE, S32BE, S32LE, F32LE, F64LE }\n layout: interleaved\n channels: [ 1, 2147483647 ]\n rate: [ 1, 2147483647 ]\naudio/x-tta:\n width: { (int)8, (int)16, (int)24 }\n channels: { (int)1, (int)2 }\n rate: [ 8000, 96000 ]\naudio/x-pn-realaudio:\n raversion: { (int)1, (int)2, (int)8 }\n channels: [ 1, 2147483647 ]\n rate: [ 1, 2147483647 ]\naudio/x-wma:\n wmaversion: [ 1, 3 ]\n block_align: [ 0, 65535 ]\n bitrate: [ 0, 524288 ]\n channels: [ 1, 2147483647 ]\n rate: [ 1, 2147483647 ]\naudio/x-alaw:\n channels: { (int)1, (int)2 }\n rate: [ 8000, 192000 ]\naudio/x-mulaw:\n channels: { (int)1, (int)2 }\n rate: [ 8000, 192000 ]\naudio/x-adpcm:\n layout: dvi\n block_align: [ 64, 8192 ]\n channels: { (int)1, (int)2 }\n rate: [ 8000, 96000 ]\naudio/G722:\n channels: 1\n rate: 16000\naudio/x-adpcm:\n layout: g726\n channels: 1\n rate: 8000\n",
"direction": "sink",
"presence": "request"
"presence": "request",
"type": "GstMatroskaMuxPad"
},
"src": {
"caps": "video/x-matroska:\nvideo/x-matroska-3d:\naudio/x-matroska:\n",
@ -9836,12 +9838,14 @@
"subtitle_%%u": {
"caps": "subtitle/x-kate:\ntext/x-raw:\n format: utf8\napplication/x-ssa:\napplication/x-ass:\napplication/x-usf:\nsubpicture/x-dvd:\napplication/x-subtitle-unknown:\n",
"direction": "sink",
"presence": "request"
"presence": "request",
"type": "GstMatroskaMuxPad"
},
"video_%%u": {
"caps": "video/mpeg:\n mpegversion: { (int)1, (int)2, (int)4 }\n systemstream: false\n width: [ 1, 2147483647 ]\n height: [ 1, 2147483647 ]\nvideo/x-h264:\n stream-format: { (string)avc, (string)avc3 }\n alignment: au\n width: [ 1, 2147483647 ]\n height: [ 1, 2147483647 ]\nvideo/x-h265:\n stream-format: { (string)hvc1, (string)hev1 }\n alignment: au\n width: [ 1, 2147483647 ]\n height: [ 1, 2147483647 ]\nvideo/x-divx:\n width: [ 1, 2147483647 ]\n height: [ 1, 2147483647 ]\nvideo/x-huffyuv:\n width: [ 1, 2147483647 ]\n height: [ 1, 2147483647 ]\nvideo/x-dv:\n width: [ 1, 2147483647 ]\n height: [ 1, 2147483647 ]\nvideo/x-h263:\n width: [ 1, 2147483647 ]\n height: [ 1, 2147483647 ]\nvideo/x-msmpeg:\n width: [ 1, 2147483647 ]\n height: [ 1, 2147483647 ]\nimage/jpeg:\n width: [ 1, 2147483647 ]\n height: [ 1, 2147483647 ]\nvideo/x-theora:\nvideo/x-dirac:\n width: [ 1, 2147483647 ]\n height: [ 1, 2147483647 ]\nvideo/x-pn-realvideo:\n rmversion: [ 1, 4 ]\n width: [ 1, 2147483647 ]\n height: [ 1, 2147483647 ]\nvideo/x-vp8:\n width: [ 1, 2147483647 ]\n height: [ 1, 2147483647 ]\nvideo/x-vp9:\n width: [ 1, 2147483647 ]\n height: [ 1, 2147483647 ]\nvideo/x-raw:\n format: { YUY2, I420, YV12, UYVY, AYUV, GRAY8, GRAY10_LE32, GRAY16_LE, BGR, RGB, RGBA64_LE, BGRA64_LE }\n width: [ 1, 2147483647 ]\n height: [ 1, 2147483647 ]\nvideo/x-prores:\n width: [ 1, 2147483647 ]\n height: [ 1, 2147483647 ]\nvideo/x-wmv:\n wmvversion: [ 1, 3 ]\n width: [ 1, 2147483647 ]\n height: [ 1, 2147483647 ]\nvideo/x-av1:\n stream-format: obu-stream\n alignment: tu\n width: [ 1, 2147483647 ]\n height: [ 1, 2147483647 ]\nvideo/x-ffv:\n ffversion: 1\n width: [ 1, 2147483647 ]\n height: [ 1, 2147483647 ]\n",
"direction": "sink",
"presence": "request"
"presence": "request",
"type": "GstMatroskaMuxPad"
}
},
"properties": {
@ -10011,6 +10015,7 @@
"hierarchy": [
"GstWebMMux",
"GstMatroskaMux",
"GstAggregator",
"GstElement",
"GstObject",
"GInitiallyUnowned",
@ -10026,7 +10031,8 @@
"audio_%%u": {
"caps": "audio/x-vorbis:\n channels: [ 1, 2147483647 ]\n rate: [ 1, 2147483647 ]\naudio/x-opus:\n channels: [ 1, 2147483647 ]\n rate: [ 1, 2147483647 ]\n",
"direction": "sink",
"presence": "request"
"presence": "request",
"type": "GstMatroskaMuxPad"
},
"src": {
"caps": "video/webm:\naudio/webm:\n",
@ -10036,12 +10042,14 @@
"subtitle_%%u": {
"caps": "subtitle/x-kate:\ntext/x-raw:\n format: utf8\napplication/x-ssa:\napplication/x-ass:\napplication/x-usf:\nsubpicture/x-dvd:\napplication/x-subtitle-unknown:\n",
"direction": "sink",
"presence": "request"
"presence": "request",
"type": "GstMatroskaMuxPad"
},
"video_%%u": {
"caps": "video/x-vp8:\n width: [ 16, 2147483647 ]\n height: [ 16, 2147483647 ]\n framerate: [ 0/1, 2147483647/1 ]\nvideo/x-vp9:\n width: [ 16, 2147483647 ]\n height: [ 16, 2147483647 ]\n framerate: [ 0/1, 2147483647/1 ]\nvideo/x-av1:\n stream-format: obu-stream\n alignment: tu\n width: [ 16, 2147483647 ]\n height: [ 16, 2147483647 ]\n framerate: [ 0/1, 2147483647/1 ]\n",
"direction": "sink",
"presence": "request"
"presence": "request",
"type": "GstMatroskaMuxPad"
}
},
"properties": {},
@ -10050,7 +10058,33 @@
},
"filename": "gstmatroska",
"license": "LGPL",
"other-types": {},
"other-types": {
"GstMatroskaMuxPad": {
"hierarchy": [
"GstMatroskaMuxPad",
"GstAggregatorPad",
"GstPad",
"GstObject",
"GInitiallyUnowned",
"GObject"
],
"kind": "object",
"properties": {
"frame-duration": {
"blurb": "Default frame duration",
"conditionally-available": false,
"construct": false,
"construct-only": false,
"controllable": true,
"default": "true",
"mutable": "null",
"readable": true,
"type": "gboolean",
"writable": true
}
}
}
},
"package": "GStreamer Good Plug-ins",
"source": "gst-plugins-good",
"tracers": {},

View file

@ -52,7 +52,7 @@ gst_ebml_write_class_init (GstEbmlWriteClass * klass)
static void
gst_ebml_write_init (GstEbmlWrite * ebml)
{
ebml->srcpad = NULL;
ebml->agg = NULL;
ebml->pos = 0;
ebml->last_pos = G_MAXUINT64; /* force segment event */
@ -68,7 +68,7 @@ gst_ebml_write_finalize (GObject * object)
{
GstEbmlWrite *ebml = GST_EBML_WRITE (object);
gst_object_unref (ebml->srcpad);
ebml->agg = NULL;
if (ebml->cache) {
gst_byte_writer_free (ebml->cache);
@ -98,12 +98,12 @@ gst_ebml_write_finalize (GObject * object)
* Returns: a new #GstEbmlWrite
*/
GstEbmlWrite *
gst_ebml_write_new (GstPad * srcpad)
gst_ebml_write_new (GstAggregator * agg)
{
GstEbmlWrite *ebml =
GST_EBML_WRITE (g_object_new (GST_TYPE_EBML_WRITE, NULL));
ebml->srcpad = gst_object_ref (srcpad);
ebml->agg = agg;
ebml->timestamp = GST_CLOCK_TIME_NONE;
gst_ebml_write_reset (ebml);
@ -207,11 +207,10 @@ gst_ebml_write_set_cache (GstEbmlWrite * ebml, guint size)
ebml->cache_pos = ebml->pos;
}
static gboolean
static void
gst_ebml_writer_send_segment_event (GstEbmlWrite * ebml, guint64 new_pos)
{
GstSegment segment;
gboolean res;
GST_INFO ("seeking to %" G_GUINT64_FORMAT, new_pos);
@ -221,12 +220,7 @@ gst_ebml_writer_send_segment_event (GstEbmlWrite * ebml, guint64 new_pos)
segment.stop = -1;
segment.position = 0;
res = gst_pad_push_event (ebml->srcpad, gst_event_new_segment (&segment));
if (!res)
GST_WARNING ("seek to %" G_GUINT64_FORMAT "failed", new_pos);
return res;
gst_aggregator_update_segment (ebml->agg, &segment);
}
/**
@ -268,7 +262,7 @@ gst_ebml_write_flush_cache (GstEbmlWrite * ebml, gboolean is_keyframe,
GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
}
ebml->last_pos = ebml->pos;
ebml->last_write_result = gst_pad_push (ebml->srcpad, buffer);
ebml->last_write_result = gst_aggregator_finish_buffer (ebml->agg, buffer);
} else {
gst_buffer_unref (buffer);
}
@ -474,7 +468,7 @@ gst_ebml_write_element_push (GstEbmlWrite * ebml, GstBuffer * buf,
GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
}
ebml->last_pos = ebml->pos;
ebml->last_write_result = gst_pad_push (ebml->srcpad, buf);
ebml->last_write_result = gst_aggregator_finish_buffer (ebml->agg, buf);
} else {
gst_buffer_unref (buf);
}

View file

@ -25,7 +25,7 @@
#include <glib.h>
#include <gst/gst.h>
#include <gst/base/gstbytewriter.h>
#include <gst/base/base.h>
G_BEGIN_DECLS
@ -45,7 +45,8 @@ G_BEGIN_DECLS
typedef struct _GstEbmlWrite {
GstObject object;
GstPad *srcpad;
GstAggregator *agg;
guint64 pos;
guint64 last_pos;
GstClockTime timestamp;
@ -70,7 +71,7 @@ typedef struct _GstEbmlWriteClass {
GType gst_ebml_write_get_type (void);
GstEbmlWrite *gst_ebml_write_new (GstPad *srcpad);
GstEbmlWrite *gst_ebml_write_new (GstAggregator *agg);
void gst_ebml_write_reset (GstEbmlWrite *ebml);
GstFlowReturn gst_ebml_last_write_result (GstEbmlWrite *ebml);

File diff suppressed because it is too large Load diff

View file

@ -24,7 +24,7 @@
#define __GST_MATROSKA_MUX_H__
#include <gst/gst.h>
#include <gst/base/gstcollectpads.h>
#include <gst/base/base.h>
#include "ebml-write.h"
#include "matroska-ids.h"
@ -42,6 +42,11 @@ G_BEGIN_DECLS
#define GST_IS_MATROSKA_MUX_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MATROSKA_MUX))
#define GST_TYPE_MATROSKA_MUX_PAD (gst_matroska_mux_pad_get_type())
#define GST_MATROSKA_MUX_PAD(pad) (G_TYPE_CHECK_INSTANCE_CAST((pad),GST_TYPE_MATROSKA_MUX_PAD,GstMatroskaMuxPad))
#define GST_MATROSKA_MUX_PAD_CAST(pad) ((GstMatroskaMuxPad *) pad)
#define GST_IS_MATROSKA_MUX_PAD(pad) (G_TYPE_CHECK_INSTANCE_TYPE((pad),GST_TYPE_MATROSKA_MUX_PAD))
typedef enum {
GST_MATROSKA_MUX_STATE_START,
GST_MATROSKA_MUX_STATE_HEADER,
@ -53,36 +58,37 @@ typedef struct _GstMatroskaMetaSeekIndex {
guint64 pos;
} GstMatroskaMetaSeekIndex;
typedef gboolean (*GstMatroskaCapsFunc) (GstPad *pad, GstCaps *caps);
typedef struct _GstMatroskaMux GstMatroskaMux;
typedef struct _GstMatroskaMuxPad GstMatroskaMuxPad;
typedef gboolean (*GstMatroskaCapsFunc) (GstMatroskaMux *mux, GstMatroskaMuxPad *mux_pad, GstCaps *caps);
/* all information needed for one matroska stream */
typedef struct
{
GstCollectData collect; /* we extend the CollectData */
struct _GstMatroskaMuxPad {
GstAggregatorPad pad;
gboolean frame_duration;
gboolean frame_duration_user;
GstMatroskaCapsFunc capsfunc;
GstMatroskaTrackContext *track;
GstMatroskaMux *mux;
GstTagList *tags;
GstClockTime start_ts;
GstClockTime end_ts; /* last timestamp + (if available) duration */
guint64 default_duration_scaled;
}
GstMatroskaPad;
};
typedef struct _GstMatroskaMuxPadClass {
GstAggregatorPadClass pad_class;
} GstMatroskaMuxPadClass;
struct _GstMatroskaMux {
GstElement element;
GstAggregator aggregator;
/* < private > */
/* pads */
GstPad *srcpad;
GstCollectPads *collect;
GstEbmlWrite *ebml_write;
guint num_streams,
@ -150,10 +156,11 @@ struct _GstMatroskaMux {
};
typedef struct _GstMatroskaMuxClass {
GstElementClass parent;
GstAggregatorClass parent;
} GstMatroskaMuxClass;
GType gst_matroska_mux_get_type (void);
GType gst_matroska_mux_pad_get_type (void);
G_END_DECLS

View file

@ -87,10 +87,10 @@ gst_webm_mux_class_init (GstWebMMuxClass * klass)
{
GstElementClass *gstelement_class = (GstElementClass *) klass;
gst_element_class_add_static_pad_template (gstelement_class,
&webm_videosink_templ);
gst_element_class_add_static_pad_template (gstelement_class,
&webm_audiosink_templ);
gst_element_class_add_static_pad_template_with_gtype (gstelement_class,
&webm_videosink_templ, GST_TYPE_MATROSKA_MUX_PAD);
gst_element_class_add_static_pad_template_with_gtype (gstelement_class,
&webm_audiosink_templ, GST_TYPE_MATROSKA_MUX_PAD);
gst_element_class_add_static_pad_template (gstelement_class, &webm_src_templ);
gst_element_class_set_static_metadata (gstelement_class, "WebM muxer",
"Codec/Muxer",

View file

@ -74,13 +74,16 @@ test_ebml_header_with_version (gint version,
g_object_set (h->element, "version", version, NULL);
inbuffer = gst_harness_create_buffer (h, 1);
GST_BUFFER_PTS (inbuffer) = 0;
fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h, inbuffer));
fail_unless_equals_int (2, gst_harness_buffers_received (h));
outbuffer = gst_harness_pull (h);
compare_buffer_to_data (outbuffer, data, data_size);
gst_buffer_unref (outbuffer);
outbuffer = gst_harness_pull (h);
gst_buffer_unref (outbuffer);
gst_harness_teardown (h);
}
@ -142,6 +145,7 @@ GST_START_TEST (test_vorbis_header)
h = setup_matroskamux_harness (VORBIS_TMPL_CAPS_STRING);
inbuffer = gst_harness_create_buffer (h, 1);
GST_BUFFER_PTS (inbuffer) = 0;
fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h, inbuffer));
outbuffer = gst_harness_pull (h);
@ -160,7 +164,10 @@ GST_START_TEST (test_vorbis_header)
ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 1);
gst_buffer_unref (outbuffer);
outbuffer = gst_harness_try_pull (h);
if (vorbis_header_found)
break;
outbuffer = gst_harness_pull (h);
}
fail_unless (vorbis_header_found);
@ -186,13 +193,11 @@ test_block_group_with_version (gint version,
inbuffer = gst_harness_create_buffer (h, 1);
GST_BUFFER_TIMESTAMP (inbuffer) = 0;
fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h, inbuffer));
fail_unless_equals_int (5, gst_harness_buffers_received (h));
for (int i = 0; i < 5; i++) {
outbuffer = gst_harness_pull (h);
fail_unless (outbuffer != NULL);
while (outbuffer != NULL) {
gst_buffer_unref (outbuffer);
outbuffer = gst_harness_try_pull (h);
}
/* Now push a buffer */
@ -245,13 +250,11 @@ GST_START_TEST (test_reset)
inbuffer = gst_harness_create_buffer (h, 1);
GST_BUFFER_TIMESTAMP (inbuffer) = 0;
fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h, inbuffer));
fail_unless_equals_int (5, gst_harness_buffers_received (h));
for (int i = 0; i < 5; i++) {
outbuffer = gst_harness_pull (h);
fail_unless (outbuffer != NULL);
while (outbuffer != NULL) {
gst_buffer_unref (outbuffer);
outbuffer = gst_harness_try_pull (h);
}
fail_unless_equals_int (GST_STATE_CHANGE_SUCCESS,
@ -262,12 +265,13 @@ GST_START_TEST (test_reset)
inbuffer = gst_harness_create_buffer (h, 1);
GST_BUFFER_TIMESTAMP (inbuffer) = 0;
fail_unless_equals_int (GST_FLOW_OK, gst_harness_push (h, inbuffer));
gst_harness_push_event (h, gst_event_new_eos ());
outbuffer = gst_harness_pull (h);
fail_unless (outbuffer != NULL);
while (outbuffer != NULL) {
gst_buffer_unref (outbuffer);
outbuffer = gst_harness_try_pull (h);
fail_unless (gst_harness_pull_until_eos (h, &outbuffer));
}
gst_harness_teardown (h);
@ -940,7 +944,6 @@ test_toc (gboolean with_edition)
/* send eos to ensure everything is written */
fail_unless (gst_harness_push_event (h, gst_event_new_eos ()));
ASSERT_MINI_OBJECT_REFCOUNT (test_toc, "test_toc", 1);
outbuffer = gst_harness_pull (h);
fail_unless (outbuffer != NULL);
@ -958,7 +961,7 @@ test_toc (gboolean with_edition)
}
gst_buffer_unref (outbuffer);
outbuffer = gst_harness_try_pull (h);
fail_unless (gst_harness_pull_until_eos (h, &outbuffer));
}
fail_unless (gst_buffer_map (merged_buffer, &info, GST_MAP_READ));