FFMPEG find decoder 軟硬解碼
针对方案:基于NXP S32V234的疲劳监测、前方碰撞、车道偏离、全景监控Eagle Eye ADAS方案
您好 想請教
我想在s32v234 上做影像的視頻解碼
目前有一份代碼是測試用 將讀取到的影片作解碼後 轉成 cv::Mat 後播放
在pc端上 可以正常執行 ffmpeg版本為2.8.5 但是在板子上會發生找不到解碼器的狀況
相關代碼如圖:
執行結果:Codec not found
追查pCodec->id 為28 搜尋後發現是mp4 的格式(我的輸入影片也是mp4)
目前試過的方法
- 重build ffmpeg 包含 libavcode.a 和其他 函式庫 有適用的參數 還請指教
- 試過build libx264 但那似乎是跟編碼相關(網路搜尋大多是此類)
- 嘗試硬解碼(find_decoder_by_name) 但我在板子上輸入ffmpeg -hwaccels 出現的選項是空的 我能透過重build 得到硬體加速的選項嗎?
感謝 回答
最佳解
1、就是调用 avcodec_find_decoder() 获取指定类型的解码器
2、安装完 VSDK 后可以找到 s32v234_sdk 目录,里面有相应的 ffmpeg 的库文件,如有库文件相关问题,一般直接使用配套的 VSDK 中的 ffmpeg 库文件即可,文件系统本身含有这类的库文件。您这边自己编译 ffmpeg 的话,那这个库肯定也是要替换成你自己的了,就是把这个自己编译的库的名称修改成你要替换的就行了
3、推荐使用 S32DS,支持 S32V234 平台,调试起来相对方便
4、可能是 CodecId 设置有问题,MP4 是封装格式,编解码器的设定可以直接设定如果你确定解封转后是 H264 格式的话,可直接设定,例如:
enum AVCodecID emViDecId = AV_CODEC_ID_H264;
AVCodec* ptCodec = NULL;
ptCodec = avcodec_find_decoder( emViDecId )
5、硬编码部分是无法通过 ffmpeg 的参数设置进行开启的,两者在使用上没有太多的关联,需要另外学习其使用
最佳解
想問 你們是自己實現ffmpeg 的 h264 解碼嗎 還是說存粹調用 av_find_decoder/av_find_decoder_by_name ?
另外 想請教 我在pc 端上build 完 ffmpeg, cross-compile nxp 的代碼後
是不是還需要在板子上更新新的.so檔? 猜測是我板子上的.so 太舊 (/usr/lib/libavcodex.so.56 ) 具體怎麼更換 再請教您?
或是透過 vsdk 裡面的 SDI_H264DecDescriptor 去做 解碼的?
沒有安裝S32DS 我是用vscode 寫完再cross-compile 成.elf
看到你說使用硬解碼 所以說 我該怎麼在s32v234開啟 因為 我用了 ffmpeg -hwaccels 並沒有任何可支援的選項
很多問題 麻煩您了
最佳解
#ifndef APEX2_EMULATE
#include "apex.h"
#else
#include "acf_lib.hpp"
#endif
#include <apexcv_base.h>
#include <common_helpers.h>
#include <string>
#include "frame_output_v234fb.h"
typedef io::FrameOutputV234Fb io_FrameOutput_t;
#ifdef __cplusplus
extern "C"
{
#endif
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavutil/avutil.h>
#include <libavutil/attributes.h>
#include <libavutil/opt.h>
#include <libavutil/mathematics.h>
#include <libavutil/imgutils.h>
#include <libavutil/samplefmt.h>
#include <libavutil/timestamp.h>
#include <libavutil/mathematics.h>
#include <libavutil/channel_layout.h>
#include <libavutil/common.h>
#include <libavformat/avio.h>
#include <libavutil/file.h>
#include <libswresample/swresample.h>
#ifdef __cplusplus
};
#endif
#include <iostream>
#include <opencv/cv.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
int thread_exit=0;
cv::Mat avFrame2Mat(AVFrame* pAvFrame, AVCodecContext*pCodecCtx) {
AVFrame* pFrameBGR = av_frame_alloc();
int size = avpicture_get_size(AV_PIX_FMT_BGR24, pCodecCtx->width, pCodecCtx->height);
uint8_t *out_buffer = (uint8_t *)av_malloc(size);
avpicture_fill((AVPicture *)pFrameBGR, out_buffer, AV_PIX_FMT_BGR24, pCodecCtx->width, pCodecCtx->height);
struct SwsContext *img_convert_ctx;
img_convert_ctx = sws_getContext(pCodecCtx->width,
pCodecCtx->height,
pCodecCtx->pix_fmt,
pCodecCtx->width,
pCodecCtx->height,
AV_PIX_FMT_BGR24,
SWS_BICUBIC,
NULL, NULL, NULL);
sws_scale(img_convert_ctx,
(const uint8_t* const*)pAvFrame->data,
pAvFrame->linesize,
0,
pCodecCtx->height,
pFrameBGR->data,
pFrameBGR->linesize);
cv::Mat mRGB(cv::Size(pCodecCtx->width, pCodecCtx->height), CV_8UC3);
mRGB.data = (uchar*)pFrameBGR->data[0];
av_free(pFrameBGR);
sws_freeContext(img_convert_ctx);
return mRGB;
}
/****************************************************************************
* Main function
****************************************************************************/
int main(int argc, char* argv[])
{
io_FrameOutput_t aFrameOutput;
AVFormatContext *pFormatCtx;
int i, videoindex;
AVCodecContext *pCodecCtx;
AVCodec *pCodec;
AVFrame *pFrame,*pFrameYUV;
AVPacket *packet;
struct SwsContext *img_convert_ctx;
int ret, got_picture;
int screen_w=0,screen_h=0;
char* filepath=argv[1];
av_register_all();
avformat_network_init();
pFormatCtx = avformat_alloc_context();
if(avformat_open_input(&pFormatCtx,filepath,NULL,NULL)!=0){
printf("Couldn't open input stream.\n");
return -1;
}
if(avformat_find_stream_info(pFormatCtx,NULL)<0){
printf("Couldn't find stream information.\n");
return -1;
}
videoindex=-1;
/*for(i=0; i<pFormatCtx->nb_streams; i++)
if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO){
videoindex=i;
break;
}*/
videoindex = av_find_best_stream(pFormatCtx, AVMEDIA_TYPE_VIDEO, videoindex, -1, NULL, 0);
if(videoindex==-1){
printf("Didn't find a video stream.\n");
return -1;
}
pCodecCtx=pFormatCtx->streams[videoindex]->codec;
//pCodec = avcodec_find_decoder_by_name("h264_mediacodec");
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
avcodec_alloc_context3(pCodec);
if(!av_codec_is_decoder(pCodec))
{
printf("Codec not found.\n");
return -1;
}
if(pCodec == NULL)
{
printf("Codec is NULL.\n");
return -1;
}
if(avcodec_open2(pCodecCtx, pCodec,NULL)<0)
{
printf("Could not open codec.\n");
return -1;
}
pFrame=av_frame_alloc();
pFrameYUV=av_frame_alloc();
//uint8_t *out_buffer=(uint8_t *)av_malloc(avpicture_get_size(PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height));
//avpicture_fill((AVPicture *)pFrameYUV, out_buffer, PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);
packet=(AVPacket *)av_malloc(sizeof(AVPacket));
printf("---------------File Information------------------\n");
av_dump_format(pFormatCtx,0,filepath,0);
printf("-------------------------------------------------\n");
img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
//Event Loop
for (;;) {
//------------------------------
if(av_read_frame(pFormatCtx, packet)>=0){
if(packet->stream_index==videoindex){
ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);
if(ret < 0){
printf("Decode Error.\n");
return -1;
}
if(got_picture){
cv::Mat mRGB = avFrame2Mat(pFrame, pCodecCtx);
aFrameOutput.PutFrame(mRGB.data, false);
}
}
av_free_packet(packet);
}else{
//Exit Thread
thread_exit=1;
break;
}
}
sws_freeContext(img_convert_ctx);
//--------------
//av_free(out_buffer);
av_free(pFrameYUV);
avcodec_close(pCodecCtx);
avformat_close_input(&pFormatCtx);
return 0;
}
最佳解
S32V234 影像软解码:支持使用 FFMPEG 库设定解码器进行软解码
S32V234 影像硬解码:可根据官方 SDK 提供单图片解码 demo:isp_h264dec_single_stream,自行开发