I have problem with end of stream signalled earlier than expected (way before file ends) by the advance()
method of MediaExtractor
class. According to Google reference the advance() method could work wrong when using a local file (and this is my case - filePath
ponits to a local file):
When extracting a local file, the behaviors of advance() and readSampleData(ByteBuffer, int) are undefined in presence of concurrent writes to the same local file:
Unfortunately there is no single word about using MediaExtractor
without advance()
method. How to move to the next sample? If there is no way to do it then I'd like to know how to feed inputBuffer
without using MediaExtractor
.
A fragment of my code below:
if(Build.VERSION.SDK_INT >= 21 ) {
try {
codec = MediaCodec.createByCodecName("OMX.google.mp3.decoder");
} catch (IOException e) {
e.printStackTrace();
}
final MediaExtractor extractor = new MediaExtractor();
try {
extractor.setDataSource(filePath); //local file
Log.i("filePath", String.valueOf(filePath));
extractor.selectTrack(0);
} catch (IOException e) {
e.printStackTrace();
}
codec.setCallback(new MediaCodec.Callback() {
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public void onInputBufferAvailable(MediaCodec mc, int inputBufferId) {
ByteBuffer inputBuffer = codec.getInputBuffer(inputBufferId);
// fill inputBuffer with valid data
int sampleSize = extractor.readSampleData(inputBuffer,0);
if(extractor.advance) {
codec.queueInputBuffer(inputBufferId, 0, sampleSize, 0, 0);
} else {
// EOS
codec.queueInputBuffer(inputBufferId, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
codec.stop();
codec.release();
}
}
// more callbacks
};
}
In my samples MediaExtractor worked correctly when I used another construction of statements. I did not check EOS with extractor.advance() like you. Try how other samples offer:
int chunkSize = extractor.readSampleData(inputBuffer, 0);
if (chunkSize < 0) {
// End of stream -- send empty frame with EOS flag set.
codec.queueInputBuffer(inputBufferId, 0, 0, 0L,
MediaCodec.BUFFER_FLAG_END_OF_STREAM);
} else {
// No EOS -- continue
long presentationTimeUs = extractor.getSampleTime();
codec.queueInputBuffer(inputBufferId, 0, chunkSize,
presentationTimeUs, 0 /*flags*/);
extractor.advance();
}
BTW, the guide of MediaExtractor tells about such usage. Fadden has MoviePlayer in Grafika with MediaExtractor. But it feeds decoder without MediaCodec.Callback.