rv1126解码的一些原理
rv1126解码篇中,出现最重要的两个api一个是,send_vdec_thread线程里面调用的RK_MPI_SYS_SendMediaBuffer,把数据发到解码器。另外一个是read_vdec_thread线程的RK_MPI_SYS_GetMediaBuffer获取解码器里面的数据。
今天想探讨一下他的底层原理。是怎么实现的,为什么在其中的一个线程里调用RK_MPI_SYS_SendMediaBuffer发送数据,另外一个线程调用RK_MPI_SYS_GetMediaBuffer,就可以获取到数据为什么呢?不管是海思还是瑞芯微的编解码,都是放到一个地方,再从其他地方拿来使用,流程知道,但是实现的原理不知道。通过画图分析。
用解码演示,编码也是一样的。下面两个柱子就表示两个线程,左边的send_vdec_thread发的是vdec的数据,有没有想过这个数据send后会到哪里?
其实vdec存放在一个队列里面,可以像一下,队列是起到一个桥梁的作用,让两个线程通讯。
所以上面的两个线程都要使用vdec的数据,所以下图,瑞芯微在rkmedia底层维护了一个队列。
这个队列不仅是放解码数据,编码数据它也能放,或者一些其他数据都能放,所以底层是void*的
所以vdec的数据发到了这个rk-queue里面,所以这个队列里面就有vdec的每一帧数据,队列有了数据RK_MPI_SYS_GetMediaBuffer线程就可以使用接口获取到每一帧的vdec的数据。大致的一个框图就是这样的
但是还有一个问题, 左边发的是编码后的数据,右边拿的应该是解码后的数据,所以底层这个队列不止要存放数据,还要能解码数据,如果是编码,还要对数据编码。就是还要根据传入模模块号编解码数据。如果模块号是ednc就编码,vdec就是解码。
总结:在RV1126/RV1109上面若对数据进行编解码操作通常使用RK_MPI_SYS_SendMediaBuffer根据MOD_ID对其进行对应的编解码工作,编解码工作完成之后就把对应的数据存放到RKMEDIA_QUEUE里面。若要获取对应的编解码数据,则调用RK_MPI_SYS_GetMediaBuffer从RKMEDIA_QUEUE获取每一帧编解码数据。应该海思平台也是这样做的。
真正情况就是通过编解码器拿到数据,还有一种把编码器bind之后也能拿到数据,但是bind拿到数据是最原始的数据,没有修改的。一般数据都是VI的数据,如果是文件的就要通过RK_MPI_SYS_SendMediaBuffer拿到。
在RV1126上面做对应的编解码工作,一般分为两种:
- .RK_MPI_SYS_Bind方式,RK_MPI_SYS_Bind方式通常用在直接获取CMOS摄像头的数据(原生的VI数据),并且不做任何加工处理。
- .RK_MPI_SYS_SendMediaBuffer方式,这种方式能够解码CMOS摄像头VI处理过后的数据(包括:opencv、yolov3、asfort)或者读取文件的编解码数据等等。