查看完整版本 : Android MediaCodec class 用法

linuxfedora 2018-1-18 06:54 PM

Android MediaCodec class 用法

My android application will receive the h.264 bit stream and display the video using Opengl.
Currently i use ffmpeg to decode the 264 bit stream, now i want to change to use MediaCodec for hardware decoding.

I have some question about the MediaCodec.

1. I have tried to put the video data to mediacodec and the output buffer seems decoded the video data into YUV420 format, then how can i use the video data for the texture on the opengl (i used before), as it seems the texture on opengl use rgb format. (The current code use ffmpeg to decode the video and convert it to rgb and put the decoded data to a texture).

2. Can i control the output format on the mediacodec to output rgb directly?

3. What is the correct way to use the mediacodec?
I created a buffer to store the video data from the network and then use asychronize processing and when mediacodec call back onInputBufferAvailable, i put the data from my buffer to it.
If the onOutputBufferAvailable is called, i get the buffer from it and it is the decoded video data on yuv420[code]mCodec.setCallback(new MediaCodec.Callback() {
@Override
public void onInputBufferAvailable(@NonNull MediaCodec codec, int index) {

if (index >= 0) {

VideoData videoData = null;
if(!mVideoDataQueue.isEmpty())
{
videoData = mVideoDataQueue.peek();
}

ByteBuffer inputBuffer = mCodec.getInputBuffer(index);
inputBuffer.clear();
inputBuffer.put(videoData.frameBuffer, 0, videoData.frameBufferLen);

mCodec.queueInputBuffer(index, 0, videoData.frameBufferLen, videoData.frameHeader.mDateTime.getSecSince1970() * 1000, 0);
}
}

@Override
public void onOutputBufferAvailable(@NonNull MediaCodec codec, int index, @NonNull MediaCodec.BufferInfo info) {

switch(index) {
case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
mOutputFormat = mCodec.getOutputFormat();

//int sample_rate = outputFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE);
//android.util.Log.d(TAG, "sample_rate=" + sample_rate);
break;

case MediaCodec.INFO_TRY_AGAIN_LATER:
//time out.
break;

default:

if(index >= 0) {

m_bufferInfo = info;

ByteBuffer outputBuffer = mCodec.getOutputBuffer(index);
MediaFormat bufferFormat = mCodec.getOutputFormat(index); // option A
final byte[] chunk = new byte[info.size];
outputBuffer.get(chunk); // Read the buffer all at once
outputBuffer.clear();

mCodec.releaseOutputBuffer(index, true);
}
break;
}

// All decoded frames have been rendered, we can stop playing now
if ((m_bufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
android.util.Log.d(TAG, "OutputBuffer BUFFER_FLAG_END_OF_STREAM");
}
}

@Override
public void onError(@NonNull MediaCodec codec, @NonNull MediaCodec.CodecException e) {

}

@Override
public void onOutputFormatChanged(@NonNull MediaCodec codec, @NonNull MediaFormat format) {
mOutputFormat = format;
}
});[/code]

jasonchan35 2018-1-19 04:24 AM

you can decode the YUV420 to RGB in OpenGL shader

but you may have to separate the input Y,U,V in 3 input textures
since the resolution of U,V only half size of Y

and convert convert YUV color space to RGB is simple, just use the matrix below
[img]https://wikimedia.org/api/rest_v1/media/math/render/svg/9d783bf1ed1edbda3e8e87d3d9067bd156a5e75b[/img]

[url=https://en.wikipedia.org/wiki/YUV]https://en.wikipedia.org/wiki/YUV[/url]

and the other way is convert on CPU using the same matrix

[[i] 本帖最後由 jasonchan35 於 2018-1-19 04:26 AM 編輯 [/i]]

煙民母親生賤種 2018-1-19 05:59 AM

[quote]原帖由 [i]linuxfedora[/i] 於 2018-1-18 06:54 PM 發表 [url=http://computer.discuss.com.hk/redirect.php?goto=findpost&pid=473992065&ptid=27191038][img]http://computer.discuss.com.hk/images/common/back.gif[/img][/url]
My android application will receive the h.264 bit stream and display the video using Opengl.
Currently i use ffmpeg to decode the 264 bit stream, now i want to change to use MediaCodec for hardware d ... [/quote]照計 mdeiacodec 呢D常用野, 網上有好多。無嗎? :fst_007:

jasonchan35 2018-1-19 09:51 AM

[quote]原帖由 [i]煙民母親生賤種[/i] 於 2018-1-19 05:59 AM 發表 [url=http://computer.discuss.com.hk/redirect.php?goto=findpost&pid=474010449&ptid=27191038][img]http://computer.discuss.com.hk/images/common/back.gif[/img][/url]
照計 mdeiacodec 呢D常用野, 網上有好多。無嗎? :fst_007: [/quote]

通常 codec 都係出 YUV 多, 不過自己轉下都唔係太難

linuxfedora 2018-1-19 12:20 PM

[quote]原帖由 [i]jasonchan35[/i] 於 2018-1-19 09:51 AM 發表 [url=http://www.discuss.com.hk/redirect.php?goto=findpost&pid=474016085&ptid=27191038][img]http://www.discuss.com.hk/images/common/back.gif[/img][/url]


通常 codec 都係出 YUV 多, 不過自己轉下都唔係太難 [/quote]
轉要用cpu做 不想浪費cpu 用gpu opengl es 1.1 又好似唔得

[[i] 本帖最後由 linuxfedora 於 2018-1-19 12:29 PM 編輯 [/i]]

jasonchan35 2018-1-20 01:07 AM

[quote]原帖由 [i]linuxfedora[/i] 於 2018-1-19 12:20 PM 發表 [url=http://computer.discuss.com.hk/redirect.php?goto=findpost&pid=474023096&ptid=27191038][img]http://computer.discuss.com.hk/images/common/back.gif[/img][/url]

轉要用cpu做 不想浪費cpu 用gpu opengl es 1.1 又好似唔得 [/quote]

OpenGL ES 1.1 無 Shader
但 OpenGL 2.0 已經有, 基本上無咩 Android 機唔 support 2.0
3.0 都差唔多近幾年既機都行到

煙民母親生賤種 2018-1-20 02:47 AM

[quote]原帖由 [i]linuxfedora[/i] 於 2018-1-19 12:20 PM 發表 [url=http://computer.discuss.com.hk/redirect.php?goto=findpost&pid=474023096&ptid=27191038][img]http://computer.discuss.com.hk/images/common/back.gif[/img][/url]

轉要用cpu做 不想浪費cpu 用gpu opengl es 1.1 又好似唔得 [/quote]看看這個幫唔幫到你... :fst_008:

[url=https://www.polarxiong.com/archives/Android-MediaCodec%E8%A7%86%E9%A2%91%E6%96%87%E4%BB%B6%E7%A1%AC%E4%BB%B6%E8%A7%A3%E7%A0%81-%E9%AB%98%E6%95%88%E7%8E%87%E5%BE%97%E5%88%B0YUV%E6%A0%BC%E5%BC%8F%E5%B8%A7-%E5%BF%AB%E9%80%9F%E4%BF%9D%E5%AD%98JPEG%E5%9B%BE%E7%89%87-%E4%B8%8D%E4%BD%BF%E7%94%A8OpenGL.html]https://www.polarxiong.com/archives/Android-MediaCodec%E8%A7%86%E9%A2%91%E6%96%87%E4%BB%B6%E7%A1%AC%E4%BB%B6%E8%A7%A3%E7%A0%81-%E9%AB%98%E6%95%88%E7%8E%87%E5%BE%97%E5%88%B0YUV%E6%A0%BC%E5%BC%8F%E5%B8%A7-%E5%BF%AB%E9%80%9F%E4%BF%9D%E5%AD%98JPEG%E5%9B%BE%E7%89%87-%E4%B8%8D%E4%BD%BF%E7%94%A8OpenGL.html[/url]

linuxfedora 2018-1-20 09:07 AM

[quote]原帖由 [i]jasonchan35[/i] 於 2018-1-20 01:07 AM 發表 [url=http://www.discuss.com.hk/redirect.php?goto=findpost&pid=474059353&ptid=27191038][img]http://www.discuss.com.hk/images/common/back.gif[/img][/url]


OpenGL ES 1.1 無 Shader
但 OpenGL 2.0 已經有, 基本上無咩 Android 機唔 support 2.0
3.0 都差唔多近幾年既機都行到 [/quote]
D opengl 1.1 code 係前人寫的 我現在要跟 基本上唔想大改做2.0⋯⋯1.1我都係自學了2個星期倒  轉2.0好似要學過又大改

[[i] 本帖最後由 linuxfedora 於 2018-1-20 09:11 AM 編輯 [/i]]

linuxfedora 2018-1-20 09:08 AM

[quote]原帖由 [i]煙民母親生賤種[/i] 於 2018-1-20 02:47 AM 發表 [url=http://www.discuss.com.hk/redirect.php?goto=findpost&pid=474061013&ptid=27191038][img]http://www.discuss.com.hk/images/common/back.gif[/img][/url]
看看這個幫唔幫到你... :fst_008:

https://www.polarxiong.com/archives/Android-MediaCodec%E8%A7%86%E9%A2%91%E6%96%87%E4%BB%B6%E7%A1%AC%E4%BB%B6%E8%A7%A3%E7%A0%81-%E9%AB%98%E6%95%88%E7%8E%87%E5%BE%97%E ... [/quote]
星期一 我再反公司睇睇 thx

jasonchan35 2018-1-20 10:21 AM

[quote]原帖由 [i]linuxfedora[/i] 於 2018-1-20 09:07 AM 發表 [url=http://computer.discuss.com.hk/redirect.php?goto=findpost&pid=474065509&ptid=27191038][img]http://computer.discuss.com.hk/images/common/back.gif[/img][/url]

D opengl 1.1 code 係前人寫的 我現在要跟 基本上唔想大改做2.0⋯⋯1.1我都係自學了2個星期倒  轉2.0好似要學過又大改 [/quote]

改 OpenGL ES 2.0 都唔係真係咁難 (比起 Desktop OpenGL 1.5 -> 2.0)
長遠黎講轉左都係好事, OpenGL ES 1.1 真係太舊,
而且 video 既 resolution 一般唔細, 用 CPU 做真係會慢, 1920 x 1080 都已經 200 萬個 pixels, 而且 4k 都開始普及啦

[url=https://developer.android.com/training/graphics/opengl/environment.html]https://developer.android.com/training/graphics/opengl/environment.html[/url]
[url=http://www.learnopengles.com/android-lesson-one-getting-started/]http://www.learnopengles.com/android-lesson-one-getting-started/[/url]

[簡單黎講 C++] Advance OpenGL
[url=https://www.youtube.com/playlist?list=PLeGk08zVu454q9gERPdZICbkzyHRufZtf]https://www.youtube.com/playlist?list=PLeGk08zVu454q9gERPdZICbkzyHRufZtf[/url]
[簡單黎講 C++] OpenGL
[url=https://www.youtube.com/playlist?list=PLeGk08zVu454RoaIrgw8VDAgrtUwHf4I_]https://www.youtube.com/playlist?list=PLeGk08zVu454RoaIrgw8VDAgrtUwHf4I_[/url]

jasonchan35 2018-1-20 10:23 AM

[quote]原帖由 [i]煙民母親生賤種[/i] 於 2018-1-20 02:47 AM 發表 [url=http://computer.discuss.com.hk/redirect.php?goto=findpost&pid=474061013&ptid=27191038][img]http://computer.discuss.com.hk/images/common/back.gif[/img][/url]
看看這個幫唔幫到你... :fst_008:

[url=https://www.polarxiong.com/archives/Android-MediaCodec%E8%A7%86%E9%A2%91%E6%96%87%E4%BB%B6%E7%A1%AC%E4%BB%B6%E8%A7%A3%E7%A0%81-%E9%AB%98%E6%95%88%E7%8E%87%E5%BE%97%E]https://www.polarxiong.com/archives/Android-MediaCodec%E8%A7%86%E9%A2%91%E6%96%87%E4%BB%B6%E7%A1%AC%E4%BB%B6%E8%A7%A3%E7%A0%81-%E9%AB%98%E6%95%88%E7%8E%87%E5%BE%97%E[/url] ... [/quote]

依個應該係因為 Jpeg 都係用 YUV 所以可以 bypass YUV->RGB (我無睇得好真篇野)
如果要出 OpenGL 做 display 應該都係要做轉換

煙民母親生賤種 2018-1-21 02:42 AM

[quote]原帖由 [i]jasonchan35[/i] 於 2018-1-20 10:23 AM 發表 [url=http://computer.discuss.com.hk/redirect.php?goto=findpost&pid=474067851&ptid=27191038][img]http://computer.discuss.com.hk/images/common/back.gif[/img][/url]


依個應該係因為 Jpeg 都係用 YUV 所以可以 bypass YUV->RGB (我無睇得好真篇野)
如果要出 OpenGL 做 display 應該都係要做轉換 [/quote]問題係如果樓主用得別人的 class, 即係唔想自己寫咁多野 ... :fst_016:

jasonchan35 2018-1-21 03:49 AM

[quote]原帖由 [i]煙民母親生賤種[/i] 於 2018-1-21 02:42 AM 發表 [url=http://computer.discuss.com.hk/redirect.php?goto=findpost&pid=474109384&ptid=27191038][img]http://computer.discuss.com.hk/images/common/back.gif[/img][/url]
問題係如果樓主用得別人的 class, 即係唔想自己寫咁多野 ... :fst_016: [/quote]

我明白, 不過搵唔到無現成既都無辦法

linuxfedora 2018-1-22 09:47 AM

[quote]原帖由 [i]煙民母親生賤種[/i] 於 2018-1-19 05:59 AM 發表 [url=http://computer.discuss.com.hk/redirect.php?goto=findpost&pid=474010449&ptid=27191038][img]http://computer.discuss.com.hk/images/common/back.gif[/img][/url]
照計 mdeiacodec 呢D常用野, 網上有好多。無嗎? :fst_007: [/quote]

直接開mp4 file 的example 有, 但係network bit stream 來decode...只有一D...唔完整的code....所以唔知方向是否正確.

Network data->Store on my own buffer queue, when the MediaCodec call the onInputBufferAvailable, i give one of the buffered data to it from the queue, and then MediaCodec will call the onOutputBufferAvailable with a index larger than or equal to 0, then i can get the decoded data from the output buffer of the corresponding index, is that right? Is it what people normal do?? As it seems waiting memory for my own buffer queue...and need code to control the network data speed if decode is slow. Thanks

I have some question.

1. If the newtork data is slow, then if the onInputBufferAvailable is called, but i have no data, then what should i do on the call??
onInputBufferAvailable
added in [url=https://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels]API level 21[/url]void onInputBufferAvailable ([url=https://developer.android.com/reference/android/media/MediaCodec.html]MediaCodec[/url] codec,                 int index)Called when an input buffer becomes available.

[table][tr][td=2,1]Parameters[/td][/tr][tr][td]codec[/td][td]MediaCodec: The MediaCodec object.This value must never be null.
[/td][/tr][tr][td]index[/td][td]int: The index of the available input buffer.[/td][/tr][/table]
The document does not mention what should i do if i have no data for the input buffer..

2. If the newtork data is faster than the decode speed, then how should i control the network data, i should block the network from receive data?

Thanks

[[i] 本帖最後由 linuxfedora 於 2018-1-22 10:08 AM 編輯 [/i]]

jasonchan35 2018-1-22 11:03 AM

1) onInputBufferAvailable 係要求你 call codec.queueInputBuffer(), 咁如果 network 無野黎, 應該唔 call 就得, 等下次再俾
2) 如果 network data 黎得快既, 咁應該要做 buffering, 如果個 buffer 已經滿左既, 只要你唔再係 socket 收 data, 咁 TCP 應該會 block 著對面等到 socket recv buffer 有空位先再 send, 但如果係 UDP streaming 咁你要預左 drop packet, 而 H.264 既設計係可以 support 到中間有 packet drop 左
[url=https://github.com/mstorsjo/android-decodeencodetest/blob/master/src/com/example/decodeencodetest/ExtractDecodeEditEncodeMuxTest.java]https://github.com/mstorsjo/android-decodeencodetest/blob/master/src/com/example/decodeencodetest/ExtractDecodeEditEncodeMuxTest.java[/url]

linuxfedora 2018-1-22 11:22 AM

[quote]原帖由 [i]jasonchan35[/i] 於 2018-1-22 11:03 AM 發表 [url=http://computer.discuss.com.hk/redirect.php?goto=findpost&pid=474174257&ptid=27191038][img]http://computer.discuss.com.hk/images/common/back.gif[/img][/url]
1) onInputBufferAvailable 係要求你 call codec.queueInputBuffer(), 咁如果 network 無野黎, 應該唔 call 就得, 等下次再俾
2) 如果 network data 黎得快既, 咁應該要做 buffering, 如果個 buffer 已經滿左既, 只 ... [/quote]

From my testing:
1)

enqueue count=1
onInputBufferAvailable,  index=2
dequeue count=0
onInputBufferAvailable,  index=3        //NO data on my queue, so i skipped not to call queueInputBuffer
onInputBufferAvailable,  index=4        //NO data on my queue, so i skipped not to call queueInputBuffer
onInputBufferAvailable,  index=0        //NO data on my queue, so i skipped not to call queueInputBuffer
onInputBufferAvailable,  index=1        //NO data on my queue, so i skipped not to call queueInputBuffer
onInputBufferAvailable,  index=2        //NO data on my queue, so i skipped not to call queueInputBuffer
onOutputBufferAvailable,  index=0
enqueue count=1
enqueue count=2
enqueue count=3
enqueue count=4
enqueue count=5
enqueue count=6
enqueue count=7

and then the onInputBufferAvailable is never call?

jasonchan35 2018-1-22 12:08 PM

how about call codec.queuInputBuffer() with empty data (size = 0)

[url]https://stackoverflow.com/questions/35884600/android-mediacodec-encode-and-decode-in-asynchronous-mode/35885471[/url]

linuxfedora 2018-1-23 11:36 AM

[quote]原帖由 [i]jasonchan35[/i] 於 2018-1-22 12:08 PM 發表 [url=http://computer.discuss.com.hk/redirect.php?goto=findpost&pid=474177442&ptid=27191038][img]http://computer.discuss.com.hk/images/common/back.gif[/img][/url]
how about call codec.queuInputBuffer() with empty data (size = 0)

[url=https://stackoverflow.com/questions/35884600/android-mediacodec-encode-and-decode-in-asynchronous-mode/35885471]https://stackoverflow.com/questions/35884600/android-mediacodec-encode-and-decode-in-asynchronous-mode/35885471[/url] [/quote]

If i have no data, then call
mCodec.queueInputBuffer(index, 0, 0, 0, 0);
Some time, it will crash on this call

E/AndroidRuntime: FATAL EXCEPTION: main                                                                       Process: , PID:                                                                       java.lang.IllegalStateException                                                                           at android.media.MediaCodec.native_queueInputBuffer(Native Method)                                                                           at android.media.MediaCodec.queueInputBuffer(MediaCodec.java:831)                                                                           at VDecoder$1.onInputBufferAvailable(VideoDecoder.java:192)                                                                           at android.media.MediaCodec$EventHandler.handleCallback(MediaCodec.java:380)                                                                           at android.media.MediaCodec$EventHandler.handleMessage(MediaCodec.java:353)                                                                           at android.os.Handler.dispatchMessage(Handler.java:102)                                                                           at android.os.Looper.loop(Looper.java:135)                                                                           at android.app.ActivityThread.main(ActivityThread.java:5264)                                                                           at java.lang.reflect.Method.invoke(Native Method)                                                                           at java.lang.reflect.Method.invoke(Method.java:372)                                                                           at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:900)                                                                           at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:695)
頁: [1]
查看完整版本: Android MediaCodec class 用法