📄 mjpeg_decode.c
字号:
{
MJPEG_ProcessErrorCode(lResult, "MJPEG_AVI_OpenStreamRead");
return CODEC_FILE_ERROR;
}
// go to start of the frame
lResult = MJPEG_AVI_RewindToFirstFrame(lStreamHandle, &lStreamBufferLength);
if(lResult == MJPEG_AVI_RETURN_NOMORESAMPLES)
fprintf(fperr, "Not enough samples to read the first JPEG image from stream\n");
else if(lResult != MJPEG_AVI_RETURN_OK)
{
MJPEG_ProcessErrorCode(lResult, "MJPEG_AVI_RewindToFirstFrame");
return CODEC_FILE_ERROR;
}
// Dynamically allocate memory to read a MJPEG frame
StreamBuffer_Obj = JPEG_MemAlloc_NEW(lStreamBufferLength, 1, MEM_TYPE_DATA);
if(StreamBuffer_Obj == NULL)
{
fprintf(fperr,"Memory allocation for StreamBuffer failed.\n");
fprintf(fperr, "Could not allocate %d bytes for input buffer\n", lStreamBufferLength); return CODEC_FILE_ERROR;
}
// get the address of memory location where the MJPEG frame will be read to
lStreamBuffer = (uint8*)JPEG_MemAlloc_ADDRESS(StreamBuffer_Obj);
// check if there is any MJPEG frame available for decoding
lResult = MJPEG_AVI_ReadNextFrame(lStreamHandle, lStreamBuffer, &lMinStreamBufLength);
if(lResult != MJPEG_AVI_RETURN_OK)
{
MJPEG_ProcessErrorCode(lResult, "MJPEG_AVI_ReadNextFrame");
JPEG_MemAlloc_DELETE(StreamBuffer_Obj);
return CODEC_FILE_ERROR;
}
// setup JPEG Decoder
lStreamBufferInfo.Length = lStreamBufferLength; // frame size
lStreamBufferInfo.Pointer = lStreamBuffer; // pointer to MJPEG frame in Blackfin memory
// set the input buffer address to JPEG library
lResult = JPEG_Param_CONFIG(&lImageParam, JPEG_POINTER_INPUT, (int)&lStreamBufferInfo);
if(lResult != E_SUCCESS)
{
JPEG_ProcessErrorCode(lResult, "JPEG_Param_CONFIG");
JPEG_MemAlloc_DELETE(StreamBuffer_Obj);
return CODEC_ALGORITHM_ERROR;
}
// YUV output buffer address
lOutputBuffer = (uint8*)pYUVBufs[0];
// set the output buffer address to JPEG library
lResult = JPEG_Param_CONFIG(&lImageParam, JPEG_POINTER_OUTPUT, (int)lOutputBuffer);
if(lResult != E_SUCCESS)
{
JPEG_ProcessErrorCode(lResult, "JPEG_Param_CONFIG");
JPEG_MemAlloc_DELETE(StreamBuffer_Obj);
return CODEC_ALGORITHM_ERROR;
}
// create a JPEG Decoder instance
JpegDecHandle= JPEG_Decoder_NEW(&lImageParam);
if(JpegDecHandle == NULL)
{
fprintf(fperr, "Could not create JPEG decoder instance\n");
JPEG_MemAlloc_DELETE(StreamBuffer_Obj);
return CODEC_FILE_ERROR;
}
// Process JPEG file header info
lResult = JPEG_ProcessHeader(JpegDecHandle, &lImageParam);
if(lResult != E_SUCCESS)
{
JPEG_ProcessErrorCode(lResult, "JPEG_ProcessHeader");
JPEG_MemAlloc_DELETE(StreamBuffer_Obj);
JPEG_Decoder_DELETE(JpegDecHandle);
return CODEC_FILE_ERROR;
}
// Get frame width
lResult = JPEG_Param_STATUS(&lImageParam, JPEG_FRAME_WIDTH, &JPEGWidth);
if(lResult != E_SUCCESS) JPEG_ProcessErrorCode(lResult, "JPEG_Param_STATUS");
// Get frame height
lResult = JPEG_Param_STATUS(&lImageParam, JPEG_FRAME_HEIGHT, &JPEGHeight);
if(lResult != E_SUCCESS) JPEG_ProcessErrorCode(lResult, "JPEG_Param_STATUS");
// Get frame format
lResult = JPEG_Param_STATUS(&lImageParam, JPEG_IMAGEFORMAT, &JPEGFrameFormat);
if(lResult != E_SUCCESS) JPEG_ProcessErrorCode(lResult, "JPEG_Param_STATUS");
// Get coding type
lResult = JPEG_Param_STATUS(&lImageParam, JPEG_ENCODINGMODE, &CodingType);
if(lResult != E_SUCCESS) JPEG_ProcessErrorCode(lResult, "JPEG_Param_STATUS");
if( (JPEGWidth * JPEGHeight) > (MAX_JPEG_IMAGE_WIDTH * MAX_JPEG_IMAGE_HEIGHT) )
{
// This image can't be decoded as its bigger than available buffer size
fprintf(fperr, "Image size larger than YUV buffer size\n");
fprintf(fperr, "Image size - %d x %d pixels (includes padding), YUV size - %d x %d pixels\n",\
JPEGWidth,JPEGHeight,MAX_JPEG_IMAGE_WIDTH,MAX_JPEG_IMAGE_HEIGHT);
fprintf(fperr, "This file will be skipped!");
printf("\n");
JPEG_MemAlloc_DELETE(StreamBuffer_Obj);
JPEG_Decoder_DELETE(JpegDecHandle);
return CODEC_FILE_ERROR;
}
// Check the decoded MJPEG image Frame Format
if (JPEGFrameFormat != 1)
{
// image format not supported by this app
fprintf(fperr,"Input image format not supported, \n");
fprintf(fperr,"this version of developer kit only support YUV420 format files\n");
JPEG_MemAlloc_DELETE(StreamBuffer_Obj);
JPEG_Decoder_DELETE(JpegDecHandle);
return CODEC_FILE_ERROR;
}
// go to start of the frame
lResult = MJPEG_AVI_RewindToFirstFrame(lStreamHandle, &lStreamBufferLength);
if(lResult != MJPEG_AVI_RETURN_OK) MJPEG_ProcessErrorCode(lResult, "MJPEG_AVI_RewindToFirstFrame");
// initialise YUV to video (ITU656) frame conversion parameters
JPEGImageWidth = JPEGWidth;
JPEGImageHeight = JPEGHeight;
// Source Descriptor start address - YUV buffer(s)
pSrcDescStartAddr = pYUVBufs[0];
// Destination Descriptor start buffer - Video (ITU656) buffer(s)
pDestDescStartAddr = pITU656Frames[0];
// switch to JPEG image Frame format
switch (JPEGFrameFormat)
{
// case (JPEG image is in YUV420 format)
case 1:
// setup YUV420 to ITU656 frame conversion
SetupMDMA_YUV420toITU656 ();
// this would never occur as we've already validated JPEG image format
default:
break;
}
#ifdef ADI_MMSK_EXTRA_INFO // macro to enable extra debug information
// check if the image frame is bigger than output display resolution size
if ((JPEGWidth * JPEGHeight) > (ITU_PIXEL_PER_LINE * ActiveFrameLines))
// This image will be clipped
printf("Frame size larger than Display resolution. This file will be clipped!\n\n");
printf("Actual Frame Size = %d x %d pixels\n", JPEGWidth, JPEGHeight);
printf("Display Frame Size = %d x %d pixels\n", ITU_PIXEL_PER_LINE, ActiveFrameLines);
#endif
printf("\nPlaying MJPEG file.Do not press any keys until prompted...\n");
/****************************
Start Decoding MJPEG file
****************************/
// Initialise counters/flags
BufferLevel = 0;
StartMDMA = FALSE;
FrameReady = TRUE;
MJPEG_YUV_BufID = 0;
YUV_MDMA_BufID = 0;
lNumFrames = 0; // # of frames played
isMJDInputDataAvailable = E_TRUE;
FrameDroppedCounter = 0; // # of frames dropped
#ifdef ADI_MMSK_EXTRA_INFO // macro to enable extra debug information
// initialise statistics
max_frame_cycles = 0;
min_frame_cycles = (cycle_t)10*600*1000000; // set to time approx equivalent to 10Seconds at 600MHz - no frame should take longer than that to decode :)
max_usb_cycles = 0;
min_usb_cycles = (cycle_t)10*600*1000000; // set to time approx equivalent to 10Seconds at 600MHz - no frame should take longer than that to be read :)
max_usb_bytes = 0;
min_usb_bytes = (unsigned int)0x0fffffff; // big value for min calculation
cycle_sum = 0;
#endif
// Continue decoding till reaching end of file
while(E_TRUE == isMJDInputDataAvailable)
{
// Enable MDMA only when half of YUV buffers is filled with MJPEG frame (YUV) data
if( (!StartMDMA) && (BufferLevel >= NUM_YUV_BUFS) )
StartMDMA = TRUE;
#ifdef ADI_MMSK_EXTRA_INFO // Extra debug information
START_CYCLE_COUNT(start_count) // begin counting time
#endif
// Read next JPEG frame
lResult = MJPEG_AVI_ReadNextFrame(lStreamHandle, lStreamBuffer, &lMinStreamBufLength);
MJPEG_ProcessErrorCode(lResult, "MJPEG_AVI_ReadNextFrame");
switch (lResult)
{
case MJPEG_AVI_RETURN_OK:
break;
case MJPEG_AVI_RETURN_NOMORESAMPLES:
#ifdef ADI_MMSK_EXTRA_INFO // Extra debug information
printf("Reached end of MJPEG stream\n");
#endif
isMJDInputDataAvailable = E_FALSE;
continue;
case MJPEG_AVI_RETURN_EVALUATIONLIMITREACHED:
fprintf(fperr, "*** Reached limit of evaluation library ***\n");
isMJDInputDataAvailable = E_FALSE;
continue;
default:
printf("Cannot read to next frame of the MJPEG stream. Error code = %d\n", lResult);
return CODEC_FILE_ERROR;
}
#ifdef ADI_MMSK_EXTRA_INFO // Extra debug information
STOP_CYCLE_COUNT(final_count,start_count) // stop counting
// update cycle measurements
min_usb_cycles = min(min_usb_cycles, final_count);
max_usb_cycles = max(max_usb_cycles, final_count);
min_usb_bytes = min(min_usb_bytes, lMinStreamBufLength);
max_usb_bytes = max(max_usb_bytes, lMinStreamBufLength);
#endif
// Next YUV buffer to hold decoded MJPEG frame data
lOutputBuffer = (uint8*)(pYUVBufs[MJPEG_YUV_BufID]);
// update the output buffer address to store the decoded image
lResult = JPEG_Param_CONFIG(&lImageParam, JPEG_POINTER_OUTPUT, (int)lOutputBuffer);
JPEG_McuBuffer_CONFIG(mcu_ex, MCU_POINTER_C1, (unsigned int)lOutputBuffer);
if(lResult != E_SUCCESS) JPEG_ProcessErrorCode(lResult, "JPEG_Param_CONFIG");
// Wait for free buffers for decoding
while ( (BufferLevel >= NUM_YUV_BUFS) );
#ifdef ADI_MMSK_EXTRA_INFO // Extra debug information
START_CYCLE_COUNT(start_count) // begin counting time
#endif
// Decode this frame
lResult = JPEG_DecodeSequentialImage(JpegDecHandle, &lImageParam);
#ifdef ADI_MMSK_EXTRA_INFO // Extra debug information
STOP_CYCLE_COUNT(final_count,start_count) // stop counting
cycle_sum += (float)final_count;
// update cycle measurements
min_frame_cycles = min(min_frame_cycles, final_count);
max_frame_cycles = max(max_frame_cycles, final_count);
#endif
if (lResult != E_SUCCESS)
{
MJPEG_ProcessErrorCode(lResult, "JPEG_DecodeSequentialImage");
fprintf(fperr, "Failed to Decode this file!\n");
JPEG_Decoder_DELETE(JpegDecHandle);
JPEG_MemAlloc_DELETE(StreamBuffer_Obj);
return CODEC_ALGORITHM_ERROR;
}
// Update the count (next YUV buffer to be used by MJPEG decoder)
++MJPEG_YUV_BufID;
if (MJPEG_YUV_BufID >= NUM_YUV_BUFS)
MJPEG_YUV_BufID = 0;
// increment buffer level
++BufferLevel;
// increment frame counter
lNumFrames++;
} // while (E_TRUE == isMJDInputDataAvailable)
// Wait for all remaining frames to be played
while (BufferLevel > 0);
// Disable MDMA
StartMDMA = false;
// some statistics
printf("\nPlayed %d Frames", lNumFrames);
#ifdef ADI_MMSK_EXTRA_INFO // Extra debug information
printf(", Dropped %d Frame(s)\n\n", FrameDroppedCounter);
printf("Slowest Frame decoded in %llu cycles, equivalent to %lu cyles/pixel\n", max_frame_cycles,max_frame_cycles/(JPEGWidth * JPEGHeight));
printf("Fastest Frame decoded in %llu cycles, equivalent to %lu cyles/pixel\n", min_frame_cycles,min_frame_cycles/(JPEGWidth * JPEGHeight));
printf("Average decoding in %.0f cycles, equivalent to %.2f cycles/pixel\n",cycle_sum/lNumFrames,cycle_sum/lNumFrames/(JPEGWidth*JPEGHeight));
printf("Slowest Frame read %d bytes over USB in %llu cycles\n", max_usb_bytes, max_usb_cycles);
printf("Fastest Frame read %d bytes over USB in %llu cycles\n", min_usb_bytes, min_usb_cycles);
#endif
// clean up and close streams
if (MJPEG_AVI_CloseStreamRead(lStreamHandle) == MJPEG_AVI_RETURN_ERROR)
{
fprintf(fperr, "Cannot close MJPEG Decoder AVI stream\n");
JPEG_Decoder_DELETE(JpegDecHandle);
JPEG_MemAlloc_DELETE(StreamBuffer_Obj);
return CODEC_FILE_ERROR;
}
if (MJPEG_AVI_CloseFileRead(lStreamFileInHandle) == MJPEG_AVI_RETURN_ERROR)
{
fprintf(fperr, "Cannot close MJPEG Decoder input file\n");
JPEG_Decoder_DELETE(JpegDecHandle);
JPEG_MemAlloc_DELETE(StreamBuffer_Obj);
return CODEC_FILE_ERROR;
}
// Free and destroy used resources
JPEG_Decoder_DELETE(JpegDecHandle);
JPEG_MemAlloc_DELETE(StreamBuffer_Obj);
printf("\n*** MJPEG Playback successful ***\n");
return CODEC_SUCCESS;
}
/*****/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -