Frame Stepping
Brian Panneton
brian.panneton at gmail.com
Thu Aug 11 21:10:15 UTC 2016
All,
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.
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.
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: http://jell.yfish.us/media/
jellyfish-25-mbps-hd-h264.mkv
<code>
from gi.repository import Gst, GObject
import sys
import os
import glob
def test_file(inc):
filename = "jellyfish-25-mbps-hd-h264.mkv"
elements = {}
def demuxer_callback(demuxer, pad):
if pad.get_property("template").name_template == "video_%u":
pad.link(elements['h264parse'].get_static_pad("sink"))
#GObject.threads_init()
Gst.init()
Gst.debug_set_active(True)
Gst.debug_set_default_threshold(1)
pipeline_front = Gst.Pipeline()
pipeline_end = Gst.Pipeline()
elements['filesrc'] = Gst.ElementFactory.make('filesrc',
str(inc)+'_filesrc')
elements['filesrc'].set_property('location', filename)
elements['matroskademux'] = Gst.ElementFactory.make('matroskademux',
str(inc)+'_matroskademux')
elements['matroskademux'].connect('pad-added', demuxer_callback)
elements['h264parse'] = Gst.ElementFactory.make('h264parse',
str(inc)+'_h264parse')
elements['raw1queue'] = Gst.ElementFactory.make('queue',
str(inc)+'_raw1queue')
elements['innersink'] = Gst.ElementFactory.make('appsink',
str(inc)+'_appsink')
elements['mp4appsrc'] = Gst.ElementFactory.make('appsrc')
elements['mp4h264parse'] = Gst.ElementFactory.make('h264parse')
elements['mp4queue'] = Gst.ElementFactory.make('queue')
elements['mp4mux'] = Gst.ElementFactory.make('mp4mux')
elements['mp4mqueue'] = Gst.ElementFactory.make('queue')
elements['mp4filesink'] = Gst.ElementFactory.make('filesink')
elements['mp4filesink'].set_property('location', "{}.mp4".format(inc))
pipeline_front.add(elements['filesrc'])
pipeline_front.add(elements['matroskademux'])
pipeline_front.add(elements['h264parse'])
pipeline_front.add(elements['raw1queue'])
pipeline_front.add(elements['innersink'])
pipeline_end.add(elements['mp4appsrc'])
pipeline_end.add(elements['mp4h264parse'])
pipeline_end.add(elements['mp4queue'])
pipeline_end.add(elements['mp4mux'])
pipeline_end.add(elements['mp4mqueue'])
pipeline_end.add(elements['mp4filesink'])
elements['filesrc'].link(elements['matroskademux'])
elements['matroskademux'].link(elements['h264parse'])
elements['h264parse'].link(elements['raw1queue'])
elements['raw1queue'].link(elements['innersink'])
elements['mp4appsrc'].link(elements['mp4queue'])
elements['mp4queue'].link(elements['mp4h264parse'])
elements['mp4h264parse'].link(elements['mp4mux'])
elements['mp4mux'].link(elements['mp4mqueue'])
elements['mp4mqueue'].link(elements['mp4filesink'])
pipeline_front.set_state(Gst.State.READY)
pipeline_front.set_state(Gst.State.PAUSED)
pipeline_end.set_state(Gst.State.READY)
pipeline_end.set_state(Gst.State.PAUSED)
pipeline_end.set_state(Gst.State.PLAYING)
print 'Front Setup Status:', pipeline_front.get_state(Gst.
CLOCK_TIME_NONE)[0]
print 'Start', inc
completed = False
last = None
while True:
if not completed:
pipeline_front.get_state(Gst.CLOCK_TIME_NONE)[0]
elements['innersink'].send_event(Gst.Event.new_step(Gst.Format.BUFFERS,
1, 1, True, False))
inner_sample = elements['innersink'].emit('pull-preroll')
inner_buffer = inner_sample.get_buffer()
elements['mp4appsrc'].set_property('caps',
inner_sample.get_caps())
elements['mp4appsrc'].emit('push-buffer', inner_buffer)
# Check position for completion
# Can't figure out how to tell there are no more frames
pos = elements['innersink'].query_position(Gst.Format.TIME)[1]
dur = elements['innersink'].query_duration(Gst.Format.TIME)[1]
print 'Loc:', pos, dur
if pos > dur:
completed = True
if pos == last:
completed = True
bus = pipeline_front.get_bus()
while True:
message = bus.pop_filtered(Gst.MessageType.ANY)
if not message:
break
elif message.type in [Gst.MessageType.EOS]:
completed = True
break
# Close stream if completed
if completed:
elements['mp4appsrc'].emit('end-of-stream')
break
last = pos
pipeline_front.set_state(Gst.State.NULL)
pipeline_end.set_state(Gst.State.NULL)
print 'End', inc, pos, dur
test_file(0)
</code>
Thanks,
Brian
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/gstreamer-devel/attachments/20160811/07fc4dc6/attachment-0001.html>
More information about the gstreamer-devel
mailing list