How to use tsparse to extract an non PES stream
Edward Hervey
bilboed at bilboed.com
Tue Jul 6 10:21:18 UTC 2021
Hi,
Please file an issue here :
https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/
Provide a link to the file in that issue, or else the output of
GST_DEBUG=2,*ts*:8 GST_DEBUG_FILE=/location/to/logfile gst-play-1.0 <yourfile>
BR,
Edward
On Tue, 2021-07-06 at 17:44 +0800, Randy Li via gstreamer-devel wrote:
> Hello
>
> I am debugging a MPEG-TS demux, there is a video file that VLC could
> play but neither FFMpeg nor Gstreamer could. I found out the target
> video channel(program) seems not to be packed into the PES packet, I
> want to extract it out first.
>
> I think the tsparse should be the plugin I could use for it, then I
> wrote a demo likes below, but it doesn't work at all. Anything went
> wrong here or I should write a plugin myself ?
>
>
> #define _GNU_SOURCE /* See feature_test_macros(7) */
> #include <unistd.h>
> #include <stdio.h>
> #include <stdbool.h>
> #include <fcntl.h>
> #include <sys/wait.h>
> #include <sys/file.h>
> #include <sys/types.h>
> #include <sys/socket.h>
> #include <string.h>
> #include <gst/gst.h>
> #include <gst/check/gstcheck.h>
>
> static GMainLoop *loop;
>
> typedef struct {
> GstElement *pipeline;
> GstBus *bus;
> guint target_prog;
> } DemoApp;
>
> /* the master process'es async GstBus callback */
> static gboolean
> bus_handler (GstBus * bus, GstMessage * message, gpointer user_data)
> {
> DemoApp *d = user_data;
>
> switch (GST_MESSAGE_TYPE (message)) {
> case GST_MESSAGE_ERROR:{
> GError *err;
> gchar *dbg;
>
> /* elements we are removing might error out as they are taken out
> of the pipeline, and fail to push. We don't care about those. */
>
> gst_message_parse_error (message, &err, &dbg);
> g_printerr ("ERROR: %s\n", err->message);
> if (dbg != NULL)
> g_printerr ("ERROR debug information: %s\n", dbg);
> g_error_free (err);
> g_free (dbg);
> g_assert_not_reached ();
> break;
> }
> case GST_MESSAGE_WARNING:{
> GError *err;
> gchar *dbg;
>
> gst_message_parse_warning (message, &err, &dbg);
> g_printerr ("WARNING: %s\n", err->message);
> if (dbg != NULL)
> g_printerr ("WARNING debug information: %s\n", dbg);
> g_error_free (err);
> g_free (dbg);
> g_assert_not_reached ();
> break;
> }
> case GST_MESSAGE_EOS:
> g_main_loop_quit (loop);
> break;
> default:
> break;
> }
> return TRUE;
> }
>
> /* source construction functions */
> static bool
> add_program_pad(DemoApp *d, GstElement *element)
> {
> GstBin *pipeline = d->pipeline;
> GstElement *next = NULL;
> GstPad *pad = NULL;
> GstPad *sink_pad = NULL;
> gchar targetpad[20];
> GstPadLinkReturn ret;
>
> g_snprintf(targetpad, sizeof(targetpad), "program_%u",
> d->target_prog);
> pad = gst_element_get_request_pad(element, targetpad);
> if (!pad) {
> g_printerr("can't request program pad\n");
> return false;
> }
>
> next = gst_bin_get_by_name (GST_BIN (pipeline), "vqueue");
>
> sink_pad = gst_element_get_static_pad (next, "sink");
> ret = gst_pad_link (pad, sink_pad);
> if (ret != GST_PAD_LINK_OK)
> {
> g_assert_not_reached();
> }
> gst_object_unref (sink_pad);
>
> gst_object_unref (next);
>
> return true;
> }
>
> bool
> create_mpegts_source (DemoApp *d, const char *loc)
> {
> GstElement *pipeline, *filesrc, *fakesink, *tsparse,
> *vqueue, *filesink;
>
> pipeline = gst_pipeline_new ("tsextract");
> d->pipeline = pipeline;
>
> filesrc = gst_element_factory_make ("filesrc", NULL);
> g_object_set (filesrc, "location", loc, NULL);
> tsparse = gst_element_factory_make ("tsparse", NULL);
> //fakesink = gst_element_factory_make ("fakesink", NULL);
> vqueue = gst_element_factory_make ("queue", "vqueue");
> filesink = gst_element_factory_make ("filesink", "sink");
> g_object_set (filesink, "location", "./tsout", NULL);
>
> gst_bin_add_many (GST_BIN (pipeline), filesrc, tsparse,
> vqueue, filesink, NULL);
> gst_element_link_many (filesrc, tsparse, NULL);
> gst_element_link_many (vqueue, filesink, NULL);
>
> add_program_pad(d, tsparse);
>
> d->bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
> gst_bus_add_watch (d->bus, bus_handler, d);
>
> return true;
> }
>
> int
> main (int argc, char **argv)
> {
> DemoApp *d = NULL;
> GOptionContext *context;
> GError *error = NULL;
> gchar *uri = NULL;
> gchar *path = NULL;
> gint program_id = 0;
>
> GOptionEntry entries[] = {
> {"uri", '\0', 0, G_OPTION_ARG_STRING, &uri, "video source URI", NULL},
> {"path", 'i', 0, G_OPTION_ARG_STRING, &path,
> "the path of a video file or directory", NULL},
> {"program", 'p', 0, G_OPTION_ARG_INT, &program_id,
> "MPEG-TS program id", NULL},
> {NULL}
> };
>
> gst_init (&argc, &argv);
>
> context = g_option_context_new ("MPEG-TS Extractor");
> g_option_context_add_main_entries (context, entries, NULL);
> if (!g_option_context_parse (context, &argc, &argv, &error)) {
> g_printerr ("option parsing failed: %s\n", error->message);
> return 1;
> }
> g_option_context_free (context);
>
> if (!uri && !path) {
> g_printerr ("need input file\n", argv[0]);
> return 1;
> }
>
> if (!program_id) {
> g_printerr ("program id\n", argv[0]);
> return 1;
> }
>
> d = g_slice_new0 (DemoApp);
> d->target_prog = program_id;
>
> create_mpegts_source(d, path);
> gst_element_set_state (d->pipeline, GST_STATE_PLAYING);
>
> loop = g_main_loop_new (NULL, FALSE);
> g_main_loop_run (loop);
>
> gst_element_set_state (d->pipeline, GST_STATE_NULL);
> gst_object_unref (d->pipeline);
>
> g_slice_free (DemoApp, d);
>
> }
>
More information about the gstreamer-devel
mailing list