Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Java Development

Reply
Contributor
papdoligosa
Posts: 27
Registered: ‎02-12-2010
My Device: Torch 9800
My Carrier: Globe/Unlocked AT&T
Accepted Solution

How To Implement and Use SourceStream.seek(long) Properly?

[ Edited ]

I'm creating a custom DataSource and SourceStream for streaming local video files (files are stored in media card). I opted to use DataSource instead of simply creating a Player given the file path because I have additional processes to do between reading the bytes from the video files and the Player getting the data, and I need to implement seek/rewind/forward functionalities aside from play/pause/resume/stop.

 

So to add these functionalities, I implemented the SourceStream.seek(long) method using SharedInputStream's method setCurrentPosition(int).

 

	public long seek(long where) throws IOException {
		if (where < 0) {
			where = 0;
		}
		
		synchronized (readLock) {
			synchronized (connectionLock) {
				sharedInputStream.setCurrentPosition((int) where);
		        	currentPosition = sharedInputStream.getCurrentPosition();
		        
		        	return currentPosition;
			}
		}
	}

 

The problem is, when I explicitly call the seek(long) method to move to a particular time/frame, the video gets stuck in a buffering state. Also, I'm concerned on the method SharedInputStream.setCurrentPosition(int) having an int parameter. I'm afraid it would cause some exception since I will be playing large video files.

 

 

I also tried using the InputStream methods reset() and skip(long)but when the video is played, an exception is thrown: 

 

	public long seek(long where) throws IOException {
		if (where < 0) {
			where = 0;
		}
		
		synchronized (readLock) {
			long now = 0;
			try{
				sharedInputStream.reset();
				now = sharedInputStream.skip(where);
			} catch (Throwable t){
				e.printStackTrace();
			}
			return now;
		}
	}

 

My questions are:

 

1. How should the seek(long) method be implemented using the SharedInputStream.setCurrentPosition(int)?

2. Similarly, how can you seek videos using InputStream.reset() and .skip(long) methods?

3. What is the proper way of calling the seek(long) method if you want to go to a particular time/frame?

 

Thanks!

Please use plain text.
Administrator
saziz
Posts: 76
Registered: ‎07-11-2008
My Device: Z10
My Carrier: SingTel

Re: How To Implement and Use SourceStream.seek(long) Properly?

Take a look at the following KB which has a very good sample attached and explains the issues you've raised: http://supportforums.blackberry.com/t5/Java-Development/Streaming-media-Start-to-finish/ta-p/488255

 

It uses a CircularStreamingBuffer, and the seek implementation can handle both seeks within the buffer, or outside in which case an additional http request is made.

 

For any user-initiated seeks, you should just use player.setMediaTime() as shown in the sample, and this should call your seek implementation at the lower level.

Sarim
BlackBerry Development Advisor
www.BlackBerryDeveloper.com
Please use plain text.
Contributor
papdoligosa
Posts: 27
Registered: ‎02-12-2010
My Device: Torch 9800
My Carrier: Globe/Unlocked AT&T

Re: How To Implement and Use SourceStream.seek(long) Properly?

[ Edited ]

Thanks Sarim!

 

I was actually using that sample as a reference.

 

It's working now. I just realized I was using milliseconds instead of microseconds for the parameter value (i.e. instead of 12000000L for 12 seconds, I was using 12000L - that's why it seems it plays from the beginning). I then thought the method Player.setMediaTime(long) isn't working so I moved to trying out other ways including explicitly calling SourceStream.seek(long).

Please use plain text.
Contributor
papdoligosa
Posts: 27
Registered: ‎02-12-2010
My Device: Torch 9800
My Carrier: Globe/Unlocked AT&T

Re: How To Implement and Use SourceStream.seek(long) Properly?

[ Edited ]

I have a follow-up question:

 

Is it possible to use a simple InputStream, instead of SharedInputStream, for the SourceStream particularly in the seek() method? It seems like I can't use InputStream.skip() (and reset() if necessary) while the player is not started yet (i.e. in prefetch state). That's why I came up with this code for:

 

public long seek(long where) throws IOException {
	synchronized (readLock) {
		synchronized (connectionLock) {
			if (started) {
				try{
					if (where < currentPosition) {
						sharedInputStream.reset();
					}
					currentPosition = sharedInputStream.skip(where);
				} catch (Throwable t){
					t.printStackTrace();
				}
				return currentPosition;
			} else {
				sharedInputStream.setCurrentPosition((int) where);
		        	currentPosition = sharedInputStream.getCurrentPosition();
			        return currentPosition;
			}
		}
	}
}

 

 I want to use only the InputStream methods, reset() and skip() for my implementation of SourceStream.seek()

 

Thanks!!!!

Please use plain text.