MediaCodec解碼FFmpeg AvPacket
private MediaFormat mediaFormat;
private MediaCodec mediaCodec;
private MediaCodec.BufferInfo info;
private Surface surface;//這個是OpenGL渲染的Surface
/**
* 初始化MediaCodec
*
* @param codecName
* @param width
* @param height
* @param csd_0
* @param csd_1
*/
public void initMediaCodec(String codecName, int width, int height, byte[] csd_0, byte[] csd_1) {
try {
if (surface != null) {
String mime = VideoSupportUtil.findVideoCodecName(codecName);
mediaFormat = MediaFormat.createVideoFormat(mime, width, height);
mediaFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, width * height);
mediaFormat.setByteBuffer("csd-0", ByteBuffer.wrap(csd_0));
mediaFormat.setByteBuffer("csd-1", ByteBuffer.wrap(csd_1));
MyLog.d(mediaFormat.toString());
mediaCodec = MediaCodec.createDecoderByType(mime);
info = new MediaCodec.BufferInfo();
if(mediaCodec == null) {
MyLog.d("craete mediaCodec wrong");
return;
}
mediaCodec.configure(mediaFormat, surface, null, 0);
mediaCodec.start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
VideoSupportUtil.java
import android.media.MediaCodecList;
import java.util.HashMap;
import java.util.Map;
public class VideoSupportUtil {
private static Map<String, String> codecMap = new HashMap<>();
static {
codecMap.put("h264", "video/avc");
}
public static String findVideoCodecName(String ffcodename){
if(codecMap.containsKey(ffcodename))
{
return codecMap.get(ffcodename);
}
return "";
}
public static boolean isSupportCodec(String ffcodecname){
boolean supportvideo = false;
int count = MediaCodecList.getCodecCount();
for(int i = 0; i < count; i++){
String[] tyeps = MediaCodecList.getCodecInfoAt(i).getSupportedTypes();
for(int j = 0; j < tyeps.length; j++){
if(tyeps[j].equals(findVideoCodecName(ffcodecname))){
supportvideo = true;
break;
}
}
if(supportvideo){
break;
}
}
return supportvideo;
}
}
c++層:
const char* codecName = ((const AVCodec*)avCodecContext->codec)->name;
onCallInitMediacodec(
codecName,
avCodecContext->width,
avCodecContext->height,
avCodecContext->extradata_size,
avCodecContext->extradata_size,
avCodecContext->extradata,
avCodecContext->extradata
);
//獲取jmid_initmediacodec
jclass jlz = jniEnv->GetObjectClass(jobj);
jmethodID jmid_initmediacodec = env->GetMethodID(jlz, "initMediaCodec", "(Ljava/lang/String;II[B[B)V");
//在子執行緒
void onCallInitMediacodec(const char* mime, int width, int height, int csd0_size, int csd1_size, uint8_t *csd_0, uint8_t *csd_1) {
JNIEnv *jniEnv;
if(javaVM->AttachCurrentThread(&jniEnv, 0) != JNI_OK)
{
if(LOG_DEBUG)
{
LOGE("call onCallComplete worng");
}
}
jstring type = jniEnv->NewStringUTF(mime);
jbyteArray csd0 = jniEnv->NewByteArray(csd0_size);
jniEnv->SetByteArrayRegion(csd0, 0, csd0_size, reinterpret_cast<const jbyte *>(csd_0));
jbyteArray csd1 = jniEnv->NewByteArray(csd1_size);
jniEnv->SetByteArrayRegion(csd1, 0, csd1_size, reinterpret_cast<const jbyte *>(csd_1));
jniEnv->CallVoidMethod(jobj, jmid_initmediacodec, type, width, height, csd0, csd1);
jniEnv->DeleteLocalRef(csd0);
jniEnv->DeleteLocalRef(csd1);
jniEnv->DeleteLocalRef(type);
javaVM->DetachCurrentThread();
}
解碼AvPacket
資料
public void decodeAVPacket(int datasize, byte[] data) {
if (surface != null && datasize > 0 && data != null) {
int intputBufferIndex = mediaCodec.dequeueInputBuffer(10);
if (intputBufferIndex >= 0) {
ByteBuffer byteBuffer = mediaCodec.getOutputBuffers()[intputBufferIndex];
byteBuffer.clear();
byteBuffer.put(data);
mediaCodec.queueInputBuffer(intputBufferIndex, 0, datasize, 0, 0);
}
//這裡拿到outputBufferIndex然後就可以獲取到資料,這裡會通過surface達到渲染
int outputBufferIndex = mediaCodec.dequeueOutputBuffer(info, 10);
while (outputBufferIndex >= 0) {
mediaCodec.releaseOutputBuffer(outputBufferIndex, true);
outputBufferIndex = mediaCodec.dequeueOutputBuffer(info, 10);
}
}
}
c++層回撥decodeAVPacket
datasize = avPacket->size;
data = avPacket->data;//jni這裡需要把uint8_t轉為jbyteArray,類似初始化那
相關文章
- FFmpeg音訊解碼音訊
- ffmpeg解碼基本流程
- MediaCodeC解碼視訊指定幀,迅捷、精確
- FFmpeg開發筆記(五):ffmpeg解碼的基本流程詳解(ffmpeg3新解碼api)筆記API
- ffmpeg解碼音訊流音訊
- Android音視訊(四)MediaCodec編解碼AACAndroid
- 使用 MediaCodec 在 Android 上進行硬解碼Android
- AVPacket(avcodec.h)
- Android 音視訊 - MediaCodec 編解碼音視訊Android
- ffmpeg軟解碼遇到的坑
- 關於FFMPEG的解碼模型模型
- android使用MediaCodec實現非同步視訊編解碼Android非同步
- NDK開發——FFmpeg視訊解碼
- FFmpeg和avconv編解碼工具
- MediaCodec 高效解碼得到標準 YUV420P 格式幀
- MediaCodec硬編碼pcm2aac
- FFmpeg開發筆記(九):ffmpeg解碼rtsp流並使用SDL同步播放筆記
- FFMPEG視音訊編解碼學習(1)音訊
- FFmpeg開發筆記(八):ffmpeg解碼音訊並使用SDL同步音訊播放筆記音訊
- 使用MediaCodec硬解碼h.265視訊及音訊進行播放音訊
- FFmpeg命令影片音訊轉碼引數詳解音訊
- FFmpeg學習之一(FFmpeg原始碼編譯)原始碼編譯
- 使用MediaCodeC將圖片集編碼為視訊
- JavaCV FFmpeg AAC編碼Java
- FFMpeg對MPEG2 TS流解碼的流程分析
- FFmpeg開發筆記(十九)FFmpeg開啟兩個執行緒分別解碼音影片筆記執行緒
- FFmpeg開發筆記(二十)Linux環境給FFmpeg整合AVS3解碼器筆記LinuxS3
- Android:MediaCodeC硬編碼解碼視訊,並將視訊幀儲存為圖片檔案Android
- Android MediaCodec小結Android
- Android MediaCodec硬解碼AAC音訊檔案(實時AAC音訊幀)並播放Android音訊
- FFmpeg開發筆記(二十一)Windows環境給FFmpeg整合AVS3解碼器筆記WindowsS3
- FFMpeg對MPEG2 TS流解碼的流程分析[2]
- hadoop + ffmpeg 雲轉碼Hadoop
- ffmpeg入門到實戰-ffmpeg是怎麼轉碼的?
- FFmpeg開發筆記(二十四)Linux環境給FFmpeg整合AV1的編解碼器筆記Linux
- php中使用 ffmpeg(部分程式碼)PHP
- FFmpeg開發筆記(六)如何訪問Github下載FFmpeg原始碼筆記Github原始碼
- ffmpeg音訊編碼之pcm轉碼aac音訊