Titanium JIRA Archive
Appcelerator Community (AC)

[AC-2501] Ti.Media.VideoPlayer stuck in VIDEO_PLAYBACK_STATE_SEEKING_*

GitHub Issuen/a
TypeBug
Priorityn/a
StatusResolved
ResolutionCannot Reproduce
Resolution Date2014-01-19T08:06:50.000+0000
Affected Version/sn/a
Fix Version/sn/a
ComponentsTitanium SDK & CLI
Labelsn/a
ReporterAlexander Ewering
AssigneeShak Hossain
Created2013-11-19T21:30:51.000+0000
Updated2016-03-08T07:41:33.000+0000

Description

As soon as the playback position of a running VideoPlayer is changed via setCurrentPlayBackTime(), its playbackState is permanently stuck in VIDEO_PLAYBACK_STATE_SEEKING_FORWARD or BACKWARD, depending on the last seeking direction. It never reverts to VIDEO_PLAYBACK_STATE_PLAYING. EDIT: It seems that once setCurrentPlaybackTime() has been used on a VideoPlayer, and then a new video is loaded via .url, it is completely impossible to start this video at position 0 (beginning). The new video, even if .setCurrentPlayBackTime(0) is used, and .stop() and again .play(), the new video will always start at the last seeked to position of the old video. Very odd. EDIT 2: The whole problem only seems to occur if a lot of setCurrentPlayBackTime() calls are executed - probably a race condition in Titanium itself. I have implemented my own seekbar for Video, and I'm using a setInterval at a rate of 200 milliseconds to update the video position while the user moves the slider. When I increase that interval to 1000 milliseconds, the problem goes away. Hope I could help :)

Comments

  1. Mauro Parra-Miranda 2013-11-21

    Hello Alexander! Please provide a minimal test case in order to move this bug to Platform. TIA! Best, Mauro
  2. Mostafizur Rahman 2013-11-23

    Hello [~mpmiranda], I have tested this issue with my test code. I didn’t reproduce this problem. It’s working good with my test code. If reporter post his test code and steps for reproduces. Then it’s really helpful.

    Testing environment:

    OS: MAC OS X 10.8.5 Ti SDK: 3.1.3 GA Ti CLI: 3.2.0 IOS simulator 7.0

    Test code

        var win = Ti.UI.createWindow({
       	backgroundColor : '#fff',
       
       });
       
       var options = {
       	top : 2,
       	url : '/etc/movie.mp4',
       	backgroundColor : '#111',
       	scalingMode : Titanium.Media.VIDEO_SCALING_MODE_FILL,
       	mediaControlStyle : Titanium.Media.VIDEO_CONTROL_DEFAULT // See TIMOB-2802, which may change this property name
       };
       
       if (Titanium.Platform.osname == "ipad") {
       	options.width = 400;
       	options.height = 300;
       }
       
       var activeMovie = Titanium.Media.createVideoPlayer(options);
       win.add(activeMovie);
       
       activeMovie.addEventListener('playbackState', function(e) {
       	Ti.API.info('Event PlaybackState Fired: ' + e.playbackState);
       });
       
       activeMovie.play();
       
       // Create a Button.
       var aButton = Ti.UI.createButton({
       	title : 'Button',
       	bottom : 0,
       });
       var tt = true;
       // Listen for click events.
       aButton.addEventListener('click', function() {
       	if (tt) {
       		activeMovie.url = '/etc/movie1.mp4';
       
       	} else {
       		activeMovie.url = '/etc/movie.mp4';
       	}
       	tt = tt === true ? true : false;
       
       	Ti.API.info('activeMovie.url' + activeMovie.url);
       	activeMovie.stop();
       
       	activeMovie.play();
       });
       
       // Add to the parent view.
       win.add(aButton);
       
       win.addEventListener('close', function() {
       	activeMovie.stop();
       });
       
       win.open();
       
       

    Step to test

    1. Create a new project 2. Paste test code in app.js 3. Now run on Simulator 7.0 4. Click on button for changing movie url h5. Expect Result/Actual Result It’s started from beginning. And playbackState also working well Thanks
  3. Mauro Parra-Miranda 2013-11-26

    Hello Alexander, can you please check the test case provided and let us know if this still fails for you? TIA! Best, Mauro
  4. Mauro Parra-Miranda 2013-11-26

    Will reopen if the provided test case still fails for the reporter.
  5. Alexander Ewering 2013-11-26

    Hi, sorry for not providing a testcase yet, I'm really busy. Your testcase doesn't contain the key component that leads to the bug: Rapidly using .setCurrentPlayBackTime(). Try adding the following code:
       
       var timesSet = 0;
       setInterval(function() {
           if ((timesSet++) < 100) {
               activeMovie.setCurrentPlaybackTime(Math.random() * 0.9);
           }
           if (timesSet == 200) {
               activeMovie.url = '/etc/movie1.mp4';
               activeMovie.stop();
               activeMovie.setCurrentPlaybackTime(0);
               activeMovie.play();
           }
           Ti.API.info(activeMovie.playbackState);
       }, 100);
       
       
    Add this code after initialization, and then please also try with an AUDIO file (mp3, wav). You'll probably see that even after 10 seconds (when the seeking stops), the movie will still be stuck in the SEEKING state, and after 20 seconds, the new movie / audio will not start at the beginning. (Code is not tested and just off the top of my head) Thanks
  6. Mauro Parra-Miranda 2013-11-26

    Hello Alexander, thanks for your last comment, we will review this again with that info to see if we can reproduce your issue. Best, Mauro
  7. Mostafizur Rahman 2013-11-27

    Hello, Please try out the updated sample as per your comments. Let us know if you continue to encounter the error.
       
       var win = Ti.UI.createWindow({
       	backgroundColor : '#fff',
       
       });
       
       var options = {
       	top : 2,
       	url : '/etc/black.mp3',
       	backgroundColor : '#111',
       	scalingMode : Titanium.Media.VIDEO_SCALING_MODE_FILL,
       	mediaControlStyle : Titanium.Media.VIDEO_CONTROL_DEFAULT // See TIMOB-2802, which may change this property name
       };
       
       if (Titanium.Platform.osname == "ipad") {
       	options.width = 400;
       	options.height = 300;
       }
       
       var activeMovie = Titanium.Media.createVideoPlayer(options);
       win.add(activeMovie);
       
       activeMovie.addEventListener('playbackState', function(e) {
       	Ti.API.info('Event PlaybackState Fired: ' + e.playbackState);
       });
       
       activeMovie.play();
       
       var timesSet = 0;
       setInterval(function() {
       	if ((timesSet++) < 100) {
       		activeMovie.setCurrentPlaybackTime(Math.random() * 0.9);
       	}
       	if (timesSet == 200) {
       		activeMovie.url = '/etc/black.mp3';
       		activeMovie.stop();
       		activeMovie.setCurrentPlaybackTime(0);
       		activeMovie.play();
       	}
       	Ti.API.info(activeMovie.playbackState);
       	Ti.API.info('timesSet ' + timesSet);
       }, 100);
       
       win.open();
       
       
    Thanks
  8. Alexander Ewering 2013-12-04

    Actually, I thought the unit passed to setCurrentPlaybackTime is normalized. Now I see it's milliseconds. Please change 'Math.random() * 0.9' to 'Math.random() * 10000' and use two WAV files (I used two different ones) that are each at least 10 seconds long. Mine were Stereo, 16 bit, 44.1 kHz. Indeed, the first WAV is stuck in playbackState '5' even after the seeking stops: ========================= [INFO] timesSet 98 [INFO] Event PlaybackState Fired: 5 [INFO] Event PlaybackState Fired: 4 [INFO] 5 [INFO] timesSet 99 [INFO] Event PlaybackState Fired: 5 [INFO] 4 [INFO] timesSet 100 [INFO] Event PlaybackState Fired: 4 [INFO] 4 [INFO] timesSet 101 [INFO] 4 [INFO] timesSet 102 [INFO] 4 [INFO] timesSet 103 [INFO] 4 [INFO] timesSet 104 [INFO] Event PlaybackState Fired: 5 [INFO] 5 [INFO] timesSet 105 [INFO] 5 [INFO] timesSet 106 [INFO] 5 [INFO] timesSet 107 [INFO] 5 [INFO] timesSet 108 [INFO] 5 [INFO] timesSet 109 [INFO] 5 [INFO] timesSet 110 [INFO] 5 [INFO] timesSet 111 ============================= (It should revert to 1) Now, in this testcase, the SECOND WAV (after changing the URL) doesn't exhibit the bug I described (doesn't start at the beginning), but I think the first bug (stuck in SEEKING state) is worth investigating.
  9. Mostafizur Rahman 2013-12-07

    Hello, I tested this issue the test code below. I can’t reproduce this issue. In my sample code, 1 have used all properties that reporter mentioned.

    Test Code

       var win = Ti.UI.createWindow({
       	backgroundColor : '#fff',
       
       });
       
       var options = {
       	top : 2,
       	url : '/etc/HugeWAV.wav',
       	backgroundColor : '#111',
       	scalingMode : Titanium.Media.VIDEO_SCALING_MODE_FILL,
       	mediaControlStyle : Titanium.Media.VIDEO_CONTROL_DEFAULT // See TIMOB-2802, which may change this property name
       };
       
       if (Titanium.Platform.osname == "ipad") {
       	options.width = 400;
       	options.height = 300;
       }
       
       var activeMovie = Titanium.Media.createVideoPlayer(options);
       win.add(activeMovie);
       
       activeMovie.addEventListener('playbackState', function(e) {
       	Ti.API.info('Event PlaybackState Fired: ' + e.playbackState);
       });
       
       activeMovie.play();
       
       var timesSet = 0;
       setInterval(function() {
       	if ((timesSet++) < 100) {
       		activeMovie.setCurrentPlaybackTime(Math.random() * 10000);
       	}
       	if (timesSet == 200) {
       		activeMovie.url = '/etc/test_stereo_44100Hz_16bit_PCM.wav';
       		activeMovie.stop();
       		activeMovie.setCurrentPlaybackTime(0);
       		activeMovie.play();
       	}
       	Ti.API.info(activeMovie.playbackState);
       	Ti.API.info('timesSet ' + timesSet);
       }, 100);
       
       win.open();
       
       

    Audio file list:

    http://download.wavetlan.com/SVV/Media/HTTP/test_stereo_44100Hz_16bit_PCM.wav

    http://download.wavetlan.com/SVV/Media/HTTP/HugeWAV.wav

    [INFO] : 0 [INFO] : timesSet 1 [INFO] : 0 [INFO] : timesSet 2 [INFO] : Event PlaybackState Fired: 1 [INFO] : 1 [INFO] : timesSet 3 [INFO] : Event PlaybackState Fired: 2 [INFO] : Event PlaybackState Fired: 1 [INFO] : 4 [INFO] : timesSet 4 [INFO] : Event PlaybackState Fired: 4 [INFO] : 4 [INFO] : timesSet 5 [INFO] : Event PlaybackState Fired: 1 [INFO] : 1 [INFO] : timesSet 6 [INFO] : Event PlaybackState Fired: 5 [INFO] : Event PlaybackState Fired: 1 [INFO] : 1 [INFO] : timesSet 7 [INFO] : Event PlaybackState Fired: 5 [INFO] : Event PlaybackState Fired: 1 [INFO] : 5 [INFO] : timesSet 8 [INFO] : Event PlaybackState Fired: 5 [INFO] : Event PlaybackState Fired: 1 [INFO] : 5 [INFO] : timesSet 9 [INFO] : Event PlaybackState Fired: 5 [INFO] : 5 [INFO] : timesSet 10 [INFO] : 5 [INFO] : timesSet 11 [INFO] : 4 [INFO] : timesSet 12 [INFO] : Event PlaybackState Fired: 4 [INFO] : 4 [INFO] : timesSet 13 [INFO] : 5 [INFO] : timesSet 14 [INFO] : Event PlaybackState Fired: 5 [INFO] : 4 [INFO] : timesSet 15 [INFO] : Event PlaybackState Fired: 4 [INFO] : 4 [INFO] : timesSet 16 [INFO] : 4 [INFO] : timesSet 17 [INFO] : 5 [INFO] : timesSet 18 [INFO] : Event PlaybackState Fired: 5 [INFO] : 5 [INFO] : timesSet 19 [INFO] : 5 [INFO] : timesSet 20 [INFO] : 5 [INFO] : timesSet 21 [INFO] : 4 [INFO] : timesSet 22 [INFO] : Event PlaybackState Fired: 4 [INFO] : 4 [INFO] : timesSet 23 [INFO] : 4 [INFO] : timesSet 24 [INFO] : 5 [INFO] : timesSet 25 [INFO] : Event PlaybackState Fired: 5 [INFO] : 4 [INFO] : timesSet 26 [INFO] : Event PlaybackState Fired: 4 [INFO] : Event PlaybackState Fired: 5 [INFO] : 5 [INFO] : timesSet 27 [INFO] : 4 [INFO] : timesSet 28 [INFO] : Event PlaybackState Fired: 4 [INFO] : 5 [INFO] : timesSet 29 [INFO] : Event PlaybackState Fired: 5 [INFO] : 4 [INFO] : timesSet 30 [INFO] : Event PlaybackState Fired: 4 [INFO] : 4 [INFO] : timesSet 31 [INFO] : 4 [INFO] : timesSet 32 [INFO] : 5 [INFO] : timesSet 33 [INFO] : Event PlaybackState Fired: 5 [INFO] : 5 [INFO] : timesSet 34 [INFO] : 5 [INFO] : timesSet 35 [INFO] : 5 [INFO] : timesSet 36 [INFO] : 4 [INFO] : timesSet 37 [INFO] : Event PlaybackState Fired: 4 [INFO] : 4 [INFO] : timesSet 38 [INFO] : 5 [INFO] : timesSet 39 [INFO] : Event PlaybackState Fired: 5 [INFO] : 5 [INFO] : timesSet 40 [INFO] : 5 [INFO] : timesSet 41 [INFO] : 4 [INFO] : timesSet 42 [INFO] : Event PlaybackState Fired: 4 [INFO] : 4 [INFO] : timesSet 43 [INFO] : 4 [INFO] : timesSet 44 [INFO] : 4 [INFO] : timesSet 45 [INFO] : 4 [INFO] : timesSet 46 [INFO] : 4 [INFO] : timesSet 47 [INFO] : 4 [INFO] : timesSet 48 [INFO] : 5 [INFO] : timesSet 49 [INFO] : Event PlaybackState Fired: 5 [INFO] : 4 [INFO] : timesSet 50 [INFO] : Event PlaybackState Fired: 4 [INFO] : 5 [INFO] : timesSet 51 [INFO] : Event PlaybackState Fired: 5 [INFO] : Event PlaybackState Fired: 4 [INFO] : 5 [INFO] : timesSet 52 [INFO] : Event PlaybackState Fired: 5 [INFO] : 5 [INFO] : timesSet 53 [INFO] : 5 [INFO] : timesSet 54 [INFO] : 4 [INFO] : timesSet 55 [INFO] : Event PlaybackState Fired: 4 [INFO] : 4 [INFO] : timesSet 56 [INFO] : 5 [INFO] : timesSet 57 [INFO] : Event PlaybackState Fired: 5 [INFO] : 5 [INFO] : timesSet 58 [INFO] : 5 [INFO] : timesSet 59 [INFO] : 5 [INFO] : timesSet 60 [INFO] : 5 [INFO] : timesSet 61 [INFO] : 4 [INFO] : timesSet 62 [INFO] : Event PlaybackState Fired: 4 [INFO] : 4 [INFO] : timesSet 63 [INFO] : 4 [INFO] : timesSet 64 [INFO] : 4 [INFO] : timesSet 65 [INFO] : 4 [INFO] : timesSet 66 [INFO] : 5 [INFO] : timesSet 67 [INFO] : Event PlaybackState Fired: 5 [INFO] : 4 [INFO] : timesSet 68 [INFO] : Event PlaybackState Fired: 4 [INFO] : 4 [INFO] : timesSet 69 [INFO] : 4 [INFO] : timesSet 70 [INFO] : 4 [INFO] : timesSet 71 [INFO] : 5 [INFO] : timesSet 72 [INFO] : Event PlaybackState Fired: 5 [INFO] : 5 [INFO] : timesSet 73 [INFO] : 5 [INFO] : timesSet 74 [INFO] : 4 [INFO] : timesSet 75 [INFO] : Event PlaybackState Fired: 4 [INFO] : 5 [INFO] : timesSet 76 [INFO] : Event PlaybackState Fired: 5 [INFO] : Event PlaybackState Fired: 4 [INFO] : 4 [INFO] : timesSet 77 [INFO] : 4 [INFO] : timesSet 78 [INFO] : 5 [INFO] : timesSet 79 [INFO] : Event PlaybackState Fired: 5 [INFO] : 5 [INFO] : timesSet 80 [INFO] : 5 [INFO] : timesSet 81 [INFO] : 4 [INFO] : timesSet 82 [INFO] : Event PlaybackState Fired: 4 [INFO] : 4 [INFO] : timesSet 83 [INFO] : 4 [INFO] : timesSet 84 [INFO] : 4 [INFO] : timesSet 85 [INFO] : 5 [INFO] : timesSet 86 [INFO] : Event PlaybackState Fired: 5 [INFO] : Event PlaybackState Fired: 4 [INFO] : 4 [INFO] : timesSet 87 [INFO] : 4 [INFO] : timesSet 88 [INFO] : 4 [INFO] : timesSet 89 [INFO] : 5 [INFO] : timesSet 90 [INFO] : Event PlaybackState Fired: 5 [INFO] : 4 [INFO] : timesSet 91 [INFO] : Event PlaybackState Fired: 4 [INFO] : Event PlaybackState Fired: 5 [INFO] : 5 [INFO] : timesSet 92 [INFO] : 4 [INFO] : timesSet 93 [INFO] : Event PlaybackState Fired: 4 [INFO] : 5 [INFO] : timesSet 94 [INFO] : Event PlaybackState Fired: 5 [INFO] : 4 [INFO] : timesSet 95 [INFO] : Event PlaybackState Fired: 4 [INFO] : 4 [INFO] : timesSet 96 [INFO] : 4 [INFO] : timesSet 97 [INFO] : 5 [INFO] : timesSet 98 [INFO] : Event PlaybackState Fired: 5 [INFO] : 5 [INFO] : timesSet 99 [INFO] : 5 [INFO] : timesSet 100 [INFO] : 5 [INFO] : timesSet 101 [INFO] : 5 [INFO] : timesSet 102 [INFO] : 5 [INFO] : timesSet 103 [INFO] : 5 [INFO] : timesSet 104 .............. [INFO] : 5 [INFO] : timesSet 194 [INFO] : 5 [INFO] : timesSet 195 [INFO] : 5 [INFO] : timesSet 196 [INFO] : 5 [INFO] : timesSet 197 [INFO] : 5 [INFO] : timesSet 198 [INFO] : 5 [INFO] : timesSet 199 [INFO] : 5 [INFO] : timesSet 200 [INFO] : Event PlaybackState Fired: 0 [INFO] : Event PlaybackState Fired: 1 [INFO] : Event PlaybackState Fired: 2 [INFO] : Event PlaybackState Fired: 1 [INFO] : 1

    Expect Result/Actual Result

    It’s started from beginning. And playbackState also working well

    Note:

    As per our code logic playback state will "1" when timesSet is equal to 200 not in 110 Thanks
  10. Ritu Agrawal 2013-12-10

    [~aewering] We have tried to reproduce the problem based on your description and we still cannot reproduce it as per the sample and log above. Can you please try out the sample listed here and see if you can reproduce the problem? It would help us narrow down the reported issue.
  11. Alexander Ewering 2013-12-10

    Sorry, but why in the world would "playbackState" be in "SEEKING" several seconds or minutes after I have seeked the last time? I don't get it. Isn't "playbackState" supposed to be telling me the... uhm... CURRENT playbackState, not the one from seconds or minutes ago? The code stops seeking after 100 iterations. Yet, playbackState is STILL in "SEEKING" after 200 iterations. So, it is not a reliable indicator of the current state of playback. If this is your code's logic, then it is wrong.
  12. Mostafizur Rahman 2013-12-22

    Hi Alexander, We tested this issue but unable to reproduce it. Please check our code and send us a complete test code that we can try. Perhaps here is a discrepancies on what we are testing and you implementation. https://gist.github.com/csemrm/8079532

JSON Source