gstreamervideo-processingvideo-encodinggstreamer-1.0

Use gstreamer to remux a single title out of a DVD without re encoding


I am trying to re-mux the video of a specific title out of a DVD into a video file, without decoding then re-encoding the video.

I have this pipeline that works exactly the way I want for audio, and theoretically would work the way I want for video, but drops most video buffers due to

matroskamux matroska-mux.c:4035:gst_matroska_mux_write_data:<mux:video_0>
    Invalid buffer timestamp; dropping buffer

The resulting video file plays, but is a slideshow, as one would expect given all the dropped video buffers.

Here's the pipeline in question

#!/bin/bash
TITLE=2
DVD=~/BATTSTAR_GALAC_S1_D2.iso
GST_DEBUG=2                                         \
gst-launch-1.0 -v -e                                \
    dvdreadsrc title=${TITLE} device=${DVD}         \
        ! mpegpsdemux name=demux                    \
                                                    \
    multiqueue name=queue                           \
        demux. ! 'video/mpeg'           ! queue.    \
        demux. ! 'audio/x-private1-ac3' ! queue.    \
                                                    \
    matroskamux name=mux                            \
        queue. ! mpegvideoparse ! mux.              \
        queue. ! ac3parse       ! mux.              \
                                                    \
    mux. ! filesink location=~/test.mkv

Here's another version of the same pipeline where I tried to inject timestamping, which also does not work.

#!/bin/bash
TITLE=2
DVD=~/BATTSTAR_GALAC_S1_D2.iso
GST_DEBUG=2                                         \
gst-launch-1.0 -v -e                                \
    dvdreadsrc do-timestamp=true ! title=${TITLE} device=${DVD} \
        ! mpegpsdemux name=demux ignore-scr=true    \
                                                    \
    multiqueue name=queue                           \
        demux. ! 'video/mpeg'           ! queue.    \
        demux. ! 'audio/x-private1-ac3' ! queue.    \
                                                    \
    matroskamux name=mux                            \
        queue. ! mpegvideoparse disable-passthrough=true ! mux. \
        queue. ! ac3parse       disable-passthrough=true ! mux. \
                                                    \
    mux. ! filesink location=~/test.mkv

Thinking that perhaps something is wrong with the multiqueue, or with syncronizing the video and the audio, I can still reproduce the choppy video (dropped buffers) by removing the audio component of the pipeline and switching from multiqueue to queue (not queue2, that ends the pipeline before it gets to the end, I don't know why other than speculating a bug).

#!/bin/bash
TITLE=2
DVD=~/BATTSTAR_GALAC_S1_D2.iso
GST_DEBUG=1                                 \
gst-launch-1.0 -v -e                        \
    dvdreadsrc title=${TITLE} device=${DVD} \
        ! mpegpsdemux name=demux            \
                                            \
    queue name=videoqueue                   \
        demux. ! 'video/mpeg' ! videoqueue. \
                                            \
    matroskamux name=mux                    \
        videoqueue. ! mpegvideoparse ! mux. \
                                            \
    mux. ! filesink location=~/test.mkv

Since I speculate a bug in queue2, what if I remove the queue entirely? Still has the problem.

#!/bin/bash
TITLE=2
DVD=~/BATTSTAR_GALAC_S1_D2.iso
GST_DEBUG=1                                 \
gst-launch-1.0 -v -e                        \
    dvdreadsrc title=${TITLE} device=${DVD} \
        ! mpegpsdemux                       \
        ! mpegvideoparse                    \
        ! matroskamux                       \
        ! filesink location=~/test.mkv

An important note is that I can play the video JUST FINE with gstreamer, e.g.

#!/bin/bash
TITLE=2
DVD=~/BATTSTAR_GALAC_S1_D2.iso
GST_DEBUG=2                                 \
gst-launch-1.0 -v -e                        \
    dvdreadsrc title=${TITLE} device=${DVD} \
        ! mpegpsdemux                       \
        ! mpegvideoparse                    \
        ! mpeg2dec                          \
        ! autovideosink

and the same with working audio and video

#!/bin/bash
TITLE=2
DVD=~/BATTSTAR_GALAC_S1_D2.iso
GST_DEBUG=2                                         \
gst-launch-1.0 -v -e                                \
    dvdreadsrc title=${TITLE} device=${DVD}         \
        ! mpegpsdemux name=demux                    \
                                                    \
    multiqueue name=queue                           \
        demux. ! 'video/mpeg'           ! queue.    \
        demux. ! 'audio/x-private1-ac3' ! queue.    \
                                                    \
        queue. ! mpegvideoparse ! mpeg2dec ! autovideosink  \
        queue. ! ac3parse       ! a52dec   ! autoaudiosink

So this is not a problem of the source video being bad, it's entirely something that's missing from the pipeline.

I can even play the video while re-muxing it, and the on-screen video is smooth, but the file saved to disk is choppy

#!/bin/bash
TITLE=2
DVD=~/BATTSTAR_GALAC_S1_D2.iso
GST_DEBUG=2                                     \
gst-launch-1.0 -v -e                            \
    dvdreadsrc title=${TITLE} device=${DVD}     \
        ! mpegpsdemux name=demux                \
                                                \
    tee name=vtee                               \
    tee name=atee                               \
        demux. ! mpegvideoparse ! vtee.         \
        demux. ! ac3parse       ! atee.         \
                                                \
    multiqueue name=playqueue                   \
    multiqueue name=convqueue                   \
        vtee. ! playqueue.                      \
        vtee. ! convqueue.                      \
        atee. ! playqueue.                      \
        atee. ! convqueue.                      \
                                                \
        playqueue. ! decodebin ! autovideosink  \
        playqueue. ! decodebin ! autoaudiosink  \
                                                \
    matroskamux name=mux                        \
        convqueue. ! mux.                       \
        convqueue. ! mux.                       \
                                                \
    mux. ! filesink location=~/test.mkv

And here's a version of the pipeline that decodes the mpeg video and then re-encodes mpeg video. This version produces a video file that is not a slideshow, but has the problem of needing to re-encode the video. I don't want to re-encode the video, I want to take it "as is".

#!/bin/bash
TITLE=2
DVD=~/BATTSTAR_GALAC_S1_D2.iso
GST_DEBUG=2                                         \
gst-launch-1.0 -v -e                                \
    dvdreadsrc title=${TITLE} device=${DVD}         \
        ! mpegpsdemux name=demux                    \
                                                    \
    multiqueue name=queue                           \
        demux. ! 'video/mpeg'           ! queue.    \
        demux. ! 'audio/x-private1-ac3' ! queue.    \
                                                    \
    matroskamux name=mux                            \
        queue. ! mpegvideoparse ! mpeg2dec ! mpeg2enc ! mux. \
        queue. ! ac3parse       ! mux.              \
                                                    \
    mux. ! filesink location=~/test.mkv

Note that I'm using gstreamer version 1.20.4, compiled and installed on Gentoo Linux. It is possible that the 1.22 release series may have a fix for my problem, but I don't see anything on the release notes that make me think this was addressed: https://gstreamer.freedesktop.org/releases/1.22/


So what am I missing from my pipeline that prevents the buffers read from the DVD from having a valid timestamp when they get to the matroskamux ?


Solution

  • The problem preventing this from working has been fixed in gstreamer 1.24

    This script works as intended

    GST_DEBUG=1                                             \
    gst-launch-1.0 -v -e                                    \
        mpegpsdemux name=demux                              \
        multiqueue name=queue                               \
            demux.video_e0 ! queue.sink_1                   \
            demux.audio_80 ! queue.sink_2                   \
                                                            \
        matroskamux name=mux                                \
            queue.src_1 ! mpegvideoparse ! mpegtsmux        \
                ! tsdemux ! mpegvideoparse ! mux.video_00   \
            queue.src_2 ! ac3parse       ! mux.audio_00     \
                                                            \
        dvdreadsrc title=${TITLE} device=${DVD} ! demux.    \
        mux. ! filesink location=${OUTPUT}
    

    I'm not excited about the need to insert the

    mpegtsmux ! tsdemux ! mpegvideoparse
    

    Into the pipeline, but if it works it works.