- 收藏
- 点赞
- 分享
- 举报
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);
}
Error
if (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. 内容
- 缩进内容
- 图片![alt](url)
-
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
-
5SS928的emmc有32GB,bootargs设置使用16GB,但是为啥能用的只有rootfs的大小
-
33SS928怎样烧写ubuntu系统
-
10ToolPlatform下载rootfs提示网络失败
-
10谁有GK7205V500的SDK
-
5Hi3516CV610 烧录不进去
-
10Hi3559AV100 芯片硬解码h265编码格式的视频时出现视频播放错误,解码错误信息 s32PackErr:码流有错
-
5海思SS928 / SD3403的sample_venc.c摄像头编码Demo中,采集到的摄像头的YUV数据在哪个相关的函数中?
-
5海鸥派openEuler无法启动网卡,连接WIFI存在问题
-
66有没有ISP相关的巨佬帮忙看看SS928对接IMX347的图像问题
-
50求助hi3559与FPGA通过SLVS-EC接口对接问题
举报类型
- 内容涉黄/赌/毒
- 内容侵权/抄袭
- 政治相关
- 涉嫌广告
- 侮辱谩骂
- 其他
详细说明