<div dir="ltr"><div><div><div><div><div>All,<br><br></div>I've been trying to step through frame by frame with one pipeline and pass through to another. Basically I want to look at every h264 frame and then pipe it off into a filesink. I have made an example of what I thought would work below.<br><br></div>It should take an MKV file, step thought the h264 frames and pipe them to a MP4 file without missing any frames (It is important that I get the actual frames here). So the first pipeline is in PAUSE mode and the second pipeline is in PLAYING (I don't think writing to a file can be done in paused mode?). I understand I could do this by removing the appsink->appsrc but that is not what I am looking for and wont work in my application.<br><br></div>My big problem at the moment is that I can't seem to determine when the end-of-stream occurs since I am in paused mode. My best attempt was to use pos > dur, but I have found this isn't always true. In the current case I either end early or never end (when I remove the pos == last section). If there is a better way to do this I would appreciate any ideas. Sample code is below! Sample MKV file: <a href="http://jell.yfish.us/media/jellyfish-25-mbps-hd-h264.mkv" target="_blank">http://jell.yfish.us/media/<wbr>jellyfish-25-mbps-hd-h264.mkv</a><br><br></div><div><code><br>from gi.repository import Gst, GObject<br>import sys<br>import os<br>import glob<br><br>def test_file(inc):<br>    filename = "jellyfish-25-mbps-hd-h264.<wbr>mkv"<br>    elements = {}<br><br>    def demuxer_callback(demuxer, pad):<br>        if pad.get_property("template").<wbr>name_template == "video_%u":<br>            pad.link(elements['h264parse']<wbr>.get_static_pad("sink"))<br><br>    #GObject.threads_init()<br>    Gst.init()<br>    Gst.debug_set_active(True)<br>    Gst.debug_set_default_<wbr>threshold(1)<br>    pipeline_front = Gst.Pipeline()<br>    pipeline_end = Gst.Pipeline()<br><br>    elements['filesrc'] = Gst.ElementFactory.make('<wbr>filesrc', str(inc)+'_filesrc')<br>    elements['filesrc'].set_<wbr>property('location', filename)<br>    elements['matroskademux'] = Gst.ElementFactory.make('<wbr>matroskademux', str(inc)+'_matroskademux')<br>    elements['matroskademux'].<wbr>connect('pad-added', demuxer_callback)<br>    elements['h264parse'] = Gst.ElementFactory.make('<wbr>h264parse', str(inc)+'_h264parse')<br>    elements['raw1queue'] = Gst.ElementFactory.make('<wbr>queue', str(inc)+'_raw1queue')<br>    elements['innersink'] = Gst.ElementFactory.make('<wbr>appsink', str(inc)+'_appsink')<br><br>    elements['mp4appsrc'] = Gst.ElementFactory.make('<wbr>appsrc')<br>    elements['mp4h264parse'] = Gst.ElementFactory.make('<wbr>h264parse')<br>    elements['mp4queue'] = Gst.ElementFactory.make('<wbr>queue')<br>    elements['mp4mux'] = Gst.ElementFactory.make('<wbr>mp4mux')<br>    elements['mp4mqueue'] = Gst.ElementFactory.make('<wbr>queue')<br>    elements['mp4filesink'] = Gst.ElementFactory.make('<wbr>filesink')<br>    elements['mp4filesink'].set_<wbr>property('location', "{}.mp4".format(inc))<br><br>    pipeline_front.add(elements['<wbr>filesrc'])<br>    pipeline_front.add(elements['<wbr>matroskademux'])<br>    pipeline_front.add(elements['<wbr>h264parse'])<br>    pipeline_front.add(elements['<wbr>raw1queue'])<br>    pipeline_front.add(elements['<wbr>innersink'])<br><br>    pipeline_end.add(elements['<wbr>mp4appsrc'])<br>    pipeline_end.add(elements['<wbr>mp4h264parse'])<br>    pipeline_end.add(elements['<wbr>mp4queue'])<br>    pipeline_end.add(elements['<wbr>mp4mux'])<br>    pipeline_end.add(elements['<wbr>mp4mqueue'])<br>    pipeline_end.add(elements['<wbr>mp4filesink'])<br><br>    elements['filesrc'].link(<wbr>elements['matroskademux'])<br>    elements['matroskademux'].<wbr>link(elements['h264parse'])<br>    elements['h264parse'].link(<wbr>elements['raw1queue'])<br>    elements['raw1queue'].link(<wbr>elements['innersink'])<br><br>    elements['mp4appsrc'].link(<wbr>elements['mp4queue'])<br>    elements['mp4queue'].link(<wbr>elements['mp4h264parse'])<br>    elements['mp4h264parse'].link(<wbr>elements['mp4mux'])<br>    elements['mp4mux'].link(<wbr>elements['mp4mqueue'])<br>    elements['mp4mqueue'].link(<wbr>elements['mp4filesink'])<br><br>    pipeline_front.set_state(Gst.<wbr>State.READY)<br>    pipeline_front.set_state(Gst.<wbr>State.PAUSED)<br><br>    pipeline_end.set_state(Gst.<wbr>State.READY)<br>    pipeline_end.set_state(Gst.<wbr>State.PAUSED)<br>    pipeline_end.set_state(Gst.<wbr>State.PLAYING)<br>    print 'Front Setup Status:', pipeline_front.get_state(Gst.<wbr>CLOCK_TIME_NONE)[0]<br>    print 'Start', inc<br>    completed = False<br>    last = None<br>    while True:<br>        if not completed:<br>            pipeline_front.get_state(Gst.<wbr>CLOCK_TIME_NONE)[0]<br>            elements['innersink'].send_<wbr>event(Gst.Event.new_step(Gst.<wbr>Format.BUFFERS, 1, 1, True, False))<br>            inner_sample = elements['innersink'].emit('<wbr>pull-preroll')<br>            inner_buffer = inner_sample.get_buffer()<br>            elements['mp4appsrc'].set_<wbr>property('caps', inner_sample.get_caps())<br>            elements['mp4appsrc'].emit('<wbr>push-buffer', inner_buffer)<br><br>        # Check position for completion <br>        # Can't figure out how to tell there are no more frames<br>        pos = elements['innersink'].query_<wbr>position(Gst.Format.TIME)[1]<br>        dur = elements['innersink'].query_<wbr>duration(Gst.Format.TIME)[1]<br>        print 'Loc:', pos, dur<br><br>        if pos > dur:<br>            completed = True<br>        if pos == last:<br>            completed = True<br><br>        bus = pipeline_front.get_bus()<br>        while True:<br>            message = bus.pop_filtered(Gst.<wbr>MessageType.ANY)<br>            if not message:<br>                break<br>            elif message.type in [Gst.MessageType.EOS]:<br>                completed = True<br>                break<br><br>        # Close stream if completed <br>        if completed:<br>            elements['mp4appsrc'].emit('<wbr>end-of-stream')<br>            break<br>        last = pos<br></div><div><br>    pipeline_front.set_state(Gst.<wbr>State.NULL)<br>    pipeline_end.set_state(Gst.<wbr>State.NULL)<br>    print 'End', inc, pos, dur<br><br></div><div>test_file(0)<br></div><div></code><br></div><div><br></div>Thanks,<br></div>Brian<br><br><br></div>