- 收藏
- 点赞
- 分享
- 举报
hi3559AV 硬解码mp4,ts等封装好的视频
由于项目需要,需要在hi3559 平台上做播放器,用海思自带的demo 是跑通了,但是他解码的是.h264 和.h265等纯码流形式的视频,但是项目需要直接打开mp4,ts,flv等封装好的视频文件,现在思路是想用ffmpeg 去解封装,然后解封装之后的数据去给海思解码通道去解码。ffmpeg解封装代码```cpp
int dcodec_open(const char *url)
{
// 初始化格式上下文AVFormatContext *fmt_ctx =NULL;fmt_ctx = avformat_alloc_context();if (fmt_ctx == NULL) {printf("failed to alloc format context\n");goto _Error;}// 打开输入流if (avformat_open_input(&fmt_ctx, url, NULL, NULL) < 0) {printf("failed to open input url\n");goto _Error;}// 读取媒体文件信息if (avformat_find_stream_info(fmt_ctx, NULL) < 0) {printf("failed to find stream\n");goto _Error;}av_dump_format(fmt_ctx, 0, url, 0);// 寻找音频流和视频流下标int video_index = -1, audio_index = -1;for (int i = 0; i < fmt_ctx->nb_streams; i++) {if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {printf("video_index\n");video_index = i;}}auto streams =fmt_ctx->streams;// 由打印的视频文件信息确定码流类型char videofile[128];printf("\ntype the name of output videofile:");scanf("%s", videofile);FILE *fvideo = fopen(videofile, "w+");AVPacket *packet = av_packet_alloc();while (av_read_frame(fmt_ctx, packet) == 0) {if (packet->stream_index == video_index) {fwrite(packet->data, 1, packet->size, fvideo);}av_packet_unref(packet);}Errorif (fmt_ctx) avformat_close_input(&fmt_ctx);if (fvideo) fclose(fvideo);if (packet) av_packet_free(&packet);
}
然后下面是sample vdec里面的COMM_VDEC_SendStream 函数代码片段
HI_VOID * COMM_VDEC_SendStream(HI_VOID *pArgs){VDEC_THREAD_PARAM_S *pstVdecThreadParam =(VDEC_THREAD_PARAM_S *)pArgs;HI_BOOL bEndOfStream = HI_FALSE;HI_S32 s32UsedBytes = 0, s32ReadLen = 0;FILE *fpStrm=NULL;HI_U8 *pu8Buf = NULL;VDEC_STREAM_S stStream;HI_BOOL bFindStart, bFindEnd;HI_U64 u64PTS = 0;HI_U32 u32Len, u32Start;HI_S32 s32Ret, i;HI_CHAR cStreamFile[256];prctl(PR_SET_NAME, "VideoSendStream", 0,0,0);snprintf(cStreamFile, sizeof(cStreamFile), "%s/%s", pstVdecThreadParam->cFilePath,pstVdecThreadParam->cFileName);if(cStreamFile != 0){fpStrm = fopen(cStreamFile, "rb");if(fpStrm == NULL){SAMPLE_PRT("chn %d can't open file %s in send stream thread!\n", pstVdecThreadParam->s32ChnId, cStreamFile);return (HI_VOID *)(HI_FAILURE);}}printf("\n \033[0;36m chn %d, stream file:%s, userbufsize: %d \033[0;39m\n", pstVdecThreadParam->s32ChnId,pstVdecThreadParam->cFileName, pstVdecThreadParam->s32MinBufSize);pu8Buf = malloc(pstVdecThreadParam->s32MinBufSize);if(pu8Buf == NULL){SAMPLE_PRT("chn %d can't alloc %d in send stream thread!\n", pstVdecThreadParam->s32ChnId, pstVdecThreadParam->s32MinBufSize);fclose(fpStrm);return (HI_VOID *)(HI_FAILURE);}fflush(stdout);u64PTS = pstVdecThreadParam->u64PtsInit;while (1){if (pstVdecThreadParam->eThreadCtrl == THREAD_CTRL_STOP){break;}else if (pstVdecThreadParam->eThreadCtrl == THREAD_CTRL_PAUSE){sleep(1);continue;}bEndOfStream = HI_FALSE;bFindStart = HI_FALSE;bFindEnd = HI_FALSE;u32Start = 0;fseek(fpStrm, s32UsedBytes, SEEK_SET);s32ReadLen = fread(pu8Buf, 1, pstVdecThreadParam->s32MinBufSize, fpStrm);if (s32ReadLen == 0){if (pstVdecThreadParam->bCircleSend == HI_TRUE){memset(&stStream, 0, sizeof(VDEC_STREAM_S) );stStream.bEndOfStream = HI_TRUE;HI_MPI_VDEC_SendStream(pstVdecThreadParam->s32ChnId, &stStream, -1);s32UsedBytes = 0;fseek(fpStrm, 0, SEEK_SET);s32ReadLen = fread(pu8Buf, 1, pstVdecThreadParam->s32MinBufSize, fpStrm);}else{break;}}if (pstVdecThreadParam->s32StreamMode==VIDEO_MODE_FRAME && pstVdecThreadParam->enType == PT_H264){for (i=0; i<s32ReadLen-8; i++){int tmp = pu8Buf[i+3] & 0x1F;if ( pu8Buf[i ] == 0 && pu8Buf[i+1] == 0 && pu8Buf[i+2] == 1 &&(((tmp == 0x5 || tmp == 0x1) && ((pu8Buf[i+4]&0x80) == 0x80)) ||(tmp == 20 && (pu8Buf[i+7]&0x80) == 0x80))){bFindStart = HI_TRUE;i += 8;break;}}for (; i<s32ReadLen-8; i++){int tmp = pu8Buf[i+3] & 0x1F;if ( pu8Buf[i ] == 0 && pu8Buf[i+1] == 0 && pu8Buf[i+2] == 1 &&(tmp == 15 || tmp == 7 || tmp == 8 || tmp == 6 ||((tmp == 5 || tmp == 1) && ((pu8Buf[i+4]&0x80) == 0x80)) ||(tmp == 20 && (pu8Buf[i+7]&0x80) == 0x80))){bFindEnd = HI_TRUE;break;}}if(i>0)s32ReadLen = i;if (bFindStart == HI_FALSE){SAMPLE_PRT("chn %d can not find H264 start code!s32ReadLen %d, s32UsedBytes %d.!\n",pstVdecThreadParam->s32ChnId, s32ReadLen, s32UsedBytes);}if (bFindEnd == HI_FALSE){s32ReadLen = i+8;}}else if (pstVdecThreadParam->s32StreamMode==VIDEO_MODE_FRAME && pstVdecThreadParam->enType == PT_H265){HI_BOOL bNewPic = HI_FALSE;for (i=0; i<s32ReadLen-6; i++){HI_U32 tmp = (pu8Buf[i+3]&0x7E)>>1;bNewPic = ( pu8Buf[i+0] == 0 && pu8Buf[i+1] == 0 && pu8Buf[i+2] == 1&& (tmp >= 0 && tmp <= 21) && ((pu8Buf[i+5]&0x80) == 0x80) );if (bNewPic){bFindStart = HI_TRUE;i += 6;break;}}for (; i<s32ReadLen-6; i++){HI_U32 tmp = (pu8Buf[i+3]&0x7E)>>1;bNewPic = (pu8Buf[i+0] == 0 && pu8Buf[i+1] == 0 && pu8Buf[i+2] == 1&&( tmp == 32 || tmp == 33 || tmp == 34 || tmp == 39 || tmp == 40 || ((tmp >= 0 && tmp <= 21) && (pu8Buf[i+5]&0x80) == 0x80) ));if (bNewPic){bFindEnd = HI_TRUE;break;}}if(i>0)s32ReadLen = i;if (bFindStart == HI_FALSE){SAMPLE_PRT("chn %d can not find H265 start code!s32ReadLen %d, s32UsedBytes %d.!\n",pstVdecThreadParam->s32ChnId, s32ReadLen, s32UsedBytes);}if (bFindEnd == HI_FALSE){s32ReadLen = i+6;}}else if (pstVdecThreadParam->enType == PT_MJPEG || pstVdecThreadParam->enType == PT_JPEG){for (i=0; i<s32ReadLen-1; i++){if (pu8Buf[i] == 0xFF && pu8Buf[i+1] == 0xD8){u32Start = i;bFindStart = HI_TRUE;i = i + 2;break;}}for (; i<s32ReadLen-3; i++){if ((pu8Buf[i] == 0xFF) && (pu8Buf[i+1]& 0xF0) == 0xE0){u32Len = (pu8Buf[i+2]<<8) + pu8Buf[i+3];i += 1 + u32Len;}else{break;}}for (; i<s32ReadLen-1; i++){if (pu8Buf[i] == 0xFF && pu8Buf[i+1] == 0xD9){bFindEnd = HI_TRUE;break;}}s32ReadLen = i+2;if (bFindStart == HI_FALSE){SAMPLE_PRT("chn %d can not find JPEG start code!s32ReadLen %d, s32UsedBytes %d.!\n",pstVdecThreadParam->s32ChnId, s32ReadLen, s32UsedBytes);}}else{if((s32ReadLen != 0) && (s32ReadLen < pstVdecThreadParam->s32MinBufSize)){bEndOfStream = HI_TRUE;}}stStream.u64PTS = u64PTS;stStream.pu8Addr = pu8Buf + u32Start;stStream.u32Len = s32ReadLen;stStream.bEndOfFrame = (pstVdecThreadParam->s32StreamMode==VIDEO_MODE_FRAME)? HI_TRUE: HI_FALSE;stStream.bEndOfStream = bEndOfStream;stStream.bDisplay = 1;SendAgain:s32Ret=HI_MPI_VDEC_SendStream(pstVdecThreadParam->s32ChnId, &stStream, pstVdecThreadParam->s32MilliSec);if( (HI_SUCCESS != s32Ret) && (THREAD_CTRL_START == pstVdecThreadParam->eThreadCtrl) ){usleep(pstVdecThreadParam->s32IntervalTime);goto SendAgain;}else{bEndOfStream = HI_FALSE;s32UsedBytes = s32UsedBytes +s32ReadLen + u32Start;u64PTS += pstVdecThreadParam->u64PtsIncrease;}usleep(pstVdecThreadParam->s32IntervalTime);}/* send the flag of stream end */memset(&stStream, 0, sizeof(VDEC_STREAM_S) );stStream.bEndOfStream = HI_TRUE;HI_MPI_VDEC_SendStream(pstVdecThreadParam->s32ChnId, &stStream, -1);printf("\033[0;35m chn %d send steam thread return ... \033[0;39m\n", pstVdecThreadParam->s32ChnId);fflush(stdout);if (pu8Buf != HI_NULL){free(pu8Buf);}fclose(fpStrm);return (HI_VOID *)HI_SUCCESS;}
这里海思的函数主要是打开文件,然后去分割每一个视频帧的大小,fseek(fpStrm, s32UsedBytes, SEEK_SET)将文件指针位置定位到s32UsedBytes处,一开始为0位置,s32UsedBytes是变量随着whiile循环逐渐变大,
s32ReadLen = fread(pu8Buf, 1, pstVdecThreadParam->s32MinBufSize, fpStrm);读取一帧数据到pu8Buf,
pstVdecThreadParam->s32StreamMode==VIDEO_MODE_FRAME && pstVdecThreadParam->enType == PT_H264 这里面应该就是找到视频数据流中一帧的长度。
然而我用ffmpeg 解封装之后的数据,包括AVPacket,还有fmt_ctx->streams[i],一帧一帧的数据,如何跟海思sample vdec HI_MPI_VDEC_SendStream(pstVdecThreadParam->s32ChnId, &stStream, pstVdecThreadParam->s32MilliSec) 这个函数中的stStream数据相匹配。或者说我这边用ffmpeg解封的步骤有问题,请大佬解惑
Markdown 语法
- 加粗**内容**
- 斜体*内容*
- 删除线~~内容~~
- 引用> 引用内容
- 代码`代码`
- 代码块```编程语言↵代码```
- 链接[链接标题](url)
- 无序列表- 内容
- 有序列表1. 内容
- 缩进内容
- 图片
-
2022-05-30 18:08:10
-
2016-04-08 09:16:39
-
2018-07-31 11:18:27
-
2016-06-30 10:39:32
-
2019-12-06 14:20:53
-
2018-07-28 10:11:05
-
02018-12-01 10:48:20
-
142016-06-30 11:41:37
-
2018-10-24 14:29:52
-
2017-08-24 16:41:46
-
2017-02-06 10:37:31
-
2018-10-23 19:23:15
-
2016-08-02 17:38:22
-
2016-12-26 21:18:32
-
2018-12-11 15:34:09
-
2019-12-02 16:18:46
-
22015-09-26 15:06:41
-
2016-07-08 14:26:05
-
2015-12-21 11:26:42
-
5hisi3516cv610 + gc4336p 夜晚很模糊
-
5AIISP(功能演示,SC4336P为BGGR,强制转RGGB,会导致颜色异常)
-
5rv1106使用luckfox的SDK,设备树和驱动都写好了,结果设备文件没有生成
-
5海思3516cv610中如何进行SD卡升级,根据官方文档操作,烧录进板子时,走的默认uboot,没有执行uboot升级。
-
5G610Q-IPC-38E 夜晚很暗 有什么办法解决吗 已经补光了
-
10转换模型时,SoC版本里没显示hi3516cv610芯片
-
5hisi3516cv610 使用 yolov8n 模型训练 要如何提高 这里识别的是人
-
10有人在海思平台接过SC035HGS吗
-
5关于hi3519dv500,以SD卡虚拟 U 盘操作
-
5ss928 sample_venc代码移植到openEuler24.03上执行报错 [sample_comm_vi_start_dev]-1068: vi set dev attr failed wi
举报类型
- 内容涉黄/赌/毒
- 内容侵权/抄袭
- 政治相关
- 涉嫌广告
- 侮辱谩骂
- 其他
详细说明

微信扫码分享
QQ好友