[Libav-user] Some questions about use mediacodec of ffmpeg in android

黄仁渭 huangrenwei2010 at 126.com
Thu Mar 29 07:27:18 EEST 2018


   Dear FFMEG:       
    I use ffmpeg in android JNI, I need use mediacodec to decode some H264 stream, first (the DecodeMp4TestV2 function)I do a test to decode some video files like mkv. It works fine and I decode it successfully.
 But  I need to decode some raw H264  stream rather then a video file or RTSP stream. It is a raw H264 stream with private header. So I can not use the avformat_open_input and  avformat_find_stream_info to get the AVCodecContext  parameters. So when I call avcodec_open2, I get error -1 . I know it is because I don't set the AVCodecContext  parameters. But on win32, when I use dxva2, I don't need to set the AVCodecContext  parameters, it just work fine.
But on android I need to set the AVCodecContext  parameters, So which AVCodecContext  parameters do I need to fill? It has so many parameters . So if you have an answer ,please let me know. Looking forward to your replies!


   
Successful Demo of decoding video files:                                                                                                                                                                                                                                                                                              Best wishes!
int DecodeMp4TestV2()
{
                 AVCodec *m_lpCodec  = NULL;
                AVCodecContext *m_lpCodecCtx = NULL;
                AVFrame *m_lpFrame = NULL;
                AVFrame *m_lpSwFrame = NULL;
                AVBufferRef *m_lpHWDeviceCtx = NULL;
                AVPixelFormat m_nPixFormat = AV_PIX_FMT_NONE;
                AVFormatContext * pFormatCtx = NULL ;
                int videoStream = -1;
                int audioStream = -1;
int nRet = 0 ;
int  i = 0;
int nType = eHWDeviceTypeMediaCodec;
int nStreamType = eStreamH264 ;
//char c_filename[256] = {0};
AVPacket struAvpkt;
//sprintf(c_filename, "%s", "/sdcard/1111.mp4");
const char *c_filename = "/sdcard/test1080.mkv" ;
av_register_all( ) ;
avcodec_register_all( ) ;
pFormatCtx = avformat_alloc_context();
if(pFormatCtx == NULL)
{
LOGI("avformat_alloc_context error");
return 1 ;
}
if((nRet = avformat_open_input(&pFormatCtx, c_filename, NULL, NULL)) < 0)
{
LOGI("Cannot open the file %s, err: %d",c_filename,  nRet);
return -1;
}
if((nRet = avformat_find_stream_info(pFormatCtx, NULL))<0)
{
    LOGI("Couldn't find stream information. err:%d", nRet);
    return -1;
}
av_dump_format(pFormatCtx, 0, c_filename, 0) ;
for (i = 0; i < pFormatCtx->nb_streams; i++) 
{
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO && videoStream < 0)
{
videoStream = i;
}
else if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
{
audioStream = i;
}
}
if(videoStream == -1)
{
LOGE("Didn't find a video stream.");
return -1; // Didn't find a video stream
}
// Get a pointer to the codec context for the video stream
      m_lpCodecCtx = pFormatCtx->streams[videoStream]->codec;
  
LOGI("avcodec_register_all succ");
if(nType == eHWDeviceTypeMediaCodec)
{
LOGI("avcodec_find_decoder_by_name start");
if (nStreamType == eStreamH264)
{
LOGI("avcodec_find_decoder_by_name h264_mediacodec");
m_lpCodec = avcodec_find_decoder_by_name("h264_mediacodec"); //android h264 hw decode
}
else if (nStreamType == eStreamHEVC)
{
LOGI("avcodec_find_decoder_by_name hevc_mediacodec");
m_lpCodec = avcodec_find_decoder_by_name("hevc_mediacodec"); //android h265 hw decode
}
else if (nStreamType == eStreamMP4)
{
LOGI("avcodec_find_decoder_by_name mpeg4_mediacodec");
m_lpCodec = avcodec_find_decoder_by_name("mpeg4_mediacodec"); //android mp4 hw decode
}
else
{
return 1 ;
}
LOGI("avcodec_find_decoder_by_name end");
}
if (m_lpCodec == NULL)
{
LOGI("avcodec_find_decoder_by_name error");
return 1;
}
nRet = avcodec_open2(m_lpCodecCtx, m_lpCodec, NULL) ;
if(nRet != 0)
{
LOGI("avcodec_open2 hw decoder error nRet[%d] height[%d] width[%d] fmt[%d]", nRet, m_lpCodecCtx->height, m_lpCodecCtx->width, m_lpCodecCtx->pix_fmt);
return 1 ;
}
LOGI("avcodec_open2 hw succ nRet[%d]", nRet);
m_lpFrame = av_frame_alloc( ) ;
if (m_lpFrame == NULL)
{
return 1;
}
LOGI("av_frame_alloc succ m_lpFrame[%x]", m_lpFrame);


while(av_read_frame(pFormatCtx, &struAvpkt)>=0)
{
if(struAvpkt.stream_index==videoStream)
{
nRet = avcodec_send_packet(m_lpCodecCtx, &struAvpkt) ;
if(nRet != 0)
{
LOGI("avcodec_send_packet error") ;
return 1 ;
}
nRet = avcodec_receive_frame(m_lpCodecCtx, m_lpFrame) ; //0: m_lpFrame is correct;  1: m_lpFrame is corrupted; 2:no frame could be decompressed;3:need more
LOGI("avcodec_receive_frame  nRet[%d] height[%d] width[%d] fmt[%d]",  nRet, m_lpFrame->height, m_lpFrame->width, m_lpFrame->format) ;
if (nRet == 0)
{
LOGI("avcodec_receive_frame succ") ;
}
else
{
LOGI("avcodec_receive_frame error") ;
}
}
Sleep(10) ;
}


return 0;   
}




failed demo of decoding raw H264 streams:
int InitDecode(eStreamType nStreamType, eHWDeviceType nType, MP4_CODEC_INIT_PARAM *lpInitParam)
{
int nRet = 0 ;
AVCodecID eCodeId = AV_CODEC_ID_NONE ;
enum AVHWDeviceType eHWType =AV_HWDEVICE_TYPE_NONE ;
         AVCodec *m_lpCodec  = NULL;
        AVCodecContext *m_lpCodecCtx = NULL;
        AVFrame *m_lpFrame = NULL;
         AVFrame *m_lpSwFrame = NULL;
         AVBufferRef *m_lpHWDeviceCtx = NULL;

         AVPixelFormat m_nPixFormat = AV_PIX_FMT_NONE;


av_register_all( ) ;
avcodec_register_all( ) ;
LOGI("avcodec_register_all succ");
if(nType == eHWDeviceTypeMediaCodec)
{
LOGI("avcodec_find_decoder_by_name start");
if (nStreamType == eStreamH264)
{
LOGI("avcodec_find_decoder_by_name h264_mediacodec");
m_lpCodec = avcodec_find_decoder_by_name("h264_mediacodec"); //android h264 hw decode
}
else if (nStreamType == eStreamHEVC)
{
LOGI("avcodec_find_decoder_by_name hevc_mediacodec");
m_lpCodec = avcodec_find_decoder_by_name("hevc_mediacodec"); //android h265 hw decode
}
else if (nStreamType == eStreamMP4)
{
LOGI("avcodec_find_decoder_by_name mpeg4_mediacodec");
m_lpCodec = avcodec_find_decoder_by_name("mpeg4_mediacodec"); //android mp4 hw decode
}
else
{
return 1 ;
}
LOGI("avcodec_find_decoder_by_name end");
}
else
{
return 1 ;
}


if (m_lpCodec == NULL)
{
LOGI("avcodec_find_decoder_by_name error");
return 1;
}


m_lpCodecCtx = avcodec_alloc_context3(NULL);
//m_lpCodecCtx = avcodec_alloc_context3(m_lpCodec);  //both avcodec_alloc_context3 way  I tried, not work
if (m_lpCodecCtx == NULL)
{
LOGI("avcodec_alloc_context3 NULL error");
return 1;
}


//AVMediaCodecContext *mediacodec_ctx = NULL;
//mediacodec_ctx = av_mediacodec_alloc_context();
//av_mediacodec_default_init(m_lpCodecCtx, mediacodec_ctx, NULL) ;
//m_lpCodecCtx->thread_count = 1;
//m_lpCodecCtx->opaque = (void*)this ;
//m_lpCodecCtx->height= lpInitParam->uMediaInfo.struVideoInfo.dwHeight;
//m_lpCodecCtx->width= lpInitParam->uMediaInfo.struVideoInfo.dwWidth;
 //m_lpCodecCtx->pix_fmt = AV_PIX_FMT_NV12;    // So which parameters do I need to set to ensure I can call avcodec_open2 successfully?
m_lpCodecCtx->get_format = GetHWFormat ;
LOGI("avcodec_alloc_context3 NULL succ and set para");


nRet = avcodec_open2(m_lpCodecCtx, m_lpCodec, NULL) ;
if(nRet != 0)
{
LOGI("avcodec_open2 hw decoder error nRet[%d] height[%d] width[%d] fmt[%d]", nRet, m_lpCodecCtx->height, m_lpCodecCtx->width, m_lpCodecCtx->pix_fmt);
return 1 ;
}
LOGI("avcodec_open2 hw succ nRet[%d]", nRet);
m_lpFrame = av_frame_alloc( ) ;


if (m_lpFrame == NULL)
{
return 1;
}


LOGI("av_frame_alloc succ m_lpFrame[%x]", m_lpFrame);
m_lpSwFrame = av_frame_alloc( ) ;


if (m_lpSwFrame == NULL)
{
return 1;
}
LOGI("av_frame_alloc succ m_lpSwFrame[%x]", m_lpSwFrame);
return 0;
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://ffmpeg.org/pipermail/libav-user/attachments/20180329/a555b287/attachment.html>


More information about the Libav-user mailing list