I'm using MediaCodec to read a video file and store the frames on SD card. However it is storing a green rectangle instead of the actual frame. Here is the code:
int outIndex = decoder.dequeueOutputBuffer(info, 10000);
switch (outIndex) {
case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
Log.d("DecodeActivity", "INFO_OUTPUT_BUFFERS_CHANGED");
outputBuffers = decoder.getOutputBuffers();
break;
case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
Log.d("DecodeActivity", "New format " + decoder.getOutputFormat());
break;
case MediaCodec.INFO_TRY_AGAIN_LATER:
Log.d("DecodeActivity", "dequeueOutputBuffer timed out!");
break;
default:
ByteBuffer buffer = outputBuffers[outIndex]; //The bytebuffer i want to convert to bitmap
Log.v("DecodeActivity", "We can't use this buffer but render it due to the API limit, " + buffer);
buffer.position(info.offset);
buffer.limit(info.offset + info.size);
byte[] ba = new byte[buffer.remaining()]; //converting bytebuffer to byte array
buffer.get(ba);
Log.d("ba", ba.length + "");
// I have to convert the byte array to a bitmap. So I'm doing this :
YuvImage yuvimage = new YuvImage(ba, ImageFormat.NV21, 1280, 720, null);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
yuvimage.compressToJpeg(new Rect(0, 0, 1280, 720), 80, baos);
byte[] jdata = baos.toByteArray();
Bitmap bmp = BitmapFactory.decodeByteArray(jdata, 0, jdata.length);
if (bmp != null) {
//Store the bitmap as JPEG in SD card
Log.d("Barcode",barcodeNumber+"");
String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath();
File videoFile = new File(baseDir + "/MyPhotos2/image" + barcodeNumber + ".jpg");
barcodeNumber ++;
FileOutputStream out = null;
Log.d("success","yes");
try {
out = new FileOutputStream(videoFile);
bmp.compress(Bitmap.CompressFormat.JPEG, 100, out);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
else if(bmp==null)
{
Log.d("null","null");
}
// We use a very simple clock to keep the video FPS, or the video
// playback will be too fast
while (info.presentationTimeUs / 1000 > System.currentTimeMillis() - startMs) {
try {
sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
}
decoder.releaseOutputBuffer(outIndex, true);
break;
}
// All decoded frames have been rendered, we can stop playing now
if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
Log.d("DecodeActivity", "OutputBuffer BUFFER_FLAG_END_OF_STREAM");
break;
}
}
decoder.stop();
decoder.release();
extractor.release();
}
I think the problem is with the format of the bitmap. I'm not sure if what I'm doing is right here. Please correct any mistakes in this or suggest a way in which I can extract the bitmap from the ByteBuffer. I decided to use mediacodec because MediaMetadataRetriever is too slow.
My goal was to handle the ByteBuffer myself so that later I can save the image while displaying it in Surface. Here's how I did it. I also note that in MediaCodec I do not transfer Surface that I can could processed ByteBuffer . Maybe you will find something that will help you.
}