seymour

seymour

0个粉丝

10

问答

0

专栏

0

资料

seymour  发布于  2016-05-11 16:12:55
采纳率 0%
10个问答
7531

hi3536 VDEC 创建channels问题

 
用下面的方式创建一个VDEC channel,例如0 channel:
HI_MPI_VDEC_SetChnParam(0,…)
HI_MPI_VDEC_StartRecvStream(0)
摧毁channel 0, 我是用下面这种方式:
HI_MPI_VDEC_StartRecvStream(0)
HI_MPI_VDEC_DestroyChn(0)。
现在问题是,我创建或摧毁channel 0 都能成功,但是我不能再次创建它。下一次我需要一个channel时,我必须创建channel 1. 这样如此循环,最多只能创建128个通道,如果我要继续创建通道必须要关闭MIPI系统(相当于重启应用程序)。重新又从channel 0 开始创建。(我是播放完一个视频后就会摧毁一个channel,再重新创建一个channel来播放接下来的视频。如果我需要同时解码16路视频的话,一次必须创建16个channel,循环不了几次)
还一个就是我不会与其他模块绑定vdec通道。
是我创建和摧毁channel的方式有问题,还是我的思路有问题。
希望大神们给一点意见和指点。
我来回答
回答10个
时间排序
认可量排序

zhuangweiye

8个粉丝

0

问答

0

专栏

0

资料

zhuangweiye 2016-05-11 16:40:45
认可0
反复使用一个channel号是没有问题的

楼主,使用同一个通道号在销毁后重新创建VDEC时有什么问题,错误log是什么,放上来看看

seymour

0个粉丝

10

问答

0

专栏

0

资料

seymour 2016-05-11 17:13:14
认可0
不好意思!久等了
[11/05 09:11:20.62174 FF0]: Calling HI_MPI_VDEC_CreateChn for Channel 0 in SAMPLE_COMM_VDEC_Start
[11/05 09:11:20.62174 FF0]: HI_MPI_VDEC_CreateChn chn 0 failed in SAMPLE_COMM_VDEC_Start: LINE: 963 with 0xffffffff!
[11/05 09:11:20.62174 FF0]: Start vdec failed with ffffffff!

zhuangweiye

8个粉丝

0

问答

0

专栏

0

资料

zhuangweiye 2016-05-11 17:21:05
认可0
一般VDEC正常的错误都是 0xa00580xx

能知道具体错在哪个函数吗?

seymour

0个粉丝

10

问答

0

专栏

0

资料

seymour 2016-05-11 17:59:36
认可0
int s32Ret = HI_MPI_VDEC_CreateChn(d->vdec, &pstAttr);
HI_MPI_VDEC_CreateChn 有可能会返回-1 或者 0xffffffff吗?  我看文档,就像你说的都是0xa00580xx这些

ngswfx

2个粉丝

55

问答

1

专栏

40

资料

ngswfx 2016-05-11 18:21:29
认可0
本帖最后由 ngswfx 于 2016-5-11 18:48 编辑

HI_MPI_VDEC_SetChnParam(0,…)
HI_MPI_VDEC_StartRecvStream(0)
摧毁channel 0, 我是用下面这种方式:
HI_MPI_VDEC_StartRecvStream(0)
HI_MPI_VDEC_DestroyChn(0)。

这个动作不对呀,你笔误吧,关闭通道前要停止接收,HI_MPI_VDEC_StopRecvStream(0),并且保证HI_MPI_VDEC_SendStream不会被调用到。

////////////////////////////////////可以明确的告诉你,只要过程合理,不是超级频繁,一分钟为量级,你来回折腾1天,这个通道的MPI也不会有事。当然,要是MMZ内存不够了,肯定失败。

我在数据回调中,直接根据过来流有没有解码出数据,来回从CIF-D1-720-1080不停切换某一个通道的解码规格,直到能解码得到YUV,工作都没事。

////////////////另外增加一个保护,用一个全局变量,例如bVdecChlOpened[0]=true or false; 来记录创建或者销毁。保证销毁过程中,或者创建前,不会输入数据到解码器HI_MPI_VDEC_SendStream。

///////////每次流程重复流程
HI_MPI_VDEC_CreateChn
HI_MPI_VDEC_GetPrtclParam
HI_MPI_VDEC_SetPrtclParam
HI_MPI_VDEC_SetChnParam
HI_MPI_VDEC_StartRecvStream

送数据

暂停送数据

HI_MPI_VDEC_StopRecvStream(VdChn);
HI_MPI_VDEC_DestroyChn(VdChn);

////////////////////////////////////////////////////////////////////////////////做解码,最怕的就是来回轮切图像,能把人郁闷死。不过还好,海斯的MPI还是比较结实的。只需要考虑自己线程取流断流的资源分配问题。

//MPI解码器通常没事。如果明确是同一种格式流,还有一种做法能规避资源释放问题:

//那就是不释放。不管是不是一路同一个图像,直接往里面送就可以了,对MPI VDEC解码器来说,他可不区分到底是那个IPC的图像,他只认关键帧。海斯MPI少了一个清空解码器缓冲的函数,要是有就更好了。换流仅仅需要清空一次解码器缓冲,这样保险些,应该会更稳定些。目前的风险是,送入另外一个IPC数据前,解码器缓冲里面还有部分数据(H264的机制决定的),其实底层会过滤掉的,但有几率会花一下屏。咱们仅仅需要尽量做到,换IPC数据后,第一个送入的数据包是一个关键帧,这样问题几率会小很多。

seymour

0个粉丝

10

问答

0

专栏

0

资料

seymour 2016-05-11 19:10:18
认可0
是我的笔误,是HI_MPI_VDEC_StopRecvStream(VdChn);
HI_MPI_VDEC_GetPrtclParam
HI_MPI_VDEC_SetPrtclParam 这两个mpi hi3536文档没有讲到

现在是,我去摧毁channel时,没有出现任何错误。

seymour

0个粉丝

10

问答

0

专栏

0

资料

seymour 2016-05-11 19:44:12
认可0
HI_S32 SAMPLE_COMM_VDEC_Stop(HI_S32 id)
{
    HI_S32 i = 0, max= 20;       
        VDECH *d = get_vd(id);
        if(!d)
                return 0;
               
        vdec_reset(id);
        while(!flush_vdec(id))
        {
                i = 0;
                while(!flush_vdec(id))
                                if(i++ >10000)
                                        break;
                usleep(10000);
                LOG("Flush iteration %d", i);
        }       
        LOG("Vdec flushed after %d iterations", i);
        for(i=0; i                 {
                        if(!HI_MPI_VDEC_StopRecvStream(d->vdec))
                                break;
                        usleep(50000);
                }
        if(i==max)
        {
                vdec_status(id);
                CHECK_CHN_RET(HI_MPI_VDEC_StopRecvStream(d->vdec), d->vdec, "HI_MPI_VDEC_StopRecvStream");      
    };
        LOG("HI_MPI_VDEC_StopRecvStream (%d) called for channel %d ", id, d->vdec);
        if(1)
        {
                mutex_lock(&chn_m);
                LOG("Destroying channel %d, hw channel %d", d->id, d->vdec);
                int s32Ret = HI_MPI_VDEC_DestroyChn(d->vdec);
                mutex_unlock(&chn_m);
                CHECK_CHN(s32Ret, d->vdec, "HI_MPI_VDEC_DestroyChn");
        }
       
    return HI_SUCCESS;
}

ngswfx

2个粉丝

55

问答

1

专栏

40

资料

ngswfx 2016-05-11 20:13:15
认可0
本帖最后由 ngswfx 于 2016-5-11 22:45 编辑

[quote][url=forum.php?mod=redirect&goto=findpost&pid=29950&ptid=11286]seymour 发表于 2016-5-11 19:10[/url]
是我的笔误,是HI_MPI_VDEC_StopRecvStream(VdChn);
HI_MPI_VDEC_GetPrtclParam
HI_MPI_VDEC_SetPrtclPar ...[/quote]

这是配置解码器参数的,不是出问题关键点   MPI1.0里面的  3.0里面是那个GetProtocolParam

ngswfx

2个粉丝

55

问答

1

专栏

40

资料

ngswfx 2016-05-11 20:32:57
认可0
本帖最后由 ngswfx 于 2016-5-11 21:10 编辑

[quote][url=forum.php?mod=redirect&goto=findpost&pid=29951&ptid=11286]seymour 发表于 2016-5-11 19:44[/url]
HI_S32 SAMPLE_COMM_VDEC_Stop(HI_S32 id)
{
    HI_S32 i = 0, max= 20;       
[/quote]

这些usleep和循环看得头大,感觉比较危险。你可以测试一下SAMPLE_COMM_VDEC_Stop时间占用。尽量控制在1ms以内完成。任何长时间等待,尤其在流回调里面都是危险的,因为40ms后,数据还会触发,如果被阻塞了,连锁反应,不异常才怪,弄不好,还把IPC搞死了:lol 。

////////////////////////////////////////////////////////////////////////////////////
我没这么干过。感觉这个SAMPLE_COMM_VDEC_Stop搞得太费劲。

这不会是海斯给的范例代码吧?

直接在下面这个基础上改成关闭一个通道不就可以了,简单高效。创建通道时再来检查,能否创建成功。
HI_S32 SAMPLE_COMM_VDEC_Stop(HI_S32 s32ChnNum)
{
    HI_S32 i;       

    for(i=0; i     {
        CHECK_CHN_RET(HI_MPI_VDEC_StopRecvStream(i), i, "HI_MPI_VDEC_StopRecvStream");      
        CHECK_CHN_RET(HI_MPI_VDEC_DestroyChn(i), i, "HI_MPI_VDEC_DestroyChn");
    }

    return HI_SUCCESS;
}

断流,我就只用了2个函数,不做返回检查,也不做状态检查。也不延时等待,默认认为肯定销毁了。

如果创建的时候不成功,才检查,如果创建失败,尝试再次销毁,然后重复3次,如果还失败,检查MMZ剩余内存够不够,如果不够,不管了(由于内存不够导致的解码通道创建失败,这个无解,顶多全局检查一遍所有解码通道,重新将浪费内存的解码通道释放,例如当前解码的图像是720的,而创建的是1080P的解码通道。还有一种情况是,这个通道根本没有码流,直接释放,开启CIF解码,送入一个CIF 264数据,显示logo,或者干脆黑屏,也可以不导入数据,直接关闭通道,释放内存,由于VO没有释放,此时这个通道图像静止于最后图像。这部分工作,我这边有个主线程里面检查所有解码通道当前解码图像格式,尽量用最低解码格式,节约内存,解码超级费内存,1个1080估计要用约20M内存),如果内存足够,还不成功,估计MPI异常,程序重启或者设备重启。

/////////////////////////不过这不排除,3536和3520D MPI部分,结实程度有差异,我一直搞3520D,没搞过3536。但感觉不会这么差,几次重新 创建就不行了。



mutex_lock(&chn_m);
                LOG("Destroying channel %d, hw channel %d", d->id, d->vdec);
                int s32Ret = HI_MPI_VDEC_DestroyChn(d->vdec);
                mutex_unlock(&chn_m);

这部分,我也不理解,你锁定这个干什么呀?  chn_m还是个全局变量,要是有128个还好说,否则,一个时刻,只允许一个通道被释放。其他释放通道通道都在这里等待。如果释放和创建不是线性执行,是在不同线程里面的动作,这肯定要出问题的。
这边还没有释放掉,其他地方已经在开始创建了。

建议你直接把函数改成下面这种简单的测试一下。
HI_S32 SAMPLE_COMM_VDEC_Stop(HI_S32 s32ChnNum,bool bSupportReleaseAgain=false);
HI_S32 SAMPLE_COMM_VDEC_Stop(HI_S32 id,bool bSupportReleaseAgain)
{
        //如果仅仅允许释放一次,这个要看底层能不能这么配合,也就是释放一次如果失败,还可以调用,估计应该不支持多次释放,首先是没必要,写函数不会这么做的,既然调用了释放,如果没有释放掉,再次释放,也不会释放掉的。
        //即便异步非阻塞释放,既然状态已经下发,再次调用,也没有实质意义。
        if(!bSupportReleaseAgain){
                if(!bDecChlInted[id])
                        return  HI_SUCCESS;
        }
        HI_MPI_VDEC_StopRecvStream(id);
        HI_MPI_VDEC_DestroyChn(id);
        bDecChlInted[id]=false;  //下次开启通道时,判断这个的状态,如果为true,通道创建是好的,不用再次创建了。
        return HI_SUCCESS;
}
平时直接调用SAMPLE_COMM_VDEC_Stop(i);   如果销毁了,还是不能创建成功,尝试三次 SAMPLE_COMM_VDEC_Stop(i,true);
//////////////////////////////////////////

seymour

0个粉丝

10

问答

0

专栏

0

资料

seymour 2016-05-12 09:56:32
认可0
非常感谢ngswfx的意见,我按照这方式测试下。:handshake
或将文件直接拖到这里
悬赏:
E币
网盘
* 网盘链接:
* 提取码:
悬赏:
E币

Markdown 语法

  • 加粗**内容**
  • 斜体*内容*
  • 删除线~~内容~~
  • 引用> 引用内容
  • 代码`代码`
  • 代码块```编程语言↵代码```
  • 链接[链接标题](url)
  • 无序列表- 内容
  • 有序列表1. 内容
  • 缩进内容
  • 图片![alt](url)
+ 添加网盘链接/附件

Markdown 语法

  • 加粗**内容**
  • 斜体*内容*
  • 删除线~~内容~~
  • 引用> 引用内容
  • 代码`代码`
  • 代码块```编程语言↵代码```
  • 链接[链接标题](url)
  • 无序列表- 内容
  • 有序列表1. 内容
  • 缩进内容
  • 图片![alt](url)
相关问答
无更多相似问答 去提问
举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

易百纳技术社区