How to keep record of the current frame when playing video?

Marcus Nascimento marcus.cps at gmail.com
Tue Nov 12 06:00:24 PST 2013


Sorry, I hit send accidentally.

I think I managed to do that.

I'm using GStreamer 0.10 targeting an embedded environment.
But, for now, I'm testing it in a PC running Arch Linux.

The formats I'm using are: Ogg Vorbis (Audio/Video), Mp3 and H.264.

That's my solution:

To set the start time, I do this (when entered the PAUSE state):
GstEvent *ev = gst_event_new_step(GST_FORMAT_TIME, startTimePosition, 1.0,
TRUE, FALSE);
 gst_element_send_event(pipeline, ev);

Just change the event creation instruction when creating SAMPLE and FRAME
events:
GstEvent *ev = gst_event_new_step(GST_FORMAT_DEFAULT, startSamplePosition,
1.0, TRUE, FALSE);
 GstEvent *ev = gst_event_new_step(GST_FORMAT_BUFFERS, startFramePosition,
1.0, TRUE, FALSE);

To get the current frame, I intercept GST_MESSAGE_QOS and increment the
current frame.
So, in the bus callback, I use something like this:

switch (GST_MESSAGE_TYPE (msg)) {
 case GST_MESSAGE_QOS: {
++currentFrame;
 break;
}
case GST_MESSAGE_STEP_DONE: {
 GstFormat format;
guint64 amount;
 gdouble rate;
gboolean flush, intermediate;
 guint64 duration;
gboolean eos;
 gst_message_parse_step_done (msg, &format, &amount, &rate, &flush,
&intermediate, &duration, &eos);
 timeOffset = duration;
break;
 }
default:
 break;
}

To keep counting the current frame, I do something like this (when entered
the READY state):

GstElement *videoSink = gst_bin_get_by_name(GST_BIN(pipeline), "videosink");
 GstPad *videoSinkPad = gst_element_get_static_pad(videoSink, "sink");
 bufferProbeID = gst_pad_add_buffer_probe(videoSinkPad, (GCallback)
IncCurrentFrame, NULL);

The IncCurrentFrame function simply increments the currentFrame variable.

This way, frame alarms can compare the current frame to their target frames
using a pad probe (same logics used above).
Every Frame alarm adds a buffer probe and the callback simply does the
comparing.

The difference in frame numbers were related to dropped packages. That's
why is necessary to keep counting QOS messages after finishing the STEP
phase.
This solution seems to work well.

The timeOffset set in the STEP_DONE event is used by Time Alarms and Frame
alarms.
I register single shot clock_id's as soon as I enter the PLAYING state. Do
you think it is a good solution? Time seems to be accurate.

Sample alarms fall back to the TIME implementation, since I use the RATE
(got from caps) to convert Samples to time.

Do you think I'm going to have trouble with something in the future?

I provided as much details as I'm allowed to. Sorry if it is confusing.


Thanks very much for your answer.
I appreciate that.

Marcus


On Tue, Nov 12, 2013 at 11:25 AM, Sebastian Dröge <sebastian at centricular.com
> wrote:

> On Mo, 2013-11-11 at 18:56 -0200, Marcus Nascimento wrote:
> > I'm working on a media platform and I have to implement a wrapper to
> > GStreamer that offers the following interface:
> >
> > - SetStartTime: Set the start position (in time)
> > - SetEndTime: Set the end position (in time)
> > - SetStartFrame: Set the start position (in frames)
> > - SetEndFrame: Set the end position (in frames)
> > - SetStartSample: Set the start position (in samples)
> > - SetEndSample: Set the end position (in samples)
> > - AddTimeAlarm: A listener will be notified when a given time is reached.
> > - AddFrameAlarm: A listener will be notified when a given frame is
> reached.
> > - AddSampleAlarm: A listener will be notified when a given sample is
> > reached.
> >
> > I'll never play streamming media nor remote media, but only local files.
> >
> > The biggest problem up to now cames from the fact it is possible to set
> > Start/End position in time, and add frame alarms, for instance.
> >
> > I'm using STEP events to set the start position. It is just a matter of
> > using gst_event_new_step passing the right parameters for that
> > (GST_FORMAT_TIME for time, GST_FORMAT_DEFAULT for samples and
> > GST_FORMAT_BUFFERS for frames).
> >
> > In any case, I need to know which frame corresponds to the step
> destination.
> > To do that, I'm incrementing the frame counter everytime I receive a QOS
> > message durring the STEP execution. I do that until I receive a STEP_DONE
> > message. By that time, I know what is the current time and current frame.
> > It seems to work fine. Does anyone know if that is not correct?
> >
> > After the STEP is complete, I'm using a pad probe (buffer probe) to keep
> > counting the frames.
> > This way, I can know for sure when a frame alarm has expired.
> >
> > Strange thing is: When I set the StartFrame to 300, the corresponding
> time
> > is a little after 9s.
> > But, when I schedule an alarm to the same frame 300, the corresponding
> time
> > is around 7s.
> > It is very strange for me.
> >
> > Can anyone help me understanding what's going on?
>
> It would be useful to have some test case to explain what exactly you do
> how and to have a way to reproduce it. Also which file formats are you
> using and which GStreamer version on which platform? :)
>
> How do you get "the corresponding time" when you do StartFrame(300)? And
> how for the alarms? The alarms are counting the frames via a pad probe
> and you get the buffer timestamp from there?
>
> --
> Sebastian Dröge <sebastian at centricular.com>
> Centricular Ltd - http://www.centricular.com
> Expertise, Straight from the Source
>
> _______________________________________________
> gstreamer-devel mailing list
> gstreamer-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
>
>


-- 
Marcus Nascimento
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/gstreamer-devel/attachments/20131112/6d3f9823/attachment.html>


More information about the gstreamer-devel mailing list