Switching video playback streams


7 posts
by mji » Sat Jul 07, 2012 1:01 am
Working off the hello_video example, I'm trying to figure out how to cleanly switch between video sources. I've already gotten the example to load multiple files and switch between them on command... the issue is that the video_decode component seems to buffer a few seconds of video... I want to clear it out and immediately begin playing from the new stream. I tried sending a buffer flush command to video_decode, but that just seems to freeze the video up and when i put more data into the buffer, nothing happens.

There doesn't really seem to be any great documentation on OpenMax (and none at all on this ilclient helper library that it uses), so I have no idea if my approach is fundamentally correct. Should I be creating multiple video_decode components and switching between them by re-setting up the tunnels?

Does anyone have an example of something like this or can suggest an appropriate way to go about doing this in OpenMax?
Thanks,
Michael
Posts: 16
Joined: Sat Jul 07, 2012 12:51 am
Location: Los Angeles, California
by mji » Tue Jul 10, 2012 11:14 pm
After many hours of trial and error, I got it working properly by doing the following: first, flushing the input/outpus of the video_decode component. Then, making sure that I actually wait for those operations to complete. Then, setting the clock state to Stopped. Then, setting the clock state to WaitingForStartTime. Finally, in the first packet of data sent to the decoder, I have to set the OMX_BUFFERFLAG_STARTTIME.

This seems to pretty much work correctly....
Posts: 16
Joined: Sat Jul 07, 2012 12:51 am
Location: Los Angeles, California
by jole » Wed Jul 18, 2012 7:23 am
Would you mind sharing your code on this? I'm very interested in flexible video playback on the pi.
Posts: 4
Joined: Thu Jun 14, 2012 8:17 am
Location: Edmonton, AB
by mji » Thu Jul 19, 2012 9:29 pm
To demonstrate the idea... launch a separate thread to listen for some sort of input and raise a flag in response.At the top of the main loop in the video.c sample program, put in a conditional statement that executes the following code when the flag is raised. This code will clear out the video buffer and prepare for a new stream:
Code: Select all
OMX_SendCommand(ILC_GET_HANDLE(video_decode),OMX_CommandFlush,130,NULL);
         OMX_SendCommand(ILC_GET_HANDLE(video_decode),OMX_CommandFlush,131,NULL);
      
            ilclient_wait_for_event(video_decode, OMX_EventCmdComplete, OMX_CommandFlush, 0, 130, 0, ILCLIENT_PORT_FLUSH, -1);
            ilclient_wait_for_event(video_decode, OMX_EventCmdComplete, OMX_CommandFlush, 0, 131, 0, ILCLIENT_PORT_FLUSH, -1);

            
           data_len=0;       
          
          memset(&cstate, 0, sizeof(cstate));
          cstate.nSize = sizeof(cstate);
          cstate.nVersion.nVersion = OMX_VERSION;
          cstate.eState = OMX_TIME_ClockStateStopped;
          cstate.nWaitMask = 1;
                  errorCode= OMX_SetParameter(ILC_GET_HANDLE(clock), OMX_IndexConfigTimeClockState, &cstate);
                  
          memset(&cstate, 0, sizeof(cstate));
          cstate.nSize = sizeof(cstate);
          cstate.nVersion.nVersion = OMX_VERSION;
          cstate.eState = OMX_TIME_ClockStateWaitingForStartTime;
          cstate.nWaitMask = 1;
                  errorCode= OMX_SetParameter(ILC_GET_HANDLE(clock), OMX_IndexConfigTimeClockState, &cstate);
              ilclient_change_component_state(clock, OMX_StateExecuting);
           first_packet = 1;
           rewind(in);


The last line simply rewinds the current file, but you could instead open up a different file. To achieve smooth playback, you might have to buffer some of the file in memory, but this should be enough to get you started.
Posts: 16
Joined: Sat Jul 07, 2012 12:51 am
Location: Los Angeles, California
by mji » Thu Jul 19, 2012 10:06 pm
Oh... and there's one more trick... at the end of the loop there's a line that reads as follows:
Code: Select all
ilclient_wait_for_event(video_render, OMX_EventBufferFlag, 90, 0, OMX_BUFFERFLAG_EOS, 0,
                            ILCLIENT_BUFFER_FLAG_EOS, 10000);


This will wait until the buffer is clear and there's no other way to cancel the media while it's waiting here. I replaced it with this:

Code: Select all
while (ilclient_remove_event(video_render, OMX_EventBufferFlag, 90, 0, OMX_BUFFERFLAG_EOS, 0) <0 & !exitFlag){
       }


which accomplishes the same thing, but can be exited by setting exitFlag.
Posts: 16
Joined: Sat Jul 07, 2012 12:51 am
Location: Los Angeles, California
by cocollective » Fri Jul 26, 2013 9:58 pm
Hi! I am trying to accomplish the same thing with different videos playing depending but with input from the GPIO without any delay of buffering. I looked at your code but I am uncertain on have to implement it in the hello_video example. Do you have an example of where to put in the different code statements?

Many thanks in advance!
Posts: 4
Joined: Fri Jul 26, 2013 9:44 pm
Location: Stockholm
by onehorsetown » Wed Nov 13, 2013 6:49 am
Any chance you could share the code you used to get this working? I am trying to switch video streams like you mentioned, but by video is hanging after the switch.

Thanks.
Posts: 1
Joined: Wed Nov 13, 2013 6:45 am