📄 jpeg_decode.c
字号:
/*****************************************************************************
Copyright(c) 2005 Analog Devices, Inc. All Rights Reserved. This software is
proprietary and confidential to Analog Devices, Inc. and its licensors.
******************************************************************************
$RCSfile: jpeg_decode.c,v $
$Revision: 1.6 $
$Date: 2006/11/20 05:54:44 $
Project: BlackfinSDK (JPEG-MJPEG)
Title: JPEG decode
Author(s): ku, bmk
Revised by:
Description:
High level JPEG decoding functions
References:
None
******************************************************************************
Tab Setting: 4
Target Processor: ADSP-BF5xx
Target Tools Revision: ADSP VisualDSP++ v4.5
******************************************************************************
Modification History:
====================
$Log: jpeg_decode.c,v $
Revision 1.6 2006/11/20 05:54:44 bmk
Enabled streaming for video output
Revision 1.5 2006/11/10 07:18:59 bmk
merged BF533 & BF561 apps
Fixed BF561 cache issue
Revision 1.4 2006/11/03 07:12:16 bmk
SDK 2.0 files - Initial Entry
*****************************************************************************/
#include <jpeg_mjpeg_system.h> // JPEG-MJPEG System includes
#include <adi_usbio_blackfin.h> // USB I/O functions for Blackfin
#include <string.h> // string header
#include <math.h>
#include <cycle_count.h> // for basic cycle counting
// codec APIs
#include <JPEG_api_decoder.h>
#include <JPEG_BitsBuffer.h>
#include <IMG_common.h>
#include <JPEG_memalloc.h>
#include <jpeg_mjpeg_err.h>
// local function prototype
int JPEG_decode(char* input_file);
/*********************************************************************
Function: do_JPEG_Decode
Description: File Handling for JPEG decoding
*********************************************************************/
section("sdram0_bank1_nocache")
int do_JPEG_Decode (void)
{
char current_input_file_name[MAX_FILE_NAME_LEN];
static char current_path[MAX_PATH_NAME_LEN];
static char temp_path[MAX_PATH_NAME_LEN];
FILE *fp_jpg_dir; // file pointer to list file
int next_file = 1; // let next file value not be a null
char key;
int return_code = CODEC_SUCCESS;
int i;
printf("Blackfin(r) Multimedia Starter Kit - JPEG Decoder\n");
printf("(c) 2006 Analog Devices Inc.\n\n");
// Reset Video codecs
ResetVideoCodecs();
// Display output video mode
if (OutputVideoMode == ITU656_NTSC)
// NTSC video out
printf ("ITU656 NTSC Interlaced Video Out\n\n");
else if (OutputVideoMode == ITU656_PAL)
// PAL video out
printf ("ITU656 PAL Interlaced Video Out\n\n");
// prompt for file name & location?
if (File_Settings == PROMPT_FOR_FILE_SETTINGS)
{
printf("Enter directory path holding JPEG file(s): ");
fflush(stdout);
scanf ("%s", current_path); // get file path
strcat(current_path,"\\");
printf("Enter JPEG file name to decode: ");
fflush(stdout);
scanf ("%s", current_input_file_name); // get file name
key = getchar(); // clear the final character (\n) in the input buffer
}
else if (File_Settings == GET_FILE_SETTINGS_FROM_TXT_FILE)
{
// Open JPEG list file from .txt file in spec directory
strcpy(current_path, SPEC_DIR);
fp_jpg_dir = fopen( strcat(current_path, JPEG_LIST_FILE), "r" );
if (fp_jpg_dir == NULL)
{
fprintf( fperr, "Error: could not read directory file\n" );
return CODEC_FILE_ERROR;
}
// start decoding
printf("Reading list of JPEG files from %s\n", JPEG_LIST_FILE);
// Get first File name from directory file
next_file = fscanf(fp_jpg_dir, "%s", current_input_file_name);
}
// clear Frame ready flag to start JPEG Decoding
FrameReady = FALSE;
// Install Video Encoder (ADV717x)
InstallVideoEncoder();
// Setup MDMA for YUV to ITU656 conversion
SetupMDMA_YUV_ITU656();
// Format a JPEG image buffer as ITU656 frame
if (VideoMode == ITU656_PAL)
// Format as PAL frame
adi_video_FrameFormat ((char *)pITU656Frames[0],PAL_IL);
else // VideoMode must be ITU656_NTSC
// Format as NTSC frame
adi_video_FrameFormat ((char *)pITU656Frames[0],NTSC_IL);
while((next_file != EOF) && (next_file != (int)NULL))
{
// clear out video frame (black screen)
if (VideoMode == ITU656_PAL)
// Fill the Video out frame with background color
adi_video_FrameFill ((char *)pITU656Frames[0],PAL_IL,JPEGImageBackground);
else // VideoMode must be ITU656_NTSC
// Fill the Video out frame with background color
adi_video_FrameFill ((char *)pITU656Frames[0],NTSC_IL,JPEGImageBackground);
if (File_Settings == PROMPT_FOR_FILE_SETTINGS)
{
// check for file extension. add file extension if user didn't provide it
if ((strstr(current_input_file_name, ".jpg") == NULL) &&
(strstr(current_input_file_name, ".JPG") == NULL))
strcat(current_input_file_name,".jpg"); // add file extension
// build the next input file name in tempstring
strcpy (temp_path,current_path);
strcat(temp_path, current_input_file_name);
}
else if (File_Settings == GET_FILE_SETTINGS_FROM_TXT_FILE)
{
printf("\nInput file: %s\n", current_input_file_name);
// build the next input file name in tempstring
strcpy(temp_path, ROOT_DIR);
strcat(strcat(temp_path, IMAGE_DIR_JPEG), current_input_file_name);
}
// decode the JPEG file
if ((return_code = JPEG_decode(temp_path)) != CODEC_SUCCESS)
{
// if it was a file error, try next file in the list
if (return_code != CODEC_FILE_ERROR)
break; // error! Abort loop
else
FrameReady = TRUE; // File error. go to next file
}
// wait until JPEG to ITU656 frame conversion is done
while(!FrameReady)
asm("nop;");
// Submit Video Output buffer for JPEG (only one ITU656 frame buffer will be used)
SubmitVideoOutBufs();
// Wait for Key stroke to go to next file
printf("\nHit 'Return' key to go to next file or 'q' to quit: ");
fflush(stdout);
while (key = getchar())
{
if ((key == 'q') || (key == 'Q'))
next_file = EOF;
else if (key == '\n')
break;
}
// check for end of file
if((next_file != EOF) && (next_file != 0))
{
if (File_Settings == PROMPT_FOR_FILE_SETTINGS)
{
printf("\nEnter next JPEG file name to decode: ");
fflush(stdout);
scanf ("%s", current_input_file_name);
key = getchar(); // clear the final character (\n) in the input buffer
}
else if (File_Settings == GET_FILE_SETTINGS_FROM_TXT_FILE)
// Get Next File name from directory file
next_file = fscanf(fp_jpg_dir, "%s", current_input_file_name);
}
FrameReady = FALSE; // clear flag for next JPEG frame
}
if(return_code)
fprintf(fperr, "\n!!! JPEG Decoding Failed !!!\n");
if (File_Settings == GET_FILE_SETTINGS_FROM_TXT_FILE)
// close the list file
fclose( fp_jpg_dir );
// free up Video and DMA resources
// Free MDMA stream used for YUV to ITU656 conversion
FreeMDMA_YUV_ITU656 ();
// Close Video Encoder (ADV717x)
ezErrorCheck(adi_dev_Close(ADV717xDeviceHandle));
return return_code;
}
/*********************************************************************
Function: JPEG_decode
Description: Decodes a JPEG image (by interacting with JPEG Decode library)
Initiates YUV to ITU656 conversion
*********************************************************************/
section("sdram0_bank1_cache")
int JPEG_decode(char* input_file_name)
{
tJpegParam lParam;
tJpegDecoder *JpegDecHandle = 0;
FILE *inPtr = NULL;
tIMG_BufferInfo lInputBufferInfo;
MemObjHandle *StreamBuffer_Obj;
uint8 *lOutputBuffer;
// Parameters returned from CONFIG
unsigned int JPEGWidth = 0;
unsigned int JPEGHeight = 0;
int32 lResult = 0;
#ifdef ADI_MMSK_EXTRA_INFO // macto to enable extra debug information
// cycle counting
static cycle_t start_count;
static cycle_t final_count;
#endif
// Start a new image
if (JPEG_Param_INIT (&lParam) != E_SUCCESS)
{
fprintf(fperr, "Could not initialize JPEG parameters.\n");
return CODEC_ALGORITHM_ERROR;
}
// Configure the input buffer (get size from input file)
inPtr = fopen(input_file_name, "rb");
if(inPtr == NULL)
{
fprintf(fperr, "Error opening Input File %s\n",input_file_name);
return CODEC_FILE_ERROR;;
}
// Get the size of JPEG file to be decoded
fseek(inPtr, 0, SEEK_END);
lInputBufferInfo.Length = ftell (inPtr); // size of input file
// Dynamically allocate memory to copy the JPEG file for decoding
StreamBuffer_Obj = JPEG_MemAlloc_NEW(lInputBufferInfo.Length,sizeof (uint8),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", lInputBufferInfo.Length);
fclose(inPtr);
return CODEC_MEMORY_ALLOCATION_ERROR;
}
// Get the address of dynamically allocated buffer
lInputBufferInfo.Pointer = (uint8*)JPEG_MemAlloc_ADDRESS(StreamBuffer_Obj);
// Read the input file
fseek(inPtr, 0, SEEK_SET);
// Copy the JPEG file to dynamically allocated memory for decoding
if (fread(lInputBufferInfo.Pointer, sizeof (uint8), lInputBufferInfo.Length, inPtr) != lInputBufferInfo.Length)
{
fprintf(fperr, "Could not read input image\n");
fclose(inPtr);
JPEG_MemAlloc_DELETE(StreamBuffer_Obj);
return CODEC_FILE_ERROR;
}
#ifdef ADI_MMSK_EXTRA_INFO // macto to enable extra debug information
printf("Input buffer size = %d bytes\n", lInputBufferInfo.Length);
printf("Input buffer address = 0x%x\n\n", lInputBufferInfo.Pointer);
#endif
// Done with input file: close it
fclose(inPtr);
// Configure JPEG library to decode the copied JPEG image
lResult = JPEG_Param_CONFIG(&lParam, JPEG_POINTER_INPUT, (int)&lInputBufferInfo);
if(lResult != E_SUCCESS) JPEG_ProcessErrorCode(lResult, "JPEG_Param_CONFIG");
// Create a new JPEG Decoder instance
JpegDecHandle = JPEG_Decoder_NEW(&lParam);
if (JpegDecHandle == NULL)
{
fprintf(fperr, "Could not create JPEG decoder instance\n");
JPEG_MemAlloc_DELETE(StreamBuffer_Obj);
return CODEC_ALGORITHM_ERROR;
}
// Process the JPEG header and extract image parameters
lResult = JPEG_ProcessHeader(JpegDecHandle, &lParam);
if (lResult != E_SUCCESS)
{
JPEG_ProcessErrorCode(lResult, "JPEG_ProcessHeader");
JPEG_MemAlloc_DELETE(StreamBuffer_Obj);
JPEG_Decoder_DELETE(JpegDecHandle);
return CODEC_FILE_ERROR;
}
// Get the JPEG image width
lResult = JPEG_Param_STATUS(&lParam, JPEG_FRAME_WIDTH, &JPEGWidth);
if(lResult != E_SUCCESS) JPEG_ProcessErrorCode(lResult, "JPEG_Param_STATUS");
// Get the JPEG image height
lResult = JPEG_Param_STATUS(&lParam, JPEG_FRAME_HEIGHT, &JPEGHeight);
if(lResult != E_SUCCESS) JPEG_ProcessErrorCode(lResult, "JPEG_Param_STATUS");
// Get the JPEG image frame format (YUV4xx/RGG)
lResult = JPEG_Param_STATUS(&lParam, JPEG_IMAGEFORMAT, &JPEGFrameFormat);
if(lResult != E_SUCCESS) JPEG_ProcessErrorCode(lResult, "JPEG_Param_STATUS");
// Check the decoded JPEG 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 supports YUV420 format\n");
JPEG_MemAlloc_DELETE(StreamBuffer_Obj);
JPEG_Decoder_DELETE(JpegDecHandle);
return CODEC_SUCCESS;
}
// Pointer to (JPEG decoded) output buffer
lOutputBuffer = (uint8*)pYUVBufs[0];
// check if the image is bigger than YUV buffer size
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_Decoder_DELETE(JpegDecHandle);
JPEG_MemAlloc_DELETE(StreamBuffer_Obj);
return CODEC_FILE_ERROR;
}
// Give the output buffer pointer to JPEG Decoder library
lResult = JPEG_Param_CONFIG(&lParam, JPEG_POINTER_OUTPUT, (int)lOutputBuffer);
if(lResult != E_SUCCESS) JPEG_ProcessErrorCode(lResult, "JPEG_Param_CONFIG");
#ifdef ADI_MMSK_EXTRA_INFO // macro to enable extra debug information
// check if the image is bigger than output display resolution size
if ((JPEGWidth * JPEGHeight) > (ITU_PIXEL_PER_LINE * ActiveFrameLines))
// This image will be clipped
printf("Image size larger than Display resolution. This image will be clipped!\n\n");
printf("Actual Image Size = %d x %d pixels\n", JPEGWidth, JPEGHeight);
printf("Display Image Size = %d x %d pixels\n", ITU_PIXEL_PER_LINE, ActiveFrameLines);
START_CYCLE_COUNT(start_count) // begin counting time
#endif
// Decode the JPEG image
lResult = JPEG_DecodeImage(JpegDecHandle, &lParam);
#ifdef ADI_MMSK_EXTRA_INFO // Extra debug information
STOP_CYCLE_COUNT(final_count,start_count) // stop counting
printf("Took %lu cycles to decode this image, ",final_count);
printf("Equivalent to %lu cyles/pixel\n\n", final_count/((JPEGWidth) * (JPEGHeight)));
#endif // ADI_MMSK_EXTRA_INFO
if (lResult != E_SUCCESS)
{
JPEG_ProcessErrorCode(lResult, "JPEG_DecodeImage");
fprintf(fperr, "Failed to Decode this image!\n");
JPEG_MemAlloc_DELETE(StreamBuffer_Obj);
JPEG_Decoder_DELETE(JpegDecHandle);
return CODEC_ALGORITHM_ERROR;
}
// Clean up
JPEG_Decoder_DELETE(JpegDecHandle);
JPEG_MemAlloc_DELETE(StreamBuffer_Obj);
// initialise YUV to ITU656 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 happen as we've already validated JPEG image format
default:
break;
}
// Disable Video out dataflow before updating Video out buffer
ezErrorCheck(adi_dev_Control(ADV717xDeviceHandle, ADI_DEV_CMD_SET_DATAFLOW, (void*)FALSE));
// Kicks off MDMA for YUV to ITU656 frame conversion
KickOffMDMA_YUV_ITU656();
printf("*** JPEG Playback successful ***\n");
return CODEC_SUCCESS;
}
/*****/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -