h264轉成 JPEG 海思

該代碼只是編解碼部分的代碼。

前臺代碼 需要 綁定 VDEC->VPSS->VENC     參考 sample_comm.h接口 及 sample_comm_vdec.c

正常的流程就是 sendstream (h264) 到VDEC 解碼後給VPSS然後VPSS將數據 給 VENC 進行編碼, 最後從 VENC的通道 取的數據流就是對應的編碼成JEPG的數據了,保存即可。 

 

 


HISI_VENC_SaveSnap(.....)
{
for (i = 0; i < pstStream->u32PackCount; i++)
 {
  pstData = &pstStream->pstPack[i];
  if (push_data->pic_len + pstData->u32Len - pstData->u32Offset < sizeof(push_data->pic_buf)) {
   memcpy(push_data->pic_buf + push_data->pic_len, pstData->pu8Addr + pstData->u32Offset, pstData->u32Len - pstData->u32Offset);
   push_data->pic_len += pstData->u32Len - pstData->u32Offset;
  }
 }
}

HI_VOID * HISI_VDEC_SendStreamThread(HI_VOID *pArgs)
{
	char *stream_id = (char*)pArgs;
	stream_task_t *task_item = NULL;
	GList *list_item = NULL;
	HI_S32 s32ChnId = 0;
	HI_S32 s32MilliSec = 10;
	HI_S32 s32IntervalTime = 500000;
	HI_S32 retryMaxCount = 5;
	HI_S32 retryCount = 0;
	HI_BOOL bEndOfStream = HI_FALSE;
	HI_U8 *pu8Buf = NULL;
	HI_S32 s32ReadLen = 0;
	VDEC_STREAM_S stStream;
	HI_S32 s32Ret = HI_SUCCESS;

	logger("[INFO] hisi vdec send stream thread running");
	while (g_run_flag) 
	{
		g_rw_lock_reader_lock(&stream_task_list_rwlock);
		list_item = (GList*)g_datalist_get_data(&stream_task_hashlist, stream_id);
		if (list_item == NULL) {
			g_rw_lock_reader_unlock(&stream_task_list_rwlock);
			break;
		}
		task_item = (stream_task_t *)list_item->data;
		if (task_item->convert_channel < 0) {
			g_rw_lock_reader_unlock(&stream_task_list_rwlock);
			break;
		}
		if (task_item->status.status != STREAM_CONNECT) {
			g_rw_lock_reader_unlock(&stream_task_list_rwlock);
			usleep(WAIT_TIME * 1000);
			continue;
		}
		//非持續拉流,無需轉換圖片
		if (task_item->status.total_success > 0 && !task_item->info.continued) {
			task_item->status.status = STREAM_STOP;
			g_rw_lock_reader_unlock(&stream_task_list_rwlock);
			usleep(WAIT_TIME * 1000);
			continue;
		}
		if (retryCount >= retryMaxCount) {
			//解碼異常,關閉流
			task_item->status.status = STREAM_CLOSE;
			g_rw_lock_reader_unlock(&stream_task_list_rwlock);
			usleep(WAIT_TIME * 1000);
			continue;
		}
		s32ChnId = (HI_S32)task_item->convert_channel;

		g_mutex_lock(&task_item->frame_queue_mutex);
		if (g_queue_is_empty(task_item->frame_queue)) {  //隊列空則等待
			g_mutex_unlock(&task_item->frame_queue_mutex);
			usleep(WAIT_TIME * 1000);
			continue;
		}
		//從隊列取幀數據
		frame_data_t *frame = (frame_data_t*)g_queue_pop_head(task_item->frame_queue);
		g_mutex_unlock(&task_item->frame_queue_mutex);
		if (NULL == frame) {
			g_rw_lock_reader_unlock(&stream_task_list_rwlock);
			continue;
		}
		g_rw_lock_reader_unlock(&stream_task_list_rwlock);

		retryCount = 0;
		pu8Buf = (HI_U8 *)frame->buf;
		s32ReadLen = (HI_S32)frame->len;
		memset(&stStream, 0, sizeof(VDEC_STREAM_S));
		if (conf_info->test)
			logger("[DEBUG] vdec get frame, stream_id: %s, channel: %d, len: %d", stream_id, s32ChnId, s32ReadLen);
		//解碼264視頻
		stStream.u64PTS = 0;
		stStream.pu8Addr = pu8Buf;
		stStream.u32Len = s32ReadLen;
		stStream.bEndOfFrame = HI_TRUE;
		stStream.bEndOfStream = bEndOfStream;
		stStream.bDisplay = 1; //必須設置爲1,否則不能生成圖片
SendAgain:
		s32Ret = HI_MPI_VDEC_SendStream(s32ChnId, &stStream, s32MilliSec);
		if (HI_SUCCESS != s32Ret)
		{
			HISI_PRT("[ERROR] VDEC SendStream failed, chn %d, ret: %x\n", s32ChnId, s32Ret);
			usleep(s32IntervalTime);
			if (retryCount < retryMaxCount)
			{
				retryCount++;
				goto SendAgain;
			}
		}
	
		free(frame);
		usleep(WAIT_TIME / 2 * 1000);
	}

	logger("[INFO] hisi vdec send stream thread exit, id: %s \n", stream_id);
	g_free(stream_id);
	return (HI_VOID *)HI_SUCCESS;
}



HI_VOID* HISI_VENC_SnapPictureThread(HI_VOID* pArgs)
{
	char *stream_id = (char*)pArgs;
	GList *list_item = NULL;
	stream_task_t *task_item = NULL;
	VENC_CHN VencChn = 0;
	HI_U32 SnapCnt = 1; //一次生成1個圖片
	HI_S32 s32VencFd = 0;
	VENC_CHN_STATUS_S stStat;
	VENC_STREAM_S stStream;
	HI_S32 s32Ret = HI_SUCCESS;
	HI_U32 i = 0;

	logger("[INFO] hisi venc snap picture thread running");
	while (g_run_flag)
	{
		g_rw_lock_reader_lock(&stream_task_list_rwlock);
		list_item = (GList*)g_datalist_get_data(&stream_task_hashlist, stream_id);
		if (list_item == NULL) {
			g_rw_lock_reader_unlock(&stream_task_list_rwlock);
			break;
		}
		task_item = (stream_task_t *)list_item->data;
		if (task_item->convert_channel < 0) {
			g_rw_lock_reader_unlock(&stream_task_list_rwlock);
			break;
		}
		if (task_item->status.status != STREAM_CONNECT) {
			g_rw_lock_reader_unlock(&stream_task_list_rwlock);
			usleep(WAIT_TIME * 1000);
			continue;
		}
		VencChn = (VENC_CHN)task_item->convert_channel;
		//非持續拉流,無需轉換圖片
		if (task_item->status.total_success > 0 && !task_item->info.continued) {
			task_item->status.status = STREAM_STOP;
			g_rw_lock_reader_unlock(&stream_task_list_rwlock);
			//停止接收數據
			HI_MPI_VENC_StopRecvFrame(VencChn);
			usleep(WAIT_TIME * 1000);
			continue;
		}
		if (conf_info->test)
			logger("[DEBUG] venc snap picture, stream_id: %s, channel: %d", stream_id, VencChn);
		//開始獲取編碼數據
		s32VencFd = HI_MPI_VENC_GetFd(VencChn);
		if (s32VencFd < 0)
		{
			HISI_PRT("HI_MPI_VENC_GetFd faild with%#x!\n", s32VencFd);
			g_rw_lock_reader_unlock(&stream_task_list_rwlock);
			usleep(WAIT_TIME * 1000);
			continue;
		}
		for (i = 0; i < SnapCnt; i++)
		{
			memset(&stStat, 0, sizeof(stStat));
			s32Ret = HI_MPI_VENC_QueryStatus(VencChn, &stStat);
			if (s32Ret != HI_SUCCESS)
			{
				HISI_PRT("HI_MPI_VENC_QueryStatus failed with %#x!\n", s32Ret);
				usleep(WAIT_TIME * 1000);
				continue;
			}
			if (0 == stStat.u32CurPacks)
			{
				HISI_PRT("[WARN] venc snap current frame is NULL! stream_id: %s, channel: %d, fd: %d", stream_id, VencChn, s32VencFd);
				usleep(WAIT_TIME*3 * 1000);
				continue;
			}
			memset(&stStream, 0, sizeof(stStream));
			stStream.pstPack = (VENC_PACK_S*)malloc(sizeof(VENC_PACK_S) * stStat.u32CurPacks);
			if (NULL == stStream.pstPack)
			{
				HISI_PRT("malloc memory failed!\n");
				usleep(WAIT_TIME * 1000);
				continue;
			}
			stStream.u32PackCount = stStat.u32CurPacks;
			s32Ret = HI_MPI_VENC_GetStream(VencChn, &stStream, -1);
			if (HI_SUCCESS != s32Ret)
			{
				HISI_PRT("HI_MPI_VENC_GetStream failed with %#x!\n", s32Ret);
				free(stStream.pstPack);
				stStream.pstPack = NULL;
				usleep(WAIT_TIME * 1000);
				continue;
			}
			//根據間隔,生成圖片
			long long cur_time = get_mtime();
			if (cur_time - task_item->status.last_run >= (long long)task_item->info.frequency) {
				task_item->status.last_run = cur_time;
				task_item->status.last_success = time(NULL);
				task_item->status.total_success++;
				s32Ret = HISI_VENC_SaveSnap(task_item, &stStream);
				if (HI_SUCCESS != s32Ret)
				{
					HISI_PRT("HISI_VENC_SaveSnap failed with %#x!\n", s32Ret);
				}
			}
			s32Ret = HI_MPI_VENC_ReleaseStream(VencChn, &stStream);
			if (s32Ret)
			{
				HISI_PRT("HI_MPI_VENC_ReleaseStream failed with %#x!\n", s32Ret);
				free(stStream.pstPack);
				stStream.pstPack = NULL;
				usleep(WAIT_TIME * 1000);
				continue;
			}
			free(stStream.pstPack);
			stStream.pstPack = NULL;
		}

		g_rw_lock_reader_unlock(&stream_task_list_rwlock);
		usleep(WAIT_TIME / 2 * 1000);
	}

	logger("[INFO] hisi venc snap picture thread exit, id: %s \n", stream_id);
	g_free(stream_id);
	return (HI_VOID *)HI_SUCCESS;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章