Просмотр исходного кода

修改libmfc库,支持最大8192x8192分辨率JPG解码,增加H264码流获取未16对齐前的实际分辨率

huangliang 2 лет назад
Родитель
Сommit
cfb940de1d

+ 25 - 0
buildroot-external/package/hx170dec/software/include/mfcapi.h

@@ -27,6 +27,9 @@ extern "C" {
 #define MAX_OUTFRAME_WIDTH	1920
 #define MAX_OUTFRAME_HEIGHT	1088
 
+#define MAX_JPEG_OUTFRAME_WIDTH		8192
+#define MAX_JPEG_OUTFRAME_HEIGHT	8192
+
 typedef struct
 {
 	u32 yBusAddress;
@@ -72,6 +75,26 @@ typedef struct
 	DWLLinearMem_t ppOutBuffer;
 }MFCHandle;
 
+
+typedef enum{
+	MFCFORMAT_NONE = -1,
+	MFCFORMAT_YCBCR400 = 0,
+	MFCFORMAT_YCBCR420_SEMIPLANAR,
+	MFCFORMAT_YCBCR422_SEMIPLANAR,
+	MFCFORMAT_YCBCR440,
+	MFCFORMAT_YCBCR411_SEMIPLANAR,
+	MFCFORMAT_YCBCR444_SEMIPLANAR,
+}MFCFormat;
+
+typedef struct
+{
+	i32 codedWidth;
+	i32 codedHeight;
+	i32 frameWidth;
+	i32 frameHeight;
+	MFCFormat format;
+}MFCStreamInfo;
+
 MFCHandle *mfc_init(int streamType);
 
 int mfc_decode(MFCHandle *handle, DWLLinearMem_t *inBuffer, OutFrameBuffer *outBuffer);
@@ -82,6 +105,8 @@ void mfc_uninit(MFCHandle *handle);
 
 int mfc_pp_init(MFCHandle *handle, int outWidth, int outHeight, int outFormat);
 
+int mfc_get_stream_info(MFCHandle *handle, DWLLinearMem_t *inBuffer, MFCStreamInfo *info);
+
 #ifdef __cplusplus
 }
 #endif

+ 2 - 2
buildroot-external/package/hx170dec/software/src/jpegdecapi.c

@@ -1800,9 +1800,9 @@ JpegDecRet JpegDecDecode(JpegDecInst decInst, JpegDecInput * pDecIn,
             return (JPEGDEC_SLICE_MODE_UNSUPPORTED);
         }
 
-        /* check if frame size over 16M */
+        /* check if frame size over maxSupportedPixelAmount */
         if((!pDecIn->sliceMbSet) &&
-           ((JPG_FRM.hwX * JPG_FRM.hwY) > JPEGDEC_MAX_PIXEL_AMOUNT))
+           ((JPG_FRM.hwX * JPG_FRM.hwY) > PTR_JPGC->maxSupportedPixelAmount))
         {
             JPEGDEC_API_TRC
                 ("JpegDecDecode# ERROR: Resolution > 16M ==> use slice mode!");

+ 149 - 30
buildroot-external/package/hx170dec/software/src/mfcapi.c

@@ -33,17 +33,21 @@ u32 g_JpegYBusAddress = 0;
 u32 g_JpegCbCrBusAddress = 0;
 
 DWLLinearMem_t g_JpegYMemInfo[2] = {0};
+u32 g_JpegMemWidth = 0;
+u32 g_JpegMemHeight = 0;
 u32 g_JpegMemIndex = 0;
 
 static codecSegmentInfo g_SliceInfo[128];
 
+static void JpegReleaseBuffer(void);
+
 static int get_pp_dec_type(int streamType);
 
 static int pp_alloc_buffer(int fdmemalloc, u32 size, DWLLinearMem_t * info);
 
 static void pp_free_buffer(int fdmemalloc, DWLLinearMem_t * info);
 
-static int pp_set_config(MFCHandle *handle, int in_width, int int_height, int in_format, int out_addr);
+static int pp_set_config(MFCHandle *handle, int in_width, int in_height, int in_format, int out_addr);
 
 static int pp_reset_outimg_addr(MFCHandle *handle, u32 addr);
 
@@ -77,8 +81,8 @@ int MFCH264Decode(MFCHandle *handle, DWLLinearMem_t *inBuffer, OutFrameBuffer *o
 		case H264DEC_HDRS_RDY:
 			/* read stream info */
 			infoRet = H264DecGetInfo(handle->decInst, &decInfo);
-			outBuffer->codedWidth = decInfo.picWidth;
-			outBuffer->codedHeight = decInfo.picHeight;
+			outBuffer->codedWidth = decInfo.cropParams.cropOutWidth;
+			outBuffer->codedHeight = decInfo.cropParams.cropOutHeight;
 			if (handle->ppInst) {
 				pp_set_config(handle, decInfo.picWidth, decInfo.picHeight, PP_PIX_FMT_YCBCR_4_2_0_SEMIPLANAR,
 					PP_OUTBUFFER_PHYADDR(handle->ppOutBufferIndex));
@@ -1434,18 +1438,6 @@ int MFCJpegDecode(MFCHandle *handle, DWLLinearMem_t *inBuffer, OutFrameBuffer *o
 
 	g_JpegYBusAddress = 0;
 
-	for (i = 0; i < 2; i++) {
-		if(g_JpegYMemInfo[i].busAddress == 0)
-		{
-			if(DWLMallocLinear(((JpegDecContainer*)handle->decInst)->dwl, MAX_OUTFRAME_WIDTH*MAX_OUTFRAME_HEIGHT*2,
-				 &g_JpegYMemInfo[i]) == DWL_ERROR)
-			{
-				printf("Jpeg DWLMallocLinear y failure.\n");
-				goto end;
-			}
-		}
-	}
-
 	/* Get image information of the JFIF */
     infoRet = JpegDecGetImageInfo(handle->decInst,
                                    &DecIn,
@@ -1456,13 +1448,11 @@ int MFCJpegDecode(MFCHandle *handle, DWLLinearMem_t *inBuffer, OutFrameBuffer *o
 		goto end;
 	}
 
-	DecIn.pictureBufferY.busAddress = g_JpegYMemInfo[g_JpegMemIndex].busAddress;
-	DecIn.pictureBufferY.pVirtualAddress = g_JpegYMemInfo[g_JpegMemIndex].virtualAddress;
-	DecIn.pictureBufferCbCr.busAddress = g_JpegYMemInfo[g_JpegMemIndex].busAddress + DecImgInf.outputWidth * DecImgInf.outputHeight;
-	DecIn.pictureBufferCbCr.pVirtualAddress = (u32*)((u32)g_JpegYMemInfo[g_JpegMemIndex].virtualAddress +
-			DecImgInf.outputWidth * DecImgInf.outputHeight);
-	DecIn.pictureBufferCr.busAddress = 0;
-	DecIn.pictureBufferCr.pVirtualAddress = 0;
+	if (DecImgInf.outputWidth > MAX_JPEG_OUTFRAME_WIDTH || DecImgInf.outputHeight > MAX_JPEG_OUTFRAME_HEIGHT)
+	{
+		printf("%dx%d image is too large to decode", DecImgInf.outputWidth, DecImgInf.outputHeight);
+		goto end;
+	}
 
 	if (handle->ppInst) {
 		if (DecImgInf.outputFormat == JPEGDEC_YCbCr400)
@@ -1479,6 +1469,34 @@ int MFCJpegDecode(MFCHandle *handle, DWLLinearMem_t *inBuffer, OutFrameBuffer *o
 			format = PP_PIX_FMT_YCBCR_4_2_2_SEMIPLANAR;
 		pp_set_config(handle, DecImgInf.displayWidth, DecImgInf.displayHeight, format,
 			PP_OUTBUFFER_PHYADDR(handle->ppOutBufferIndex));
+		DecIn.pictureBufferY.busAddress = 0;
+		DecIn.pictureBufferY.pVirtualAddress = NULL;
+		DecIn.pictureBufferCbCr.busAddress = 0;
+		DecIn.pictureBufferCbCr.pVirtualAddress = NULL;
+		DecIn.pictureBufferCr.busAddress = 0;
+		DecIn.pictureBufferCr.pVirtualAddress = 0;
+	} else {
+		if (g_JpegMemWidth != DecImgInf.outputWidth || g_JpegMemHeight != DecImgInf.outputHeight) {
+			JpegReleaseBuffer();
+
+			for (i = 0; i < 2; i++) {
+				if(DWLMallocLinear(((JpegDecContainer*)handle->decInst)->dwl,
+					DecImgInf.outputWidth*DecImgInf.outputHeight*3, &g_JpegYMemInfo[i]) == DWL_ERROR)
+				{
+					printf("Jpeg DWLMallocLinear y failure.\n");
+					goto end;
+				}
+			}
+			g_JpegMemWidth = DecImgInf.outputWidth;
+			g_JpegMemHeight = DecImgInf.outputHeight;
+		}
+		DecIn.pictureBufferY.busAddress = g_JpegYMemInfo[g_JpegMemIndex].busAddress;
+		DecIn.pictureBufferY.pVirtualAddress = g_JpegYMemInfo[g_JpegMemIndex].virtualAddress;
+		DecIn.pictureBufferCbCr.busAddress = g_JpegYMemInfo[g_JpegMemIndex].busAddress + DecImgInf.outputWidth * DecImgInf.outputHeight;
+		DecIn.pictureBufferCbCr.pVirtualAddress = (u32*)((u32)g_JpegYMemInfo[g_JpegMemIndex].virtualAddress +
+				DecImgInf.outputWidth * DecImgInf.outputHeight);
+		DecIn.pictureBufferCr.busAddress = 0;
+		DecIn.pictureBufferCr.pVirtualAddress = 0;
 	}
 
 	g_JpegMemIndex = !g_JpegMemIndex;
@@ -1536,11 +1554,14 @@ int MFCJpegDecodeEof(MFCHandle *handle, OutFrameBuffer *outBuffer)
 	return 0;
 }
 
-void JpegReleaseBuffer(void)
+static void JpegReleaseBuffer(void)
 {
     int fd_memalloc;
     int i;
 
+	if (!g_JpegYMemInfo[0].busAddress && !g_JpegYMemInfo[1].busAddress)
+		return;
+
 	fd_memalloc = open(MEMALLOC_MODULE_PATH, O_RDWR | O_SYNC);
 
     if(fd_memalloc == -1)
@@ -1553,7 +1574,7 @@ void JpegReleaseBuffer(void)
 		if(g_JpegYMemInfo[i].busAddress != 0)
 			ioctl(fd_memalloc, MEMALLOC_IOCSFREEBUFFER, &g_JpegYMemInfo[i].busAddress);
 
-		if(g_JpegYMemInfo[i].virtualAddress != MAP_FAILED)
+		if(g_JpegYMemInfo[i].virtualAddress != MAP_FAILED && g_JpegYMemInfo[i].virtualAddress != 0)
 			munmap(g_JpegYMemInfo[i].virtualAddress, g_JpegYMemInfo[i].size);
 
 		memset(&g_JpegYMemInfo[i], 0, sizeof(g_JpegYMemInfo[i]));
@@ -1824,6 +1845,9 @@ void mfc_uninit(MFCHandle *handle)
 
 	if (handle->ppInst) {
 		PPRelease(handle->ppInst);
+	}
+
+	if (handle->ppMemalloc > 0) {
 		pp_free_buffer(handle->ppMemalloc, &handle->ppOutBuffer);
 		close(handle->ppMemalloc);
 	}
@@ -1960,6 +1984,8 @@ static int pp_alloc_buffer(int fdmemalloc, u32 size, DWLLinearMem_t * info)
         return -1;
 	}
 
+	close(fd_mem);
+
     return 0;
 }
 
@@ -1973,7 +1999,7 @@ static void pp_free_buffer(int fdmemalloc, DWLLinearMem_t * info)
         munmap(info->virtualAddress, info->size);
 }
 
-static int pp_set_config(MFCHandle *handle, int in_width, int int_height, int in_format, int out_addr)
+static int pp_set_config(MFCHandle *handle, int in_width, int in_height, int in_format, int out_addr)
 {
 	PPResult ppRet;
 	PPConfig pPpConf;
@@ -1990,15 +2016,15 @@ static int pp_set_config(MFCHandle *handle, int in_width, int int_height, int in
 	/* Set input width */
 	pPpConf.ppInImg.width = (in_width + 15) & ~15;
 	/* Set input height */
-	pPpConf.ppInImg.height = (int_height + 15) & ~15;
+	pPpConf.ppInImg.height = (in_height + 15) & ~15;
 	/* set input Crop */
-	if (in_width & 15 || int_height & 15) {
+	if (in_width & 15 || in_height & 15) {
 
 		pPpConf.ppInCrop.enable = 1;
 		pPpConf.ppInCrop.originX = 0;
 		pPpConf.ppInCrop.originY = 0;
-		pPpConf.ppInCrop.width = in_width;
-		pPpConf.ppInCrop.height = int_height;
+		pPpConf.ppInCrop.width = in_width & ~7;
+		pPpConf.ppInCrop.height = in_height & ~7;
 	}
 	/* Set video range to 0 */
 	pPpConf.ppInImg.videoRange = 0;
@@ -2106,7 +2132,7 @@ int mfc_pp_init(MFCHandle *handle, int outWidth, int outHeight, int outFormat)
 		PPRelease(pp);
 		return -1;
 	}
-	printf("DWLMallocLinear 0x%x, 0x%x.\n", handle->ppOutBuffer.busAddress, handle->ppOutBuffer.virtualAddress);
+	//printf("DWLMallocLinear 0x%x, 0x%x.\n", handle->ppOutBuffer.busAddress, handle->ppOutBuffer.virtualAddress);
 
 	/* if (get_pp_dec_type(handle->streamType) != PP_PIPELINED_DEC_TYPE_H264) {
 		PPOutputBuffers ppOutBuf;
@@ -2127,3 +2153,96 @@ int mfc_pp_init(MFCHandle *handle, int outWidth, int outHeight, int outFormat)
 
 	return 0;
 }
+
+int MFCJpegGetInfo(MFCHandle *handle, DWLLinearMem_t *inBuffer, MFCStreamInfo *info)
+{
+	JpegDecInst  decoder;
+	JpegDecRet  infoRet;
+	JpegDecInput DecIn;
+	JpegDecImageInfo DecImgInf;
+	int ret = 0;
+
+	if (!handle || !inBuffer || !info) {
+		printf("Invalid parameter!\n");
+		return -1;
+	}
+
+	infoRet = JpegDecInit(&decoder);
+	if(infoRet !=JPEGDEC_OK) {
+		printf("JpegDecInit failure %d.\n", infoRet);
+		return -1;
+	}
+	handle->decInst = (void*)decoder;
+
+	DecIn.decImageType = JPEGDEC_IMAGE;
+	DecIn.sliceMbSet = 0;
+	DecIn.bufferSize = 0;
+	DecIn.streamLength = inBuffer->size;
+	DecIn.streamBuffer.busAddress= inBuffer->busAddress;
+	DecIn.streamBuffer.pVirtualAddress = inBuffer->virtualAddress;
+
+	/* Get image information of the JFIF */
+    infoRet = JpegDecGetImageInfo(handle->decInst,
+                                   &DecIn,
+                                   &DecImgInf);
+	if(infoRet !=JPEGDEC_OK)
+	{
+		printf("JpegDecGetImageInfo failure.\n");
+		info->codedWidth = 0;
+		info->codedHeight = 0;
+		info->frameWidth = 0;
+		info->frameHeight = 0;
+		info->format = MFCFORMAT_NONE;
+		ret = -1;
+		goto end;
+	}
+
+	info->codedWidth = DecImgInf.displayWidth;
+	info->codedHeight = DecImgInf.displayHeight;
+	info->frameWidth = DecImgInf.outputWidth;
+	info->frameHeight = DecImgInf.outputHeight;
+	if (DecImgInf.outputFormat == JPEGDEC_YCbCr400)
+		info->format = MFCFORMAT_YCBCR400;
+	else if (DecImgInf.outputFormat == JPEGDEC_YCbCr440)
+		info->format = MFCFORMAT_YCBCR440;
+	else if (DecImgInf.outputFormat == JPEGDEC_YCbCr411_SEMIPLANAR)
+		info->format = MFCFORMAT_YCBCR411_SEMIPLANAR;
+	else if (DecImgInf.outputFormat == JPEGDEC_YCbCr444_SEMIPLANAR)
+		info->format = MFCFORMAT_YCBCR444_SEMIPLANAR;
+	else if (DecImgInf.outputFormat == JPEGDEC_YCbCr420_SEMIPLANAR)
+		info->format = MFCFORMAT_YCBCR420_SEMIPLANAR;
+	else
+		info->format = MFCFORMAT_YCBCR422_SEMIPLANAR;
+
+end:
+	JpegDecRelease((JpegDecInst)handle->decInst);
+
+	return ret;
+}
+
+int mfc_get_stream_info(MFCHandle *handle, DWLLinearMem_t *inBuffer, MFCStreamInfo *info)
+{
+	if (handle == NULL) {
+		printf("Invalid handle.\n");
+		return -1;
+	}
+
+	switch(handle->streamType) {
+	case RAW_STRM_TYPE_JPEG:
+		return MFCJpegGetInfo(handle, inBuffer, info);
+	case RAW_STRM_TYPE_WMV3:
+	case RAW_STRM_TYPE_H264:
+	case RAW_STRM_TYPE_H264_NOREORDER:
+	case RAW_STRM_TYPE_MP2:
+	case RAW_STRM_TYPE_MP4:
+	case RAW_STRM_TYPE_SOR:
+	case RAW_STRM_TYPE_MP4_CUSTOM:
+	case RAW_STRM_TYPE_REAL:
+	case RAW_STRM_TYPE_VC1:
+	case RAW_STRM_TYPE_VP8:
+	case RAW_STRM_TYPE_VP6:
+	default:
+		printf("Not supported yet.\n");
+		return -1;
+	}
+}