mpp icon indicating copy to clipboard operation
mpp copied to clipboard

MPP 无法解码

Open zhguo676 opened this issue 7 years ago • 16 comments

程序在解码时到ret = mpi->decode_get_frame(ctx, &frame)在这里返回0,但是去不了frame,一读取frame,系统崩溃,frame返回为NULL,明明返回时0,成功,为何不能读取,

zhguo676 avatar Oct 26 '18 06:10 zhguo676

返回 0 代表流程正常,没有错误出现,具体有没有取到数据,还是要读 frame 做判断

HermanChen avatar Oct 26 '18 06:10 HermanChen

为什么同样的H264文件,在软解码可以解,MPP不能解,是不是MPP解码不兼容

zhguo676 avatar Oct 26 '18 06:10 zhguo676

Hi3516C 视频流无法解码

zhguo676 avatar Oct 26 '18 06:10 zhguo676

void VideoDecoder::Decoder()

{

RK_U32 pkt_done = 0;

RK_U32 pkt_eos  = 0;

RK_U32 err_info = 0;

MPP_RET ret = MPP_OK;

int size;

MppFrame  frame  = NULL;

RK_U32 width;

RK_U32 height;

RK_U32 hor_stride;

RK_U32 ver_stride;

RK_U32 buf_size;



while(1)

{

	//printf("start Decoder\n");

	if(IsStop==1)

		break;

	//printf("IsStop = %d\n",IsStop);

	//printf("readpos = %d, writepos = %d\n",readpos, writepos);

	if(readpos!=writepos)

	{

		printf("readpos = %d, writepos = %d\n",readpos, writepos);

		size=m_pDecode[readpos].size;

		memcpy(buf, m_pDecode[readpos].pbuff, size);

		// write data to packet

			mpp_packet_write(packet, 0, buf, size);		//把文件读到的数据写入packet

		// reset pos and set valid length

			mpp_packet_set_pos(packet, buf);			//设置有效数据的起始地址

			mpp_packet_set_length(packet, size);		//设置有效数据的长度



		do 

		{

			RK_S32 times = 5;

			if (!pkt_done) 

			{

	    			ret = mpi->decode_put_packet(ctx, packet);			//视频解码输入接口

	    			if (MPP_OK == ret) 

				{

	        		pkt_done = 1;

	    			}

			}

			do 

			{

		    		RK_S32 get_frm = 0;

		    		RK_U32 frm_eos = 0;

				try_again:

	    			ret = mpi->decode_get_frame(ctx, &frame);		//frame 解码出来的帧

	    			if (MPP_ERR_TIMEOUT == ret) 

				{

					if (times > 0) 

					{

				    		times--;

				    		msleep(2);

				    		goto try_again;

					}

	        			mpp_err("decode_get_frame failed too much time\n");

	    			}

				if (MPP_OK != ret) 

				{

	        			mpp_err("decode_get_frame failed ret %d\n", ret);

	        			break;

	    			}



				if (frame) 

				{

					if (mpp_frame_get_info_change(frame))

					{

				    		width = mpp_frame_get_width(frame);				//获取图像宽度

				    		height = mpp_frame_get_height(frame);			//获取图像高度

				    		hor_stride = mpp_frame_get_hor_stride(frame);	//获取buffer缓存宽度

				    		ver_stride = mpp_frame_get_ver_stride(frame);	//获取buffer缓存高度

				    		buf_size = mpp_frame_get_buf_size(frame);		//获取图像需要分配的缓存大小

				    		printf("buf_size = %d\n",buf_size);



				    		mpp_log("decode_get_frame get info changed found\n");

				    		mpp_log("decoder require buffer w:h [%d:%d] stride [%d:%d] buf_size %d",

			            		width, height, hor_stride, ver_stride, buf_size);

						if (NULL == frm_grp) 

						{

							/* If buffer group is not set create one and limit it */

							ret = mpp_buffer_group_get_internal(&frm_grp, MPP_BUFFER_TYPE_ION);		//解码器内存分配

							if (ret) 

							{

						    		mpp_err("get mpp buffer group failed ret %d\n", ret);

						    		break;

							}

									/* Set buffer to mpp decoder */

							ret = mpi->control(ctx, MPP_DEC_SET_EXT_BUF_GROUP, frm_grp);		//半内部分配模式

							if (ret) 

							{

						    		mpp_err("set buffer group failed ret %d\n", ret);

						    		break;

							}	

						}

						else

						{

									/* If old buffer group exist clear it */

							ret = mpp_buffer_group_clear(frm_grp);						//释放内存

							if (ret) 

							{

						    		mpp_err("clear buffer group failed ret %d\n", ret);

						    		break;

							}

						}

								/* Use limit config to limit buffer count to 24 with buf_size */

				    		ret = mpp_buffer_group_limit_config(frm_grp, buf_size, 24);		//限制最多24个buf

				    		if (ret) 

						{

							mpp_err("limit buffer group failed ret %d\n", ret);

							break;

				    		}

								/*

			     		* All buffer group config done. Set info change ready to let

			     		* decoder continue decoding

			     		*/

				    		ret = mpi->control(ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL);		//分配设置确认

				    		if (ret) 

						{

							mpp_err("info change ready failed ret %d\n", ret);

							break;

				    		}

					}

					else 

					{

						err_info = mpp_frame_get_errinfo(frame) | mpp_frame_get_discard(frame);	//检查获得的帧数据是否正常

			   		 	if (err_info) 

						{

	 		                       		mpp_log("decoder_get_frame get err info:%d discard:%d.\n",

			                		mpp_frame_get_errinfo(frame), mpp_frame_get_discard(frame));

				    		}

						mpp_log("decode_get_frame get frame 1111\n");

						if (!err_info)

						{

									//解码后数据的使用方法

							m_videoback((char*)frame,hor_stride,ver_stride);

							printf("m_videoback OK, Width = %d, Height = %d\n",hor_stride,ver_stride);

						}

					}

					frm_eos = mpp_frame_get_eos(frame);

					mpp_frame_deinit(&frame);

					frame = NULL;

					get_frm = 1;

				}

				if (pkt_done && !frm_eos) 

				{

		       			msleep(1);

					continue;

	       			}

		    		if (frm_eos) 

				{

				// mpp_log("found last frame\n");

					break;

		    		}

		    		if (get_frm)

					continue;

		    			break;

			}while(1);

			if (pkt_done)

			{

				pkt_done = 0;

        				break;

			}



    		/*

     		* why sleep here:

     		* mpi->decode_put_packet will failed when packet in internal queue is

     		* full,waiting the package is consumed .Usually hardware decode one

     		* frame which resolution is 1080p needs 2 ms,so here we sleep 3ms

     		* * is enough.

     		*/

    			msleep(1);

			

		}while(1);

		if(readpos<(MAX_NUMD-1))

				readpos++;

		else

				readpos=0;	

		usleep(20000);

	}

	

	

}

pthread_exit(&dwTheadId);

}

zhguo676 avatar Oct 26 '18 06:10 zhguo676

这是我的解码流程

zhguo676 avatar Oct 26 '18 06:10 zhguo676

void VideoDecoder::InitVideoDecoder(VideoDecoderBack pvideoback)

{

m_videoback=pvideoback;



ret         = MPP_OK;

mpi_cmd      = MPP_CMD_BASE;

need_split   = 1;

output_block = MPP_POLL_BLOCK;

// paramter for resource malloc

	width        = 1920;

	height       = 1080;

	type  = MPP_VIDEO_CodingAVC;

	packet_size  = PACKETSIZE;

buf = mpp_malloc(char, packet_size); //分配了256K char类型的buf, packet_size = 256K

if (NULL == buf) {

	mpp_err("mpi_dec_test malloc input stream buffer failed\n");

	Mpp_test_out();      

}

ret = mpp_packet_init(&packet, buf, packet_size);		//一个新的packet, 数据buf, 大小packet_size

if (ret) {

mpp_err("mpp_packet_init failed\n");

Mpp_test_out();

}

mpp_log("mpi_dec_test decoder test start w %d h %d type %d\n", width, height, type);



// decoder demo

ret = mpp_create(&ctx, &mpi);				//获取 MppCtx 实例以及 MppApi 结构体

if (MPP_OK != ret) {

    mpp_err("mpp_create failed\n");

    Mpp_test_out();

}	



// NOTE: decoder split mode need to be set before init

mpi_cmd = MPP_DEC_SET_PARSER_SPLIT_MODE;				//设置分帧模式

param = &need_split;

ret = mpi->control(ctx, mpi_cmd, param);

if (MPP_OK != ret) {

    mpp_err("mpi->control failed\n");

    Mpp_test_out();

}



ret = mpp_init(ctx, MPP_CTX_DEC, type);		//初始化 MppCtx 实例, 解码模式,H264格式

if (MPP_OK != ret) {

    mpp_err("mpp_init failed\n");

    Mpp_test_out();

}

}

zhguo676 avatar Oct 26 '18 07:10 zhguo676

这是初始化MPP,你看看有何问题

zhguo676 avatar Oct 26 '18 07:10 zhguo676

能否帮我解惑

zhguo676 avatar Oct 26 '18 07:10 zhguo676

有没有结果

zhguo676 avatar Oct 26 '18 08:10 zhguo676

先把码流给 ffmpeg 解码看一下能否正常。 mpp 只能处理没有封装的裸码流,你看下码流能不能用 elecard 打开,是否码流本身非标。

HermanChen avatar Oct 27 '18 02:10 HermanChen

和楼主遇到了完全一模一样的问题。解出来的frame是NULL。 同样的文件,我用ffmpeg软解码,都没问题。用mpp解不出来。不知道是什么原因 但有些文件,用mpp又可以正常

bingo9303 avatar Feb 08 '21 14:02 bingo9303

解码取数据的方式要看是阻塞还是非阻塞的。

HermanChen avatar Feb 09 '21 06:02 HermanChen

解码取数据的方式要看是阻塞还是非阻塞的。

HI Chen: 我用ffmpeg -i video.mp4 -codec copy -f h264 video.h264提取出H264的裸流以后,就可以播放了 可能是我ffmpeg解完封装后的喂给mpp的packet不是H264纯码流

我想再请教一下,mpp解码后的像素格式只能是YUV420sp吗?因为我用SDL2进行显示,SDL2对YUV数据的接口只支持YUV420p和YV12。我这里需要对YUV420sp数据进行一次转换,这个转换非常耗时,有没有可能,mpp直接解码出YUV420p的数据?

谢谢~

bingo9303 avatar Feb 09 '21 06:02 bingo9303

硬件只支持 420sp 的输出,420p 的格式对硬件的数据访问不太友好,可以试试用 rga 来做 sp -> p 的这个转换

HermanChen avatar Feb 17 '21 04:02 HermanChen

解码取数据的方式要看是阻塞还是非阻塞的。

请问怎么设置MMP解码方式。

jutyy avatar May 29 '21 08:05 jutyy

能否帮我解惑

楼主是否解决了问题,遇到趴您同样的问题。受教了。

jutyy avatar May 29 '21 08:05 jutyy