首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >基于S3C6410和ffmpeg的视频加速示例

基于S3C6410和ffmpeg的视频加速示例

作者头像
雪影
发布2018-08-02 11:59:41
5420
发布2018-08-02 11:59:41
举报
/*
* Video Acceleration (shared data between FFmpeg and the video player)
* HW decode acceleration for MPEG-4, H.264, H263 and VC-1
* Using Samsung Multi-Format Codec API
*
* Copyright(C) 2012  TuYuanDong
* author:	tuyaundong
* email:	tuyuandong@gmail.com
* Date:		2012-02-27
*
*/
#include "s3c_va.h"
#include "./libavcodec/avcodec.h"
#include "./libavcodec/mpeg4video.h"
#include "./libavcodec/h264.h"
#include "SsbSipH264Decode.h"
#include "SsbSipLogMsg.h"
#include "vaapi.h"

#define NAL_UNIT_TYPE_TYPE(n)    ((0x001F) & (n))
static const uint8_t delimiter_h264[4]  = {0x00, 0x00, 0x00, 0x01};

/** Initialize and start decoding a frame with S3CMFC API. */
static int start_frame(AVCodecContext          *avctx,
					   av_unused const uint8_t *buffer,
					   av_unused uint32_t       size)
{
	int is_avc = 0;
	SSBSIP_H264_STREAM_INFO stream_info;

	//如果decode_slice函数解码失败,则需停止硬解,转向软解
	if(bDecSuc == -1)
	{
		avctx->hwaccel = NULL; 
		LOG_MSG(LOG_TRACE,__FUNCTION__,"Hardware decode video failed,being used soft decoder\r\n");
		return -1;
	}
	
	if(ResetVideoAccelerator(avctx,SsbSipH264DecodeDeInit) < 0)
		goto fail;

	if(avctx->extradata_size > 0)
	{
		uint8_t * p = avctx->extradata;
		if(p[0] == 0x01)
			is_avc = 1;
	}

	if(bFistFrame && size >0)  //初始化硬解加速器
	{
		//	1. Create new instance
		handle = SsbSipH264DecodeInit();
		if (handle == NULL) {
			LOG_MSG(LOG_ERROR, __FUNCTION__, "Decoder Init Failed\n");
			goto fail;
		}
	
		//	2. Obtaining the Input Buffer
		pStrmBuf = SsbSipH264DecodeGetInBuf(handle,BUFFER_SIZE);
		if (pStrmBuf == NULL) {
			LOG_MSG(LOG_ERROR, __FUNCTION__, "SsbSipH264DecodeGetInBuf Failed.\n");			
			goto fail;
		}
	}
		
	BufSize = 0;
	if(is_avc)
	{
		uint8_t* buf = buffer;
		int tot_size = 0;
		if(bFistFrame && avctx->extradata_size > 0)
		{
			uint8_t* p  = avctx->extradata;	
			int i, cnt, nalsize;
			
			// Decode sps from avcC
		        cnt = *(p+5) & 0x1f; // Number of sps
		        p += 6;
		        for (i = 0; i < cnt; i++) {
		            	nalsize = AV_RB16(p);
		            	if((nalsize+2) > avctx->extradata_size - (p-avctx->extradata))
		               	return -1;
		            	//copy h264 data
		           	memcpy(pStrmBuf+BufSize,delimiter_h264,sizeof(delimiter_h264));
				BufSize += sizeof(delimiter_h264);
				p += 2;
				memcpy(pStrmBuf+BufSize,p,nalsize);			            	
			  	BufSize += nalsize;

				p += nalsize;				
		        }
			
		        // Decode pps from avcC
		        cnt = *(p++); // Number of pps
		        for (i = 0; i < cnt; i++) {
		            nalsize = AV_RB16(p);
		            if((nalsize+2) > avctx->extradata_size  - (p-avctx->extradata))
		                return -1;
				//copy h264 data
		           	memcpy(pStrmBuf+BufSize,delimiter_h264,sizeof(delimiter_h264));
				BufSize += sizeof(delimiter_h264);	
				p += 2;
				memcpy(pStrmBuf+BufSize,p,nalsize);			              
				BufSize += nalsize;

				p += nalsize;
		        }
			//fwrite(avctx->extradata, 1, avctx->extradata_size, fp1);
		}
		unsigned char      nal_type = 255;
		int num_iframe = 0;
		do
		{
			int slice_size = buf[0]<<24 | buf[1]<<16 | buf[2]<<8 | buf[3];			
			nal_type = NAL_UNIT_TYPE_TYPE(buf[4]);
			//printf("slice size=%d nal_type=%d\n",slice_size,nal_type);	
			if(nal_type == 5)
				num_iframe ++;

			memcpy(pStrmBuf+BufSize,delimiter_h264,sizeof(delimiter_h264));
			BufSize += sizeof(delimiter_h264);				
			memcpy(pStrmBuf+BufSize,buf+4,slice_size);
			BufSize += slice_size;
			
			buf += slice_size+4;
			tot_size += slice_size+4;	

		}while(tot_size < size);

		if(num_iframe > 1)
			goto fail;
	}
	else
	{
		if (bFistFrame && avctx->extradata_size != 0)
		{
			memcpy(pStrmBuf+BufSize,avctx->extradata,avctx->extradata_size);
			BufSize += avctx->extradata_size;
		}
		
		memcpy(pStrmBuf+BufSize,buffer,size);
		BufSize += size;
	}

	if(bFistFrame)
	{
		//	3. Configuring the instance with the config stream SsbSipXXXDecodeExe
		int ret =SsbSipH264DecodeExe(handle, BufSize);
		if (ret != SSBSIP_H264_DEC_RET_OK) {
			LOG_MSG(LOG_ERROR, __FUNCTION__, "Decoder SsbSipH264DecodeExe Failed err=%d.\n",ret);
			goto fail;
		}	
	
		///   4. Get stream information 
		SsbSipH264DecodeGetConfig(handle, H264_DEC_GETCONF_STREAMINFO, &(stream_info));
		LOG_MSG(LOG_TRACE, __FUNCTION__,"STREAMINFO width=%d   height=%d\r\n",stream_info.width, stream_info.height);
		bFistFrame = 0;
	}
		
	BufSize = size;
	return 0;
	
fail:
	LOG_MSG(LOG_TRACE,__FUNCTION__,"Hardware decode video failed,being used soft decoder\r\n");
	if(handle)
	{
		SsbSipH264DecodeDeInit(handle);
		handle = NULL;
	}
	avctx->hwaccel = NULL;  //用于跳转到软解方案中
	return -1;
}

/** End a hardware decoding based frame. */
static int end_frame(AVCodecContext *avctx)
{
	struct H264Context *h = avctx->priv_data;
    	struct MpegEncContext *s = &h->s;
		
	Picture* pic = s->current_picture_ptr;		
	uint8_t* pYUVBuf = NULL;
	long size;
	
	if(bDecSuc > 0 && handle)
	{
		pYUVBuf = SsbSipH264DecodeGetOutBuf(handle,&size);
		if(pYUVBuf)
		{
			avpicture_fill(pic,pYUVBuf,pic->format,pic->width,pic->height);
			//pYUVBuf 中的YUV420在内存中不是连续的
			pic->data[1] = (int8_t*)(pYUVBuf+4*size/6);
			pic->data[2] = (int8_t*)(pYUVBuf+5*size/6);
		}
//				LOG_MSG(LOG_ERROR, __FUNCTION__,"width=%d height=%d size[%d] data[%p][%p][%p] data2[%p][%p][%p]\r\n",
//							pic->width,pic->height,size,
//							pic->data[0],pic->data[1],pic->data[2],pYUVBuf,pYUVBuf+4*size/6,pYUVBuf+5*size/6);
	}
	return 0;
}

/** Decode the given h264 slice with S3CMFC API. */
static int decode_slice(AVCodecContext *avctx,
						const uint8_t  *buffer,
						uint32_t        size)
{
	int ret = 0;

	bDecSuc = 0; 
	ret =SsbSipH264DecodeExe(handle, BufSize);
	if (ret != SSBSIP_H264_DEC_RET_OK) {
		bDecSuc = -1;
		return -1;
	}
	else	
		bDecSuc = 1;
	
	return 0;
}


AVHWAccel ff_h264_s3c_hwaccel = {
	"h264_s3c",
	AVMEDIA_TYPE_VIDEO,
	CODEC_ID_H264,
	PIX_FMT_YUV420P,
	0,
	NULL,
	start_frame,	
	decode_slice,
	end_frame,
	0,
};
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2012年11月02日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档