美文网首页
Android万能视频播放器09-MediaCodec解码AVP

Android万能视频播放器09-MediaCodec解码AVP

作者: 张俊峰0613 | 来源:发表于2019-01-14 19:04 被阅读0次

1、步骤

1.1、初始化MediaCodec

解码器类型(mime),视频宽度(width),视频高度(height),最大数据输入大小(max_input_size),csd-0,csd-1。

mediaFormat = MediaFormat.createVideoFormat(mime, width, height);
mediaFormat.setInteger(MediaFormat.KEY_WIDTH, width);
mediaFormat.setInteger(MediaFormat.KEY_HEIGHT, height);
mediaFormat.setLong(MediaFormat.KEY_MAX_INPUT_SIZE, width * height);
mediaFormat.setByteBuffer(“csd-0”, ByteBuffer.wrap(csd0)); //avCodecContext->extradata
mediaFormat.setByteBuffer("csd-1", ByteBuffer.wrap(csd1)); //avCodecContext->extradata

对于H.264来说,"csd-0"和"csd-1"分别对应sps和pps;对于AAC来说,"csd-0"对应ADTS。

1.2、MediaCodec开始解码

int inputBufferIndex = mediaCodec.dequeueInputBuffer(10);
if(inputBufferIndex >= 0)
 {
    ByteBuffer byteBuffer = mediaCodec.getInputBuffers()[inputBufferIndex];
    byteBuffer.clear();
    byteBuffer.put(bytes);
    mediaCodec.queueInputBuffer(inputBufferIndex, 0, size, pts, 0);
}
    int index = mediaCodec.dequeueOutputBuffer(info, 10);
    while (index >= 0) {
    mediaCodec.releaseOutputBuffer(index, true);
    index = mediaCodec.dequeueOutputBuffer(info, 10);
}
size:avPacket->size, bytes :avPacket->data

2、实现

2.1、初始化MediaCodec

Java层:

/**
 * 初始化MediaCodec
 * @param codecName 解码器名称:h264、h265...
 * @param width
 * @param height
 * @param csd_0
 * @param csd_1
 */
public void onCallInitMediaCodec(String codecName,int width,int height,byte[] csd_0,byte[] csd_1){
    try {
        String mime = JfVideoSupUtil.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));
        JfLog.d("mediaFormat.toString() === " + mediaFormat.toString());

        mediaCodec = MediaCodec.createDecoderByType(mime);
        //mediaCodec.configure(mediaFormat,null,null,0);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

C++层调用:

end:
if (supMediaCodec){
    video->codectype = CODEC_MEDIACODEC;
    video->callJava->onCallInitMediaCodec(
            codecName,
            video->pVCodecCtx->width,
            video->pVCodecCtx->height,
            video->pVCodecCtx->extradata_size,
            video->pVCodecCtx->extradata_size,
            video->pVCodecCtx->extradata,
            video->pVCodecCtx->extradata
            );
}

2.2、MediaCodec开始解码

Java层:

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public void onCallDecodeAVPacket(int datasize, byte[] data){
    if (surface != null && datasize > 0 && data != null) {
        int inputBufferIndex = mediaCodec.dequeueInputBuffer(10);
        if (inputBufferIndex >= 0) {//进队
            //可能有好几个队列,按照索引,把队列中的bytebuffer拿出来
            ByteBuffer byteBuffer = mediaCodec.getOutputBuffer(inputBufferIndex);
            byteBuffer.clear();
            byteBuffer.put(data);
            mediaCodec.queueInputBuffer(inputBufferIndex,0,datasize,0,0);
        }

        int outputBufferIndex = mediaCodec.dequeueOutputBuffer(info,10);
        while (outputBufferIndex >= 0) {
            mediaCodec.releaseOutputBuffer(outputBufferIndex,true);
            outputBufferIndex = mediaCodec.dequeueOutputBuffer(info,10);
        }
    }
}

C++层调用:

if (video->codectype == CODEC_MEDIACODEC){
    LOGD("硬解码视频");
    //送入AVPacket过滤
    if (av_bsf_send_packet(video->abs_ctx,avPacket) != 0) {
        av_packet_free(&avPacket);//AVPacket中的第一个参数,就是引用,减到0才真正释放
        av_free(avPacket);
        avPacket = NULL;
        continue;
    }
    //接收过滤后的AVPacket
    while (av_bsf_receive_packet(video->abs_ctx,avPacket) == 0){
        LOGD("开始解码");

        double diff = video->getFrameDiffTime(NULL,avPacket);
        LOGD("DIFF IS %f",diff);
        av_usleep(video->getDelayTime(diff) * 1000000);

        video->callJava->onCallDecodeAVPacket(avPacket->size,avPacket->data);

        av_packet_free(&avPacket);//AVPacket中的第一个参数,就是引用,减到0才真正释放
        av_free(avPacket);
        continue;
    }
    avPacket = NULL;
}

相关文章

网友评论

      本文标题:Android万能视频播放器09-MediaCodec解码AVP

      本文链接:https://www.haomeiwen.com/subject/apfjdqtx.html