【STM32H7教程】第57章 STM32H7硬件JPEG編解碼基礎知識和HAL庫API

完整教程下載地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980

第57章       STM32H7硬件JPEG編解碼基礎知識和HAL庫API

本章節爲大家講解硬件JPEG,實際項目用到圖像顯示的地方比較多,有了硬件JPEG可以大大加速JPEG圖片顯示速度。

目錄

第57章       STM32H7硬件JPEG編解碼基礎知識和HAL庫API

57.1 初學者重要提示

57.2 硬件JPEG基礎知識

57.2.1 JPEG硬件框圖

57.2.2 YCbCr顏色格式

57.2.3 YCbCr採樣格式

57.2.4 YCbCr的優勢

57.2.5 YCbCr和RGB互轉

57.2.6 JPEG編解碼知識

57.3 硬件JPEG的HAL庫用法

57.3.1 JPEG寄存器結構體JPEG_TypeDef

57.3.2 JPEG的編解碼參數結構體JPEG_ConfTypeDef

57.3.3 JPEG結構體句柄JPEG_HandleTypeDef

57.3.4 JPEG初始化流程總結

57.4 源文件stm32h7xx_hal_jpeg.c

57.4.1 函數HAL_JPEG_Init

57.4.2 函數HAL_JPEG_GetInfo

57.4.3 函數HAL_JPEG_Decode_DMA

57.4.4 函數HAL_JPEG_ConfigInputBuffer

57.4.5 函數HAL_JPEG_ConfigOutputBuffer

57.5 總結


 

57.1 初學者重要提示

  1.   由於硬件JPEG解碼後輸出的圖像格式是YCbCr,所以本章對YCbCr進行了重點介紹。
  2.   測試STM32H7硬件JPEG解碼800*480圖片性能,全部通過SDRAM緩存數據,解碼10ms,顯示9ms:http://www.armbbs.cn/forum.php?mod=viewthread&tid=93598
  3.   JPEG涉及到的知識點還是比較多的,如果想深入瞭解JPEG的話,可以看本章2.6小節給的參考資料。
  4.   本章JPEG相關概念的介紹參考了wiki百科和百度百科。

57.2 硬件JPEG基礎知識

對於STM32H7的硬件JPEG瞭解到以下幾點即可:

  •   支持JPEG解碼和編碼。
  •   對每個像素數據進行編解碼只需一個時鐘週期。
  •   支持RGB、 YCbCr、YCMK和BW(灰度)圖像色彩模型。
  •   編解碼時每圖像分量8位深度。

57.2.1 JPEG硬件框圖

認識一個外設,最好的方式就是看它的框圖,方便我們快速地瞭解JPEG的基本功能,然後再看手冊瞭解細節。框圖如下所示:

通過這個框圖,我們可以得到如下信息:

  •   JPEG硬件外設支持編碼和解碼

並且對於輸入數據和輸出數據都有FIFO支持。

  •   jpeg_hclk

爲JPEG內核和寄存器提供時鐘。

  •   jpeg_it

JPEG全局中斷輸出。

  •   jpeg_ift_trg

JPEG輸入FIFO閾值信號,可觸發MDMA。

  •   jpeg_ifnf_trg

JPEG輸入FIFO未滿信號,可觸發MDMA。

  •   jpeg_oft_trg

JPEG輸出FIFO閥值信號,可觸發MDMA。

  •   jpeg_ofne_trg

JPEG輸出FIFO非空信號,可觸發MDMA。

  •   jpeg_oec_trg

JPEG轉換結束信號,可觸發MDMA。

57.2.2 YCbCr顏色格式

(注,硬件JPEG解碼後輸出的圖像格式是YCbCr,所以有必要了解下)

正如幾何上用座標空間來描述座標集,而色彩空間用數學方式來描述顏色集。常見的3種色彩模型是RGB,CMYK和YUV。

YCbCr是YUV經過縮放和修改的翻版,只是在表示方法上不同。其中Y是指亮度分量,Cb指藍色色度分量,而Cr指紅色色度分量。人眼對視頻的Y分量更敏感,因此通過對色度分量進行子採樣來減少色度分量後,人眼察覺不到的圖像質量的變化。

在YUV 家族中,YCbCr 是在計算機系統中應用最多的成員,其應用領域廣泛,JPEG、MPEG均採用此格式。一般人們所講的YUV大多是指YCbCr。

57.2.3 YCbCr採樣格式

YCbCr有許多取樣格式,如YCbCr 4:4:4,YCbCr 4:2:2,YCbCr 4:1:1 和YCbCr 4:2:0。

  •   4:2:0

表示每4個像素有4個亮度分量,2個色度分量 (YYYYCbCr),僅採樣奇數掃描線,是便攜式視頻設備(MPEG-4)以及電視會議(H.263)最常用格式。

  •   4:2:2

表示每4個像素有4個亮度分量,4個色度分量(YYYYCbCrCbCr),是DVD、數字電視、HDTV以及其它消費類視頻設備的最常用格式。

  •   4:4:4

表示全像素點陣(YYYYCbCrCbCrCbCrCbCr),用於高質量視頻應用、演播室以及專業視頻產品。

 

具體的採樣方式如下圖所示,以8個像素爲一個單元進行採樣:

 

由上面的截圖可以瞭解到:

4:4:4表示Y通道,Cb+Cr通道全部採樣。

4:2:2表示Y通道全部採樣,而Cb+Cr通道兩個像素爲一組,統一採用第1個顏色值。

4:2:0表示Y通道全部採樣,而Cb+Cr通道四個像素爲一組,統一採用第1個顏色值。

下面是整體效果,方便大家更好的理解:

 

 

57.2.4 YCbCr的優勢

RGB信號作爲存儲和傳輸的效率不高,因爲它們具有大量冗餘信息。而使用YCbCr可以丟棄一些信息以減少帶寬,因爲人的肉眼對視頻的Y分量更敏感,因此通過對色度分量進行子採樣來減少色度分量後,肉眼察覺不到的圖像質量的變化。瞭解這種人爲缺點,NTSC和PAL等標準大大降低了色度通道的帶寬。

57.2.5 YCbCr和RGB互轉

爲了方便大家更好的瞭解YCbCr和RGB圖像的實際效果,特此蒐集整理了兩個截圖(來自WIKI百科)。下面是圖像轉YCBCR的效果:四個圖,從上到下依次是原始圖像,Y通道,Cb通道和Cr通道。

下面是一幅圖像分別以R,G,B通道和Y,CB,CR通道的方式展示:

57.2.6 JPEG編解碼知識

JPEG涉及到的知識點比較多,這裏有之前整理的20多個專題知識點,大家有興趣可以瞭解下(不瞭解也沒有關係,不影響使用硬件JPEG外設):

http://www.armbbs.cn/forum.php?mod=forumdisplay&fid=12&filter=typeid&typeid=71

另外還ST整理的JPEG應用筆記,含中文版:

http://www.armbbs.cn/forum.php?mod=viewthread&tid=93516

57.3 硬件JPEG的HAL庫用法

JPEG的HAL庫用法其實就是幾個結構體變量成員的配置和使用,然後配置時鐘,並根據需要配置NVIC、中斷和MDMA。下面我們逐一展開爲大家做個說明。

57.3.1 JPEG寄存器結構體JPEG_TypeDef

JPEG相關的寄存器是通過HAL庫中的結構體JPEG_TypeDef定義的,在stm32h743xx.h中可以找到它們的具體定義:

typedef struct
{
  __IO uint32_t CONFR0;         
  __IO uint32_t CONFR1;          
  __IO uint32_t CONFR2;        
  __IO uint32_t CONFR3;        
  __IO uint32_t CONFR4;         
  __IO uint32_t CONFR5;       
  __IO uint32_t CONFR6;       
  __IO uint32_t CONFR7;        
  uint32_t  Reserved20[4];      
  __IO uint32_t CR;             
  __IO uint32_t SR;             
  __IO uint32_t CFR;            
  uint32_t  Reserved3c;        
  __IO uint32_t DIR;          
  __IO uint32_t DOR;            
  uint32_t  Reserved48[2];      
  __IO uint32_t QMEM0[16];     
  __IO uint32_t QMEM1[16];       
  __IO uint32_t QMEM2[16];      
  __IO uint32_t QMEM3[16];       
  __IO uint32_t HUFFMIN[16];    
  __IO uint32_t HUFFBASE[32];   
  __IO uint32_t HUFFSYMB[84];   
  __IO uint32_t DHTMEM[103];   
  uint32_t  Reserved4FC;      
  __IO uint32_t HUFFENC_AC0[88]; 
  __IO uint32_t HUFFENC_AC1[88]; 
  __IO uint32_t HUFFENC_DC0[8];  
  __IO uint32_t HUFFENC_DC1[8]; 
} JPEG_TypeDef;

 

__IO表示volatile, 這是標準C語言中的一個修飾字,表示這個變量是非易失性的,編譯器不要將其優化掉。core_m7.h 文件定義了這個宏:

#define     __O     volatile             /*!< Defines 'write only' permissions */
#define     __IO    volatile             /*!< Defines 'read / write' permissions */

 

下面我們再看JPEG的定義,在stm32h743xx.h文件。

#define PERIPH_BASE           ((uint32_t)0x40000000)
#define D1_AHB1PERIPH_BASE    (PERIPH_BASE + 0x12000000)
#define JPEG                  ((JPEG_TypeDef *) JPGDEC_BASE)
#define JPGDEC_BASE           (D1_AHB1PERIPH_BASE + 0x3000) <----- 展開這個宏,(JPEG_TypeDef *) 0x52003000

 

我們訪問JPEG的CR寄存器可以採用這種形式:JPEG->CR = 0。

57.3.2 JPEG的編解碼參數結構體JPEG_ConfTypeDef

此結構體用於JPEG的編解碼參數,具體定義如下:

typedef struct
{
  uint8_t  ColorSpace;               
  uint8_t  ChromaSubsampling;        
  uint32_t ImageHeight;              
  uint32_t ImageWidth;             
  uint8_t  ImageQuality;               
}JPEG_ConfTypeDef;

 

下面將這幾個參數逐一爲大家做個說明:

  •   uint8_t  ColorSpace

此參數用於設置輸出數據流中的量化表,具體支持的參數如下:

#define JPEG_GRAYSCALE_COLORSPACE     ((uint32_t)0x00000000U)    /* 灰度(1 個量化表)*/
#define JPEG_YCBCR_COLORSPACE         JPEG_CONFR1_COLORSPACE_0   /* YUV(2 個量化表) */
#define JPEG_CMYK_COLORSPACE          JPEG_CONFR1_COLORSPACE     /* CMYK(4 個量化表)*/

 

  •   uint8_t  ChromaSubsampling

此參數用於色度子採樣,具體支持的參數如下:

#define JPEG_444_SUBSAMPLING     ((uint32_t)0x00000000U)   /* 4:4:4 */
#define JPEG_420_SUBSAMPLING     ((uint32_t)0x00000001U)   /* 4:2:0 */
#define JPEG_422_SUBSAMPLING     ((uint32_t)0x00000002U)   /* 4:2:2 */

 

  •   uint32_t  ImageHeight

此參數用於圖像高度。

  •   uint32_t ImageWidth

此參數用於圖像寬度。

  •   uint8_t  ImageQuality

此參數用於圖像質量,參數範圍1 – 100,1最差,100最好。

57.3.3 JPEG結構體句柄JPEG_HandleTypeDef

HAL庫在JPEG_TypeDef, JPEG_ConfTypeDef的基礎上封裝了一個結構體JPEG_HandleTypeDef,定義如下:

typedef struct
{
  JPEG_TypeDef             *Instance;        
  JPEG_ConfTypeDef         Conf;             
  uint8_t                  *pJpegInBuffPtr; 
  uint8_t                  *pJpegOutBuffPtr; 
  __IO uint32_t            JpegInCount;      
  __IO uint32_t            JpegOutCount;     
  uint32_t                 InDataLength;     
  uint32_t                 OutDataLength;     
  MDMA_HandleTypeDef        *hdmain;         
  MDMA_HandleTypeDef        *hdmaout;        
  uint8_t                  CustomQuanTable; 
  uint8_t                  *QuantTable0;   
  uint8_t                  *QuantTable1;    
  uint8_t                  *QuantTable2;    
  uint8_t                  *QuantTable3;          
  HAL_LockTypeDef          Lock;            
  __IO  HAL_JPEG_STATETypeDef State;         
  __IO  uint32_t           ErrorCode;      
  __IO uint32_t Context;                    
}JPEG_HandleTypeDef;

 

下面將這幾個參數逐一做個說明。

  •   JPEG_TypeDef   *Instance

這個參數是寄存器的例化,方便操作寄存器,詳見本章3.1小節。

  •   JPEG_ConfTypeDef   Conf

這個參數是用戶接觸較多的,用於JPEG的編解碼參數,詳見本章3.2小節。

  •   uint8_t       *pJpegInBuffPtr

JPEG編解碼輸入緩衝地址

  •   uint8_t       *pJpegOutBuffPtr

JPEG編解碼輸出緩衝地址

  •   __IO uint32_t   JpegInCount

JPEG內部輸入計數。

  •   __IO uint32_t   JpegOutCount

JPEG內部輸出計數。

  •   uint32_t        InDataLength

JPEG輸入緩衝區長度,單位字節

  •   uint32_t          OutDataLength

JPEG輸出緩衝區長度,單位字節。

  •   MDMA_HandleTypeDef        *hdmain
  •   MDMA_HandleTypeDef        *hdmaout

MDMA句柄結構體指針變量,用於關聯JPEG句柄,方便調用。

  •   uint8_t       CustomQuanTable

如果此參數設置爲1,將使用用戶設置的量化表。

  •   uint8_t      *QuantTable0;   
  •   uint8_t      *QuantTable1;     
  •   uint8_t      *QuantTable2;    
  •   uint8_t      *QuantTable3;

指定量化表地址。    

  •   HAL_LockTypeDef          Lock           
  •   __IO  HAL_JPEG_STATETypeDef State           
  •   __IO  uint32_t           ErrorCode      

這三個變量主要供函數內部使用。Lock用於設置鎖狀態,State用於設置JPEG狀態,而ErrorCode用於配置代碼錯誤。

  •   __IO uint32_t Context

JPEG上下文。

57.3.4 JPEG初始化流程總結

使用方法由HAL庫提供:

  第1步:調用函數HAL_JPEG_Init進行初始化,但這個函數不需要初始化參數。

如果是JPEG編碼,可以通過函數HAL_JPEG_ConfigEncoding設置JPEG圖像的質量參數,質量越高,生成的JPEG文件越大、

  第2步:調用編解碼函數

  •   查詢式編解碼函數

HAL_JPEG_Encode

HAL_JPEG_Decode

 

  •   中斷方式

HAL_JPEG_Encode_IT

HAL_JPEG_Decode_IT

 

  •   DMA方式

HAL_JPEG_Encode_DMA

HAL_JPEG_Decode_DMA

  第4步:如果用戶之前的數據已經處理完畢,需要插入新數據,會調用函數HAL_JPEG_GetDataCallback

(1)如果新的數據已經準備好,需要調用函數HAL_JPEG_ConfigInputBuffer。如果新的數據沒有準備好,需要等待插入新數據時,可以調用函數HAL_JPEG_Pause(參數XferSelection被設置爲JPEG_PAUSE_RESUME_INPUT),待數據準備好後,可以調用HAL_JPEG_ConfigInputBuffer設置新的輸入緩衝和大小,然後調用函數HAL_JPEG_Resume恢復JPEG編解碼。

如果編解碼的數據已經處理完畢,可以調用函數HAL_JPEG_ConfigInputBuffer設置InDataLength參數爲0(此函數是在回調函數HAL_JPEG_GetDataCallback裏面被調用的)。

 

(2)函數HAL_JPEG_ConfigInputBuffer/HAL_JPEG_Pause/HAL_JPEG_Resume的工作機制允許應用程序以塊爲單位提供輸入數據。如果新的數據塊未準備好,可以調用函數HAL_JPEG_Pause暫停輸入,待數據準備好後,可以調用HAL_JPEG_ConfigInputBuffer設置新的輸入緩衝和大小,然後調用函數HAL_JPEG_Resume恢復JPEG編解碼。

 

(3)新的數據塊準備好後,可以在回調函數HAL_JPEG_GetDataCallback外面調用HAL_JPEG_ConfigInputBuffer 和 HAL_JPEG_Resume,但是爲了保持數據一致性問題,務必在回調函數HAL_JPEG_GetDataCallback裏面調用HAL_JPEG_Resume。

 

  第5步:輸出緩衝區填充了給定大小的數據後,會調用回調函數HAL_JPEG_DataReadyCallback

(1)如果有數據空間存儲新數據塊,需要調用函數HAL_JPEG_ConfigOutputBuffer配置新存儲位置。如果沒有數據空間存儲新數據塊,需要等待有數據空間可用時,可以調用函數HAL_JPEG_Pause(參數XferSelection被設置爲JPEG_PAUSE_RESUME_INPUT),待有數據空間可用時,可以調用HAL_JPEG_ConfigOutputBuffe設置新的輸出緩衝,然後調用函數HAL_JPEG_Resume恢復JPEG編解碼。

 

(2)函數HAL_JPEG_ConfigOutputBuffe/HAL_JPEG_Pause/HAL_JPEG_Resume的工作機制允許應用程序以塊爲單位接收數據。當接收到數據塊時,應用程序可以暫停JPEG輸出來處理這些數據,比如解碼時YCbCr轉RGB或者編碼時數據存儲。

 

(3)新的數據空間準備好後,可以在回調函數HAL_JPEG_DataReadyCallback外面調用HAL_JPEG_ConfigOutputBuffer和 HAL_JPEG_Resume,但是爲了保持數據一致性問題,務必在回調函數HAL_JPEG_DataReadyCallback裏面調用HAL_JPEG_Resume。

 

  第6步:其它相關函數

  •   JPEG解碼時,如果解碼成功,會調用回調函數HAL_JPEG_InfoReadyCallback。
  •   JPEG編碼操作結束後會調用回調函數HAL_JPEG_EncodeCpltCallback。
  •   JPEG解碼操作結束後,會調用回調函數HAL_JPEG_DecodeCpltCallback。
  •   操作過程中出現錯誤,會調用回調函數HAL_JPEG_ErrorCallback,用戶可以調用函數HAL_JPEG_GetError獲取錯誤類型。
  •   HAL JPEG默認使用的是ISO/IEC 10918-1規格量化表,如果要修改,可以調用函數HAL_JPEG_SetUserQuantTables實現。
  •   通過函數HAL_JPEG_GetState可以獲取JPEG狀態。

57.4 源文件stm32h7xx_hal_jpeg.c

這裏把我們把如下幾個常用到的函數做個說明:

  •   HAL_JPEG_Init
  •   HAL_JPEG_GetInfo
  •   HAL_JPEG_Decode_DMA
  •   HAL_JPEG_ConfigInputBuffer
  •   HAL_JPEG_ConfigOutputBuffer

57.4.1 函數HAL_JPEG_Init

函數原型:

HAL_StatusTypeDef HAL_JPEG_Init(JPEG_HandleTypeDef *hjpeg)
{
  uint32_t acLum_huffmanTableAddr = (uint32_t)(&JPEG_ACLUM_HuffTable);
  uint32_t dcLum_huffmanTableAddr = (uint32_t)(&JPEG_DCLUM_HuffTable);
  uint32_t acChrom_huffmanTableAddr = (uint32_t)(&JPEG_ACCHROM_HuffTable);
  uint32_t dcChrom_huffmanTableAddr = (uint32_t)(&JPEG_DCCHROM_HuffTable);
  
  /* 檢測句柄是否有效 */
  if(hjpeg == NULL)
  {
    return HAL_ERROR;
  }

  if(hjpeg->State == HAL_JPEG_STATE_RESET)
  {
    hjpeg->Lock = HAL_UNLOCKED;

     /* 初始化GPIO,NVIC等 */
    HAL_JPEG_MspInit(hjpeg);
  }
  
  /* 設置JPEG狀態 */
  hjpeg->State = HAL_JPEG_STATE_BUSY;
  
  /* 使能JPEG  */
  __HAL_JPEG_ENABLE(hjpeg);
  
  /* 關閉JPEG編解碼處理 */
  hjpeg->Instance->CONFR0 &=  ~JPEG_CONFR0_START;
  
  /* 關閉JPEG所有中斷 */
  __HAL_JPEG_DISABLE_IT(hjpeg,JPEG_INTERRUPT_MASK);
  
  /* 清空輸入輸入FIFO緩衝 */
  hjpeg->Instance->CR |= JPEG_CR_IFF;
  hjpeg->Instance->CR |= JPEG_CR_OFF;  
  
  /* 清除所有標誌 */
  __HAL_JPEG_CLEAR_FLAG(hjpeg,JPEG_FLAG_ALL);
  
  /* 初始化默認的量化表 */
  hjpeg->QuantTable0 = (uint8_t *)((uint32_t)JPEG_LUM_QuantTable);
  hjpeg->QuantTable1 = (uint8_t *)((uint32_t)JPEG_CHROM_QuantTable);
  hjpeg->QuantTable2 = NULL;
  hjpeg->QuantTable3 = NULL;
   
  /* 初始化默認的霍夫曼表 */
  if(JPEG_Set_HuffEnc_Mem(hjpeg, (JPEG_ACHuffTableTypeDef *)acLum_huffmanTableAddr, (JPEG_DCHuffTableTypeDef *)dcLum_huffmanTableAddr, (JPEG_ACHuffTableTypeDef *)acChrom_huffmanTableAddr, (JPEG_DCHuffTableTypeDef *)dcChrom_huffmanTableAddr) != HAL_OK)
  {
    hjpeg->ErrorCode = HAL_JPEG_ERROR_HUFF_TABLE;
    
    return HAL_ERROR;
  }
  
  /* 使能文件頭處理 */
  hjpeg->Instance->CONFR1 |= JPEG_CONFR1_HDR;
  
  /* 復位JPEG輸入輸出計數 */
  hjpeg->JpegInCount = 0;
  hjpeg->JpegOutCount = 0;
  
  /* 設置JPEG就緒 */
  hjpeg->State = HAL_JPEG_STATE_READY;
  
  /* 設置無錯誤 Reset the JPEG ErrorCode */
  hjpeg->ErrorCode = HAL_JPEG_ERROR_NONE;
  
  /* 清除上下文 */
  hjpeg->Context = 0;
  
  /* 返回HAL_OK */
  return HAL_OK;
}

 

函數描述:

此函數用於初始化JPEG。

函數參數:

  •   第1個參數是JPEG_HandleTypeDef類型結構體指針變量,用於配置要初始化的參數,結構體變量成員的詳細介紹看本章3.3小節。
  •   返回值,返回HAL_ERROR表示配置失敗,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示時間溢出。

注意事項:

  1. 函數HAL_JPEG_MspInit用於初始化JPEG的底層時鐘、NVIC等功能。需要用戶自己在此函數裏面實現具體的功能。由於這個函數是弱定義的,允許用戶在工程其它源文件裏面重新實現此函數。當然,不限制一定要在此函數裏面實現,也可以像早期的標準庫那樣,用戶自己初始化即可,更靈活些。
  2. 如果形參hjpeg的結構體成員State沒有做初始狀態,這個地方就是個坑。特別是用戶搞了一個局部變量JPEG_HandleTypeDef JpegHandle。

對於局部變量來說,這個參數就是一個隨機值,如果是全局變量還好,一般MDK和IAR都會將全部變量初始化爲0,而恰好這個 HAL_JPEG_STATE_RESET  = 0x00U。

解決辦法有三

方法1:用戶自己初始JPEG底層。

方法2:定義JPEG_HandleTypeDef JpegHandle爲全局變量。

方法3:下面的方法

if(HAL_JPEG_DeInit(&JpegHandle) != HAL_OK)
{
    Error_Handler();
}  
if(HAL_JPEG_Init(&Dma2dHandle) != HAL_OK)
{
    Error_Handler();
}

 

使用舉例:

JPEG_HandleTypeDef    JPEG_Handle;
JPEG_Handle.Instance = JPEG;
HAL_JPEG_Init(&JPEG_Handle);

 

57.4.2 函數HAL_JPEG_GetInfo

函數原型:

HAL_StatusTypeDef HAL_JPEG_GetInfo(JPEG_HandleTypeDef *hjpeg, JPEG_ConfTypeDef *pInfo)
{
  uint32_t yblockNb, cBblockNb, cRblockNb;
  
  /* 檢測句柄是否有效 */
  if((hjpeg == NULL) || (pInfo == NULL))
  {
    return HAL_ERROR;
  }
  
  /* 讀取配置參數 */
  if((hjpeg->Instance->CONFR1 & JPEG_CONFR1_NF) == JPEG_CONFR1_NF_1)
  {
    pInfo->ColorSpace = JPEG_YCBCR_COLORSPACE;    
  }    
  else if((hjpeg->Instance->CONFR1 & JPEG_CONFR1_NF) == 0)
  {
    pInfo->ColorSpace = JPEG_GRAYSCALE_COLORSPACE;
  }
  else if((hjpeg->Instance->CONFR1 & JPEG_CONFR1_NF) == JPEG_CONFR1_NF)
  {
    pInfo->ColorSpace = JPEG_CMYK_COLORSPACE;    
  }
  
  pInfo->ImageHeight = (hjpeg->Instance->CONFR1 & 0xFFFF0000U) >> 16;
  pInfo->ImageWidth  = (hjpeg->Instance->CONFR3 & 0xFFFF0000U) >> 16;
  
  if((pInfo->ColorSpace == JPEG_YCBCR_COLORSPACE) || (pInfo->ColorSpace == JPEG_CMYK_COLORSPACE))
  {
    yblockNb  = (hjpeg->Instance->CONFR4 & JPEG_CONFR4_NB) >> 4;
    cBblockNb = (hjpeg->Instance->CONFR5 & JPEG_CONFR5_NB) >> 4;
    cRblockNb = (hjpeg->Instance->CONFR6 & JPEG_CONFR6_NB) >> 4;
    
    if((yblockNb == 1) && (cBblockNb == 0) && (cRblockNb == 0))
    {
      pInfo->ChromaSubsampling = JPEG_422_SUBSAMPLING; /*16x8 block*/
    }
    else if((yblockNb == 0) && (cBblockNb == 0) && (cRblockNb == 0))
    {
      pInfo->ChromaSubsampling = JPEG_444_SUBSAMPLING;
    }
    else if((yblockNb == 3) && (cBblockNb == 0) && (cRblockNb == 0))
    {
      pInfo->ChromaSubsampling = JPEG_420_SUBSAMPLING;
    }
    else /* 默認是 4:4:4*/
    {
      pInfo->ChromaSubsampling = JPEG_444_SUBSAMPLING;
    } 
  }
  else 
  {
    pInfo->ChromaSubsampling = JPEG_444_SUBSAMPLING;
  }
  
  pInfo->ImageQuality = JPEG_GetQuality(hjpeg);
  
  /* 返回HAL_OK */
  return HAL_OK;
}

 

函數描述:

此函數主要用於解碼JPEG時獲取相關圖像信息,比如圖像質量,圖像長寬等。

函數參數:

  •   第1個參數是JPEG_HandleTypeDef類型結構體指針變量,用於配置要初始化的參數,結構體變量成員的詳細介紹看本章3.3小節。
  •   第2個參數是JPEG_ConfTypeDef類型結構體指針變量,用於獲取JPEG的配置信息,結構體變量成員的詳細介紹看本章3.2小
  •   返回值,返回HAL_ERROR表示配置失敗,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示時間溢出。

使用舉例:

JPEG_HandleTypeDef    JPEG_Handle;
JPEG_ConfTypeDef      JPEG_Info;

HAL_JPEG_GetInfo(&JPEG_Handle, &JPEG_Info);  

 

57.4.3 函數HAL_JPEG_Decode_DMA

函數原型:

HAL_StatusTypeDef  HAL_JPEG_Decode_DMA(JPEG_HandleTypeDef *hjpeg ,uint8_t *pDataIn ,uint32_t InDataLength ,uint8_t *pDataOutMCU ,uint32_t OutDataLength)
{
  /* 檢測參數 */
  assert_param((InDataLength >= 4));
  assert_param((OutDataLength >= 4));
  
  /* 檢測參數 */
  if((hjpeg == NULL) || (pDataIn == NULL) || (pDataOutMCU == NULL))
  {
    return HAL_ERROR;
  }
  
  /* 上鎖 */
  __HAL_LOCK(hjpeg);
  
  if(hjpeg->State == HAL_JPEG_STATE_READY)
  {
    /* 設置JPEG忙 */
    hjpeg->State = HAL_JPEG_STATE_BUSY_DECODING;
    
    /* 設置JPEG上下文,工作在DMA界面狀態 */
    hjpeg->Context &= ~(JPEG_CONTEXT_OPERATION_MASK | JPEG_CONTEXT_METHOD_MASK);
    hjpeg->Context |= (JPEG_CONTEXT_DECODE | JPEG_CONTEXT_DMA);         
    
    /* 設置輸入輸出緩衝地址和大小 */
    hjpeg->pJpegInBuffPtr = pDataIn;
    hjpeg->pJpegOutBuffPtr = pDataOutMCU;
    hjpeg->InDataLength = InDataLength;
    hjpeg->OutDataLength = OutDataLength;
    
    /* 復位輸入輸出緩衝計數 */
    hjpeg->JpegInCount = 0;    
    hjpeg->JpegOutCount = 0;    
    
    /* 初始化解碼處理 */
    JPEG_Init_Process(hjpeg);
    
    /* 啓動JPEG解碼處理,使用DMA方式 */
    JPEG_DMA_StartProcess(hjpeg);
    
  }
  else
  {
    /* 解鎖 */
    __HAL_UNLOCK(hjpeg);
    
    return HAL_BUSY;
  }

  /* 返回HAL_OK */
  return HAL_OK;
}

 

函數描述:

此函數用於啓動JPEG的DMA方式解碼。

函數參數:

  •   第1個參數是JPEG_HandleTypeDef類型結構體指針變量,用於配置要初始化的參數,結構體變量成員的詳細介紹看本章3.3小節。
  •   第2個參數是輸入數據緩衝地址。
  •   第3個參數輸入數據大小,單位字節。
  •   第4個參數是輸出緩衝地址。
  •   第5個參數是輸出緩衝大小,單位字節。
  •   返回值,返回HAL_ERROR表示配置失敗,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示時間溢出。

使用舉例:

/*
*********************************************************************************************************
*    函 數 名: JPEG_Decode_DMA
*    功能說明: JPEG解碼
*    形    參: hjpeg               JPEG_HandleTypeDef句柄指針
*             FrameSourceAddress  數據地址
*             FrameSize           數據大小
*             DestAddress         目的數據地址
*    返 回 值: HAL_ERROR表示配置失敗,HAL_OK表示配置成功
*             HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示時間溢出
*********************************************************************************************************
*/
uint32_t JPEG_Decode_DMA(JPEG_HandleTypeDef *hjpeg, uint32_t FrameSourceAddress ,uint32_t FrameSize, uint32_t DestAddress)
{
    JPEGSourceAddress =  FrameSourceAddress ;
    FrameBufferAddress = DestAddress;
    Input_frameIndex = 0;
    Input_frameSize = FrameSize;

    /* 設置標誌,0表示開始解碼,1表示解碼完成 */
    Jpeg_HWDecodingEnd = 0;

    /* 啓動JPEG解碼 */
    HAL_JPEG_Decode_DMA(hjpeg ,(uint8_t *)JPEGSourceAddress ,CHUNK_SIZE_IN ,
(uint8_t *)FrameBufferAddress ,CHUNK_SIZE_OUT);

    return HAL_OK;
}

 

57.4.4 函數HAL_JPEG_ConfigInputBuffer

函數原型:

void HAL_JPEG_ConfigInputBuffer(JPEG_HandleTypeDef *hjpeg, uint8_t *pNewInputBuffer, uint32_t InDataLength)
{
  hjpeg->pJpegInBuffPtr =  pNewInputBuffer;
  hjpeg->InDataLength = InDataLength;
}

 

函數描述:

此函數用於配置編解碼輸入緩衝地址和數據大小。

函數參數:

  •   第1個參數是JPEG_HandleTypeDef類型結構體指針變量,用於配置要初始化的參數,結構體變量成員的詳細介紹看本章3.3小節。
  •   第2個參數是輸入緩衝地址。
  •   第3個參數是輸入緩衝大小,單位字節。
  •   返回值,返回HAL_ERROR表示配置失敗,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示時間溢出。

使用舉例:

/*
*********************************************************************************************************
*    函 數 名: HAL_JPEG_GetDataCallback
*    功能說明: JPEG回調函數,用於從輸入地址獲取新數據繼續解碼
*    形    參: hjpeg          JPEG_HandleTypeDef 句柄指針
*             NbDecodedData  上一輪已經解碼的數據大小,單位字節  
*    返 回 值: 無
*********************************************************************************************************
*/
void HAL_JPEG_GetDataCallback(JPEG_HandleTypeDef *hjpeg, uint32_t NbDecodedData)
{
    uint32_t inDataLength; 
    
    /* 更新已經解碼的數據大小 */
    Input_frameIndex += NbDecodedData;
    
    /* 如果當前已經解碼的數據小於總文件大小,繼續解碼 */
    if( Input_frameIndex < Input_frameSize)
    {
        /* 更新解碼數據位置 */
        JPEGSourceAddress = JPEGSourceAddress + NbDecodedData;

        /* 更新下一輪要解碼的數據大小 */
        if((Input_frameSize - Input_frameIndex) >= CHUNK_SIZE_IN)
        {
            inDataLength = CHUNK_SIZE_IN;
        }
        else
        {
            inDataLength = Input_frameSize - Input_frameIndex;
        }    
    }
    else
    {
        inDataLength = 0; 
    }
    
    /* 更新輸入緩衝 */
    HAL_JPEG_ConfigInputBuffer(hjpeg,(uint8_t *)JPEGSourceAddress, inDataLength);    
}

 

57.4.5 函數HAL_JPEG_ConfigOutputBuffer

函數原型:

void HAL_JPEG_ConfigOutputBuffer(JPEG_HandleTypeDef *hjpeg, uint8_t *pNewOutputBuffer, uint32_t OutDataLength)
{
  hjpeg->pJpegOutBuffPtr = pNewOutputBuffer;
  hjpeg->OutDataLength = OutDataLength;  
}

 

函數描述:

此函數用於配置編解碼輸出緩衝地址和數據大小。

函數參數:

  •   第1個參數是JPEG_HandleTypeDef類型結構體指針變量,用於配置要初始化的參數,結構體變量成員的詳細介紹看本章3.3小節。
  •   第2個參數是輸出緩衝地址。
  •   第3個參數是輸出緩衝大小,單位字節。
  •   返回值,返回HAL_ERROR表示配置失敗,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示時間溢出。

使用舉例:

/*
*********************************************************************************************************
*    函 數 名: HAL_JPEG_DataReadyCallback
*    功能說明: JPEG回調函數,用於輸出緩衝地址更新
*    形    參: hjpeg         JPEG_HandleTypeDef 句柄指針
*             pDataOut      輸出數據緩衝
*             OutDataLength 輸出數據大小,單位字節
*    返 回 值: 無
*********************************************************************************************************
*/
void HAL_JPEG_DataReadyCallback (JPEG_HandleTypeDef *hjpeg, uint8_t *pDataOut, uint32_t OutDataLength)
{
    /* 更新JPEG輸出地址 */  
    FrameBufferAddress += OutDataLength;

    HAL_JPEG_ConfigOutputBuffer(hjpeg, (uint8_t *)FrameBufferAddress, CHUNK_SIZE_OUT); 
}

 

57.5 總結

本章節就爲大家講解這麼多,JPEG功能用到的地方還是比較多的,建議熟練使用。

 

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