GNOME Bugzilla – Bug 619204
Framestepping backwards sometimes doesn't work on MPEG-2 files.
Last modified: 2013-03-09 17:49:16 UTC
The playbin2 doesn't react on the new_step events when paused. Current playing position, reported by _query_position doesn't change. The displayed picture doesn't change also. Framestepping forward is OK. 0. GStreamer is initialized with the keys --gst-debug=player:5,mpegpsdemux:3 where player is my private debug category. 1. My application creates the playbin2 instance to play the file. It successfully opens and plays. 2. I pause the playbin2. 3. I position a playbin2 somewhere in the movie by clicking on a movie progress bar on my form. This issues the call r=gst_element_seek_simple(GST_ELEMENT(m_player), GST_FORMAT_TIME, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH|GST_SEEK_FLAG_KEY_UNIT), pos*GST_MSECOND); where pos is the seek position. GST_DEBUG rigth after this shows that r=1 (seek is successful), I also observe the changing picture. Debug shows the following. 0:00:11.316272000 3952 003D9118 INFO mpegpsdemux gstmpegdemux.c:1060:gst_flups_demux_do_seek:<mpegpsdemux0> sink segment configured 0409D880, trying to go at SCR: 5535000 0:00:11.326286000 3952 003D9118 INFO mpegpsdemux gstmpegdemux.c:1082:gst_flups_demux_do_seek:<mpegpsdemux0> doing seek at offset 42065920 SCR: 5534990 0:01:01.499888888 0:00:11.346315000 3952 003D9118 DEBUG player gst_player.cpp:911:gst_player::set_position: direction=1, seek to 61500 msec, r=1 0:00:11.356329000 3952 040A06C0 INFO mpegpsdemux gstmpegdemux.c:533:gst_flups_demux_send_data:<mpegpsdemux0> sending new segment: rate 1 applied_rate 1 start: 0:01:01.500011111, stop: 99:99:99.999999999, time: 0:01:01.500000000 to pad 0401E668 0:00:11.356329000 3952 040A06C0 INFO mpegpsdemux gstmpegdemux.c:533:gst_flups_demux_send_data:<mpegpsdemux0> sending new segment: rate 1 applied_rate 1 start: 0:01:01.500011111, stop: 99:99:99.999999999, time: 0:01:01.500000000 to pad 0401EA50 0:00:11.486517000 3952 0404AEE0 DEBUG player gst_player.cpp:330:gst_player::bus_watch: message async-done(2097152) from playbin0 0:00:11.486517000 3952 0404AEE0 DEBUG player gst_player.cpp:334:gst_player::bus_watch: current player position 61500ms 0:00:11.526574000 3952 0404AEE0 DEBUG player gst_player.cpp:341:gst_player::bus_watch: current segment: rate 1.000000 fmt 3 start 61500011111 stop -1 direction 1 4. I press "step left" button on my player's window. This issues the call to my step_left() function void gst_player::step_left(void) {GstFormat fmt=GST_FORMAT_TIME; gboolean rb; if(m_player){ if(m_current_position>=40*GST_MSECOND){ if(m_direction>0) { m_direction=-1; flag_set(FLAG_STEP_LEFT1); rb=gst_element_seek(m_player,-1.0,GST_FORMAT_TIME, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH|GST_SEEK_FLAG_ACCURATE), GST_SEEK_TYPE_SET,0,GST_SEEK_TYPE_SET,m_current_position); GST_DEBUG("seek backwards: %d",rb); }else{ rb=gst_element_send_event (m_player, gst_event_new_step (GST_FORMAT_BUFFERS, 1, 1.0, TRUE, FALSE)); GST_DEBUG("send step event: %d",rb); } } } } This function tracks current playback direction, if it doesn't match, it sends the seek event to turn the player to backwards playback. The bus_watch watches for the async-done messages, checks the application's internal flags and basing on them decides what caused the async-done message and what to do next. Here is the relevant code from my bus-watch. case GST_MESSAGE_ASYNC_DONE:{ GST_DEBUG("message %s(%d) from %s", GST_MESSAGE_TYPE_NAME(msg),GST_MESSAGE_TYPE(msg),GST_MESSAGE_SRC_NAME(msg)); GstFormat fmt=GST_FORMAT_TIME; gst_element_query_position(m_player,&fmt,&m_current_position); GST_DEBUG("current player position %dms",GST_TIME_AS_MSECONDS(m_current_position)); GstQuery *query=gst_query_new_segment(GST_FORMAT_TIME); gst_element_query(GST_ELEMENT(m_player),query); gdouble rate; gint64 start=-1,stop=-1; gst_query_parse_segment(query,&rate,&fmt,&start,&stop); GST_DEBUG("current segment: rate %lf fmt %d start %"G_GINT64_FORMAT " stop %"G_GINT64_FORMAT" direction %d",rate,fmt,start,stop,m_direction); gst_query_unref(query); if(m_flags & FLAG_GO_END){ flag_unset(FLAG_GO_END); /* ... */ }else if(m_flags & FLAG_STEP_LEFT1){ flag_unset(FLAG_STEP_LEFT1); GST_DEBUG("flag_unset(FLAG_STEP_LEFT1);"); rb=gst_element_send_event (m_player, gst_event_new_step (GST_FORMAT_BUFFERS, 1, 1.0, TRUE, FALSE)); GST_DEBUG("send step event: %d",rb); } } Here is the debug output, resulted by several presses of the step_left button 0:10:32.509504000 3952 003D9118 INFO mpegpsdemux gstmpegdemux.c:1060:gst_flups_demux_do_seek:<mpegpsdemux0> sink segment configured 0409D880, trying to go at SCR: 5535000 0:10:32.519518000 3952 003D9118 INFO mpegpsdemux gstmpegdemux.c:1082:gst_flups_demux_do_seek:<mpegpsdemux0> doing seek at offset 42065920 SCR: 5534990 0:01:01.499888888 0:10:32.519518000 3952 003D9118 DEBUG player gst_player.cpp:940:gst_player::step_left: seek backwards: 1 0:10:32.519518000 3952 040A06C0 INFO mpegpsdemux gstmpegdemux.c:533:gst_flups_demux_send_data:<mpegpsdemux0> sending new segment: rate -1 applied_rate 1 start: 0:00:00.000011111, stop: 0:01:01.500011111, time: 0:00:00.000000000 to pad 0401E668 0:10:32.990195000 3952 0404AEE0 DEBUG player gst_player.cpp:330:gst_player::bus_watch: message async-done(2097152) from playbin0 0:10:32.990195000 3952 0404AEE0 DEBUG player gst_player.cpp:334:gst_player::bus_watch: current player position 61500ms 0:10:32.990195000 3952 0404AEE0 DEBUG player gst_player.cpp:341:gst_player::bus_watch: current segment: rate -1.000000 fmt 3 start 11111 stop 61500011111 direction -1 0:10:32.990195000 3952 0404AEE0 DEBUG player gst_player.cpp:354:gst_player::bus_watch: flag_unset(FLAG_STEP_LEFT1); 0:10:32.990195000 3952 0404AEE0 DEBUG player gst_player.cpp:356:gst_player::bus_watch: send step event: 1 0:10:33.000209000 3952 0404AEE0 DEBUG player gst_player.cpp:330:gst_player::bus_watch: message async-done(2097152) from playbin0 0:10:33.000209000 3952 0404AEE0 DEBUG player gst_player.cpp:334:gst_player::bus_watch: current player position 61500ms 0:10:33.000209000 3952 0404AEE0 DEBUG player gst_player.cpp:341:gst_player::bus_watch: current segment: rate -1.000000 fmt 3 start 11111 stop 61500011111 direction -1 0:14:59.793840000 3952 003D9118 DEBUG player gst_player.cpp:943:gst_player::step_left: send step event: 1 0:14:59.803854000 3952 0404AEE0 DEBUG player gst_player.cpp:330:gst_player::bus_watch: message async-done(2097152) from playbin0 0:14:59.803854000 3952 0404AEE0 DEBUG player gst_player.cpp:334:gst_player::bus_watch: current player position 61500ms 0:14:59.803854000 3952 0404AEE0 DEBUG player gst_player.cpp:341:gst_player::bus_watch: current segment: rate -1.000000 fmt 3 start 11111 stop 61500011111 direction -1 0:15:02.467685000 3952 003D9118 DEBUG player gst_player.cpp:943:gst_player::step_left: send step event: 1 0:15:02.467685000 3952 0404AEE0 DEBUG player gst_player.cpp:330:gst_player::bus_watch: message async-done(2097152) from playbin0 0:15:02.467685000 3952 0404AEE0 DEBUG player gst_player.cpp:334:gst_player::bus_watch: current player position 61500ms 0:15:02.467685000 3952 0404AEE0 DEBUG player gst_player.cpp:341:gst_player::bus_watch: current segment: rate -1.000000 fmt 3 start 11111 stop 61500011111 direction -1 0:15:05.191601000 3952 003D9118 DEBUG player gst_player.cpp:943:gst_player::step_left: send step event: 1 0:15:05.191601000 3952 0404AEE0 DEBUG player gst_player.cpp:330:gst_player::bus_watch: message async-done(2097152) from playbin0 0:15:05.191601000 3952 0404AEE0 DEBUG player gst_player.cpp:334:gst_player::bus_watch: current player position 61500ms 0:15:05.191601000 3952 0404AEE0 DEBUG player gst_player.cpp:341:gst_player::bus_watch: current segment: rate -1.000000 fmt 3 start 11111 stop 61500011111 direction -1 As can be seen, current position remains at 61500ms, the displayed picture doesn't change. I repeat, m_player is the playbin2, and is paused. If I increase the mpegdemux debug level, then it can be seen that it parses the file after the direction was changed to backwards.
*** Bug 622262 has been marked as a duplicate of this bug. ***
I can provide a sample video file, where this problem occurs. But it's at least 10Mb, so, I need a special permission to do so, to avoid wastes of the disk space.
The same behavior can be seen with the seek example, both on windows and linux. This issue doesn't depend on video sink. More simple chains, built with parse_launch, not including playbin2, successfully do the reverse framestepping and even playback. Therefore, the problem is somewhere in the playbin2 or components it includes.
In my tests, framestepping for MPEG-PS and MPEG-2 video work fine. The problems come from the audio chain, because mpegaudioparse and friends don't implement backwards playback. I'm attaching a hacky patch that makes it work somewhat, but the real fix is to write correct backwards playback and sample reversing code for mpegaudioparse and mad.
Created attachment 167600 [details] [review] hacky fix to somewhat support backwards play in mpegaudioparse
Could you retest this with the new mpegaudioparse element in -bad in git (from -bad/gst/audioparsers/).
It doesn't build right now. CC libgstaudioparsersbad_la-gstac3parse.lo cc1: warnings being treated as errors gstac3parse.c: In function ‘gst_ac3_parse_frame_header’: gstac3parse.c:357: error: ‘sync’ may be used uninitialized in this function gstac3parse.c:358: error: ‘bsid’ may be used uninitialized in this function gstac3parse.c:257: error: ‘frmsizcod’ may be used uninitialized in this function gstac3parse.c:257: note: ‘frmsizcod’ was declared here gstac3parse.c:257: error: ‘fscod’ may be used uninitialized in this function gstac3parse.c:257: note: ‘fscod’ was declared here gstac3parse.c:257: error: ‘bsid’ may be used uninitialized in this function gstac3parse.c:257: note: ‘bsid’ was declared here gstac3parse.c:257: error: ‘acmod’ may be used uninitialized in this function gstac3parse.c:257: note: ‘acmod’ was declared here gstac3parse.c:257: error: ‘lfe_on’ may be used uninitialized in this function gstac3parse.c:257: note: ‘lfe_on’ was declared here gstac3parse.c:307: error: ‘strmtyp’ may be used uninitialized in this function gstac3parse.c:307: note: ‘strmtyp’ was declared here gstac3parse.c:307: error: ‘strmid’ may be used uninitialized in this function gstac3parse.c:307: note: ‘strmid’ was declared here gstac3parse.c:306: error: ‘frmsiz’ may be used uninitialized in this function gstac3parse.c:306: note: ‘frmsiz’ was declared here gstac3parse.c:307: error: ‘fscod’ may be used uninitialized in this function gstac3parse.c:307: note: ‘fscod’ was declared here gstac3parse.c:307: error: ‘fscod2’ may be used uninitialized in this function gstac3parse.c:307: note: ‘fscod2’ was declared here gstac3parse.c:307: error: ‘numblkscod’ may be used uninitialized in this function gstac3parse.c:307: note: ‘numblkscod’ was declared here gstac3parse.c:307: error: ‘acmod’ may be used uninitialized in this function gstac3parse.c:307: note: ‘acmod’ was declared here gstac3parse.c:307: error: ‘lfe_on’ may be used uninitialized in this function gstac3parse.c:307: note: ‘lfe_on’ was declared here
Added some '=0' to fix these errors. This works, but not stable. Hereis the file: http://dl.dropbox.com/u/11507187/5417.mpg Sometimes it steps back, sometimes not.
Fresh OSSBuild, everything builds. Framestepping still doesn't work always.
File no longer exists, and I don't appear to have a copy anywhere. Vladimir: is this still an issue with 1.0.x ?
Unfortunately, I cannot answer, because I've left that project and the whole company, where I held that project.
Closing this bug report as no further information has been provided. Please feel free to reopen this bug if you can provide the information asked for. Thanks!