生活随笔
收集整理的這篇文章主要介紹了
【视频处理】嵌入式硬件编码(6818)进行H264编码
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
有一個(gè)需要進(jìn)行硬件編碼的項(xiàng)目,因?yàn)榘遄咏o的SDK中并沒(méi)有給出詳細(xì)的使用方法,給自己的使用中帶來(lái)了很多的麻煩。經(jīng)過(guò)了很長(zhǎng)一段時(shí)間的嘗試,終于完成了對(duì)于NXP這套硬件編碼SDK的使用方式。
相關(guān)依賴(lài)文件:
NX_Queue.cpp
#include <assert.h>
#include <string.h>
#include <pthread.h>#include "NX_Queue.h"#define DbgMsg(fmt,...) printf(fmt)
int NX_InitQueue( NX_QUEUE
*pQueue
, unsigned int maxNumElement
)
{memset( pQueue
, 0, sizeof(NX_QUEUE
) );if( maxNumElement
> NX_MAX_QUEUE_ELEMENT
){return -1;}if( 0 != pthread_mutex_init( &pQueue
->hMutex
, NULL ) ){return -1;}pQueue
->maxElement
= maxNumElement
;pQueue
->bEnabled
= 1;return 0;
}int NX_PushQueue( NX_QUEUE
*pQueue
, void *pElement
)
{assert( NULL != pQueue
);pthread_mutex_lock( &pQueue
->hMutex
);if( pQueue
->curElements
>= pQueue
->maxElement
|| !pQueue
->bEnabled
){pthread_mutex_unlock( &pQueue
->hMutex
);return -1;}else{pQueue
->pElements
[pQueue
->tail
] = pElement
;pQueue
->tail
= (pQueue
->tail
+1)%pQueue
->maxElement
;pQueue
->curElements
++;}pthread_mutex_unlock( &pQueue
->hMutex
);return 0;
}int NX_PopQueue( NX_QUEUE
*pQueue
, void **pElement
)
{assert( NULL != pQueue
);pthread_mutex_lock( &pQueue
->hMutex
);if( pQueue
->curElements
== 0 || !pQueue
->bEnabled
){pthread_mutex_unlock( &pQueue
->hMutex
);return -1;}else{*pElement
= pQueue
->pElements
[pQueue
->head
];pQueue
->head
= (pQueue
->head
+ 1)%pQueue
->maxElement
;pQueue
->curElements
--;}pthread_mutex_unlock( &pQueue
->hMutex
);return 0;
}int NX_GetNextQueuInfo( NX_QUEUE
*pQueue
, void **pElement
)
{assert( NULL != pQueue
);pthread_mutex_lock( &pQueue
->hMutex
);if( pQueue
->curElements
== 0 || !pQueue
->bEnabled
){pthread_mutex_unlock( &pQueue
->hMutex
);return -1;}else{*pElement
= pQueue
->pElements
[pQueue
->head
];}pthread_mutex_unlock( &pQueue
->hMutex
);return 0;
}unsigned int NX_GetQueueCnt( NX_QUEUE
*pQueue
)
{assert( NULL != pQueue
);return pQueue
->curElements
;
}void NX_DeinitQueue( NX_QUEUE
*pQueue
)
{assert( NULL != pQueue
);pthread_mutex_lock( &pQueue
->hMutex
);pQueue
->bEnabled
= 0;pthread_mutex_unlock( &pQueue
->hMutex
);pthread_mutex_destroy( &pQueue
->hMutex
);memset( pQueue
, 0, sizeof(NX_QUEUE
) );
}
Queue.h
#ifndef __NX_Queue_h__
#define __NX_Queue_h__#include <pthread.h>#define NX_MAX_QUEUE_ELEMENT 128typedef struct NX_QUEUE
{unsigned int head
;unsigned int tail
;unsigned int maxElement
;unsigned int curElements
;int bEnabled
;void *pElements
[NX_MAX_QUEUE_ELEMENT
];pthread_mutex_t hMutex
;
}NX_QUEUE
;int NX_InitQueue( NX_QUEUE
*pQueue
, unsigned int maxNumElement
);
int NX_PushQueue( NX_QUEUE
*pQueue
, void *pElement
);
int NX_PopQueue( NX_QUEUE
*pQueue
, void **pElement
);
int NX_GetNextQueuInfo( NX_QUEUE
*pQueue
, void **pElement
);
unsigned int NX_GetQueueCnt( NX_QUEUE
*pQueue
);
void NX_DeinitQueue( NX_QUEUE
*pQueue
);#endif
Util.cpp
#include <stdio.h>
#include <sys/time.h>#include "Util.h"uint64_t NX_GetTickCount( void )
{uint64_t ret
;struct timeval tv
;struct timezone zv
;gettimeofday( &tv
, &zv
);ret
= ((uint64_t)tv
.tv_sec
)*1000 + tv
.tv_usec
/1000;return ret
;
}void dumpdata( void *data
, int32_t len
, const char *msg
)
{int32_t i
=0;uint8_t *byte
= (uint8_t *)data
;printf("Dump Data : %s", msg
);for( i
=0 ; i
<len
; i
++ ){if( i
!=0 && i
%16 == 0 ) printf("\n\t");printf("%.2x", byte
[i
] );if( i
%4 == 3 ) printf(" ");}printf("\n");
}
Util.h
#ifndef __UTIL_h__
#define __UTIL_h__#include <stdint.h>uint64_t NX_GetTickCount( void );
void dumpdata( void *data
, int32_t len
, const char *msg
);
typedef struct CODEC_APP_DATA
{char *inFileName
; int32_t width
; int32_t height
; int32_t fpsNum
; int32_t fpsDen
; char *outFileName
; char *outLogFileName
; char *outImgName
; int32_t kbitrate
; int32_t gop
; int32_t codec
; int32_t qp
; int32_t vbv
;int32_t maxQp
;int32_t RCAlgorithm
;int32_t angle
;int32_t dspX
; int32_t dspY
; int32_t dspWidth
; int32_t dspHeight
;
} CODEC_APP_DATA
;#endif
DEMO文件
VpuEncTest.cpp
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/time.h>
#include <math.h>#include <nx_fourcc.h>
#include <nx_vip.h>
#include <nx_dsp.h>
#include <nx_video_api.h> #include "NX_Queue.h"
#include "Util.h"#define MAX_SEQ_BUF_SIZE (4*1024)
#define MAX_ENC_BUFFER 8
#define ENABLE_NV12 1
static int32_t giX
= 0, giY
= 0, giWidth
= 1024, giHeight
= 600; static float GetPSNR
(uint8_t *pbyOrg
, uint8_t *pbyRecon
, int32_t iWidth
, int32_t iHeight
, int32_t iStride
)
{int32_t i
, j
;float fPSNR_L
= 0;for (i
= 0; i
< iHeight
; i
++) {for (j
= 0; j
< iWidth
; j
++) {fPSNR_L
+= (*(pbyOrg
+ j
) - *(pbyRecon
+ j
)) * (*(pbyOrg
+ j
) - *(pbyRecon
+ j
));}pbyOrg
+= iStride
;pbyRecon
+= iWidth
;}fPSNR_L
= (float) fPSNR_L
/ (float) (iWidth
* iHeight
);fPSNR_L
= (fPSNR_L
)? 10 * (float) log10
((float) (255 * 255) / fPSNR_L
): (float) 99.99;return fPSNR_L
;
}
static int32_t LoadImage( uint8_t *pSrc
, int32_t w
, int32_t h
, NX_VID_MEMORY_INFO
*pImg
)
{int32_t i
, j
;uint8_t *pDst
, *pCb
, *pCr
;pDst
= (uint8_t*)pImg
->luVirAddr
;for( i
=0 ; i
<h
; i
++ ){memcpy(pDst
, pSrc
, w
);pDst
+= pImg
->luStride
;pSrc
+= w
;}pCb
= pSrc
;pCr
= pSrc
+ w
*h
/4;switch( pImg
->fourCC
){case FOURCC_NV12
:{ printf("NV12\n");uint8_t *pCbCr
;pDst
= (uint8_t*)pImg
->cbVirAddr
;for( i
=0 ; i
<h
/2 ; i
++ ){pCbCr
= pDst
+ pImg
->cbStride
*i
;for( j
=0 ; j
<w
/2 ; j
++ ){*pCbCr
++ = *pCb
++;*pCbCr
++ = *pCr
++;}}break;}case FOURCC_NV21
:{uint8_t *pCrCb
;pDst
= (uint8_t*)pImg
->cbVirAddr
;for( i
=0 ; i
<h
/2 ; i
++ ){pCrCb
= pDst
+ pImg
->cbStride
*i
;for( j
=0 ; j
<w
/2 ; j
++ ){*pCrCb
++ = *pCr
++;*pCrCb
++ = *pCb
++;}}break;}case FOURCC_MVS0
:case FOURCC_YV12
:case FOURCC_IYUV
:{printf("YUV\n");pDst
= (uint8_t*)pImg
->cbVirAddr
;for( i
=0 ; i
<h
/2 ; i
++ ){memcpy(pDst
, pCb
, w
/2);pDst
+= pImg
->cbStride
;pCb
+= w
/2;}pDst
= (uint8_t*)pImg
->crVirAddr
;for( i
=0 ; i
<h
/2 ; i
++ ){memcpy(pDst
, pCr
, w
/2);pDst
+= pImg
->crStride
;pCr
+= w
/2;}break;}}return 0;
}#ifdef TEST_CHG_PARA
static void TestChangeParameter( ENC_APP_DATA
*pAppData
, NX_VID_ENC_HANDLE hEnc
, int32_t frameCnt
)
{NX_VID_ENC_CHG_PARAM stChgParam
= {0,};if (frameCnt
== 0){printf(" <<< Test Change Parameter >>> \n");}else if (frameCnt
== 200){stChgParam
.chgFlg
= VID_CHG_GOP
;stChgParam
.gopSize
= pAppData
->gop
>> 1;printf("Change From 200Frm : GOP Size is half (%d -> %d) \n", pAppData
->gop
, stChgParam
.gopSize
);NX_VidEncChangeParameter( hEnc
, &stChgParam
);}else if (frameCnt
== 400){stChgParam
.chgFlg
= VID_CHG_BITRATE
| VID_CHG_GOP
| VID_CHG_VBV
;stChgParam
.bitrate
= ( pAppData
->kbitrate
>> 1 ) * 1024;stChgParam
.gopSize
= pAppData
->gop
;stChgParam
.rcVbvSize
= 0;printf("Change From 400Frm : BPS is half (%d -> %d) \n", pAppData
->kbitrate
, stChgParam
.bitrate
);NX_VidEncChangeParameter( hEnc
, &stChgParam
);}else if (frameCnt
== 600){stChgParam
.chgFlg
= VID_CHG_FRAMERATE
| VID_CHG_BITRATE
| VID_CHG_VBV
;stChgParam
.bitrate
= pAppData
->kbitrate
* 1024;stChgParam
.fpsNum
= pAppData
->fpsNum
>> 1;stChgParam
.fpsDen
= pAppData
->fpsDen
;stChgParam
.rcVbvSize
= 0;printf("Change From 600Frm : FPS is half (%d, %d) \n", pAppData
->fpsNum
, stChgParam
.fpsNum
);NX_VidEncChangeParameter( hEnc
, &stChgParam
);}else if (frameCnt
== 800){stChgParam
.chgFlg
= VID_CHG_BITRATE
| VID_CHG_GOP
| VID_CHG_FRAMERATE
| VID_CHG_VBV
;stChgParam
.bitrate
= ( pAppData
->kbitrate
<< 2 ) * 1024;stChgParam
.gopSize
= pAppData
->gop
>> 2;stChgParam
.fpsNum
= pAppData
->fpsNum
;stChgParam
.fpsDen
= pAppData
->fpsDen
;stChgParam
.rcVbvSize
= 0;printf("Change From 800Frm : BPS is quadruple & gop is quarter (%d -> %d, %d -> %d) \n", pAppData
->kbitrate
, stChgParam
.bitrate
, pAppData
->gop
, stChgParam
.gopSize
);NX_VidEncChangeParameter( hEnc
, &stChgParam
);}
}
#endif#if 0
static int32_t VpuCamEncMain( CODEC_APP_DATA
*pAppData
)
{int32_t i
;int32_t cropX
=0, cropY
=0, cropW
, cropH
; int32_t frameCnt
= 0;FILE
*fdOut
= NULL;VIP_HANDLE hVip
;VIP_INFO vipInfo
;NX_VID_MEMORY_HANDLE hMem
[MAX_ENC_BUFFER
];DISPLAY_HANDLE hDsp
;NX_QUEUE memQueue
;DISPLAY_INFO dspInfo
;NX_VID_MEMORY_INFO
*pPrevDsp
= NULL;
#ifdef NV12_MEM_TESTNX_VID_MEMORY_INFO
*pNV12Mem
= NULL;
#endifNX_VID_MEMORY_INFO
*pCurCapturedBuf
= NULL;NX_VID_MEMORY_INFO
*pTmpMem
= NULL;NX_VID_ENC_INIT_PARAM encInitParam
;unsigned char *seqBuffer
= (unsigned char *)malloc( MAX_SEQ_BUF_SIZE
);NX_VID_ENC_HANDLE hEnc
;NX_VID_ENC_IN encIn
;NX_VID_ENC_OUT encOut
;long long totalSize
= 0;long long vipTimeStamp
;int instanceIdx
;cropX
= 0;cropY
= 0;cropW
= pAppData
->width
;cropH
= pAppData
->height
;NX_InitQueue( &memQueue
, MAX_ENC_BUFFER
);for( i
=0; i
<MAX_ENC_BUFFER
; i
++ ){hMem
[i
] = NX_VideoAllocateMemory( 4096, cropW
, cropH
, NX_MEM_MAP_LINEAR
, FOURCC_MVS0
);NX_PushQueue( &memQueue
, hMem
[i
] );}memset( &vipInfo
, 0, sizeof(vipInfo
) );vipInfo
.port
= 2;vipInfo
.mode
= VIP_MODE_CLIPPER
;vipInfo
.width
= pAppData
->width
;vipInfo
.height
= pAppData
->height
;vipInfo
.numPlane
= 1;vipInfo
.cropX
= cropX
;vipInfo
.cropY
= cropY
;vipInfo
.cropWidth
= cropW
;vipInfo
.cropHeight
= cropH
;vipInfo
.fpsNum
= pAppData
->fpsNum
;vipInfo
.fpsDen
= 1;if( pAppData
->outFileName
)fdOut
= fopen( pAppData
->outFileName
, "wb" );#ifndef ANDROIDdspInfo
.port
= 0;dspInfo
.module
= 0;dspInfo
.width
= cropW
;dspInfo
.height
= cropH
;dspInfo
.numPlane
= 1;dspInfo
.dspSrcRect
.left
= 0;dspInfo
.dspSrcRect
.top
= 0;dspInfo
.dspSrcRect
.right
= cropW
;dspInfo
.dspSrcRect
.bottom
= cropH
;dspInfo
.dspDstRect
.left
= 0;dspInfo
.dspDstRect
.top
= 0;dspInfo
.dspDstRect
.right
= cropW
;dspInfo
.dspDstRect
.bottom
= cropH
;hDsp
= NX_DspInit( &dspInfo
);
#endifhEnc
= NX_VidEncOpen( NX_AVC_ENC
, &instanceIdx
);memset( &encInitParam
, 0, sizeof(encInitParam
) );encInitParam
.width
= cropW
;encInitParam
.height
= cropH
;encInitParam
.gopSize
= pAppData
->gop
;encInitParam
.bitrate
= pAppData
->kbitrate
* 1024;encInitParam
.fpsNum
= pAppData
->fpsNum
;encInitParam
.fpsDen
= 1;
#ifdef NV12_MEM_TESTencInitParam
.chromaInterleave
= 1;
#elseencInitParam
.chromaInterleave
= 0;
#endifencInitParam
.enableRC
= 1; encInitParam
.disableSkip
= 0; encInitParam
.maximumQp
= 51; encInitParam
.initialQp
= pAppData
->qp
; encInitParam
.enableAUDelimiter
= 1; NX_VidEncInit( hEnc
, &encInitParam
);if( fdOut
){int size
;NX_VidEncGetSeqInfo( hEnc
, seqBuffer
, &size
);fwrite( seqBuffer
, 1, size
, fdOut
);dumpdata( seqBuffer
, size
, "sps pps" );printf("Encoder Out Size = %d\n", size
);}#ifdef NV12_MEM_TESTpNV12Mem
= NX_VideoAllocateMemory( 4096, cropW
, cropH
, NX_MEM_MAP_LINEAR
, FOURCC_NV12
);
#endif#ifndef ANDROIDNX_PopQueue( &memQueue
, (void**)&pTmpMem
);NX_VipQueueBuffer( hVip
, pTmpMem
);
#endifwhile(1){NX_PopQueue( &memQueue
, (void**)&pTmpMem
);NX_VipQueueBuffer( hVip
, pTmpMem
);NX_VipDequeueBuffer( hVip
, &pCurCapturedBuf
, &vipTimeStamp
);NX_DspQueueBuffer( hDsp
, pCurCapturedBuf
);if( pPrevDsp
){NX_DspDequeueBuffer( hDsp
);#ifdef NV12_MEM_TESTif( pNV12Mem
){int j
;unsigned char *cbcr
=(unsigned char*)pNV12Mem
->cbVirAddr
;unsigned char *cb
=(unsigned char*)pPrevDsp
->cbVirAddr
;unsigned char *cr
=(unsigned char*)pPrevDsp
->crVirAddr
;memcpy( (unsigned char*)pNV12Mem
->luVirAddr
, (unsigned char*)pPrevDsp
->luVirAddr
, cropW
*cropH
);for( i
=0 ; i
<cropH
/2 ; i
++ ){for( j
=0 ; j
<cropW
/2 ; j
++ ){*cbcr
++ = *cb
++;*cbcr
++ = *cr
++;}}encIn
.pImage
= pNV12Mem
;}else
#endif{encIn
.pImage
= pPrevDsp
;}encIn
.timeStamp
= 0;encIn
.forcedIFrame
= 0;encIn
.forcedSkipFrame
= 0;encIn
.quantParam
= 25;NX_VidEncEncodeFrame( hEnc
, &encIn
, &encOut
);if( fdOut
&& encOut
.bufSize
>0 ){double bitRate
= 0.;fwrite( encOut
.outBuf
, 1, encOut
.bufSize
, fdOut
);printf("FrameType = %d, size = %8d, ", encOut
.frameType
, encOut
.bufSize
);
#ifdef DUMP_DATAdumpdata( encOut
.outBuf
, 16, "" );
#endiftotalSize
+= encOut
.bufSize
;bitRate
= (double)totalSize
/(double)frameCnt
*.8;printf("bitRate = %4.3f kbps\n", bitRate
*30/1024.);}NX_PushQueue( &memQueue
, pPrevDsp
);}pPrevDsp
= pCurCapturedBuf
;frameCnt
++;}if( fdOut
){fclose( fdOut
);}NX_DspClose( hDsp
);NX_VipClose( hVip
);return 0;
}
#endif
static int32_t VpuEncPerfMain( CODEC_APP_DATA
*pAppData
)
{DISPLAY_HANDLE hDsp
; NX_VID_ENC_HANDLE hEnc
; uint64_t StrmTotalSize
= 0;float PSNRSum
= 0;int32_t inWidth
= pAppData
->width
;int32_t inHeight
= pAppData
->height
;FILE
*fdIn
= fopen( pAppData
->inFileName
, "rb" );FILE
*fdOut
= fopen( pAppData
->outFileName
, "wb" );FILE
*fdLog
= fopen( pAppData
->outLogFileName
, "w" );FILE
*fdRecon
= ( pAppData
->outImgName
) ? fopen( pAppData
->outImgName
, "wb" ) : NULL;if ( fdIn
== NULL || fdOut
== NULL ){printf("input file or output file open error!!\n");exit(-1);}{NX_VID_ENC_INIT_PARAM encInitParam
= {0, }; uint8_t *seqBuffer
= (uint8_t *)malloc( MAX_SEQ_BUF_SIZE
);
#ifndef ANDROIDDISPLAY_INFO dspInfo
= {0, };dspInfo
.port
= 0;dspInfo
.module
= 0;dspInfo
.width
= inWidth
;dspInfo
.height
= inHeight
;dspInfo
.numPlane
= 1;dspInfo
.dspSrcRect
.left
= 0;dspInfo
.dspSrcRect
.top
= 0;dspInfo
.dspSrcRect
.right
= inWidth
;dspInfo
.dspSrcRect
.bottom
= inHeight
;dspInfo
.dspDstRect
.left
= pAppData
->dspX
;dspInfo
.dspDstRect
.top
= pAppData
->dspY
;dspInfo
.dspDstRect
.right
= pAppData
->dspX
+ pAppData
->dspWidth
;dspInfo
.dspDstRect
.bottom
= pAppData
->dspY
+ pAppData
->dspHeight
;hDsp
= NX_DspInit( &dspInfo
);NX_DspVideoSetPriority(dspInfo
.module
, 0);
#endifif ( pAppData
->codec
== 0) pAppData
->codec
= NX_AVC_ENC
;else if (pAppData
->codec
== 1) pAppData
->codec
= NX_MP4_ENC
;else if (pAppData
->codec
== 2) pAppData
->codec
= NX_H263_ENC
;else if (pAppData
->codec
== 3) pAppData
->codec
= NX_JPEG_ENC
;hEnc
= NX_VidEncOpen( (VID_TYPE_E
)pAppData
->codec
, NULL );pAppData
->fpsNum
= ( pAppData
->fpsNum
) ? ( pAppData
->fpsNum
) : ( 30 );pAppData
->fpsDen
= ( pAppData
->fpsDen
) ? ( pAppData
->fpsDen
) : ( 1 );pAppData
->gop
= ( pAppData
->gop
) ? ( pAppData
->gop
) : ( pAppData
->fpsNum
/ pAppData
->fpsDen
);encInitParam
.width
= inWidth
;encInitParam
.height
= inHeight
;encInitParam
.fpsNum
= pAppData
->fpsNum
;encInitParam
.fpsDen
= pAppData
->fpsDen
;encInitParam
.gopSize
= pAppData
->gop
;encInitParam
.bitrate
= pAppData
->kbitrate
* 1024;encInitParam
.chromaInterleave
= ENABLE_NV12
;encInitParam
.enableAUDelimiter
= 0; encInitParam
.searchRange
= 0;if ( pAppData
->codec
== NX_JPEG_ENC
){encInitParam
.chromaInterleave
= 0;encInitParam
.jpgQuality
= (pAppData
->qp
== 0) ? (90) : (pAppData
->qp
);}encInitParam
.maximumQp
= pAppData
->maxQp
;encInitParam
.disableSkip
= 0;encInitParam
.initialQp
= pAppData
->qp
;encInitParam
.enableRC
= ( encInitParam
.bitrate
) ? ( 1 ) : ( 0 );encInitParam
.RCAlgorithm
= ( pAppData
->RCAlgorithm
== 0 ) ? ( 1 ) : ( 0 );encInitParam
.rcVbvSize
= ( pAppData
->vbv
) ? (pAppData
->vbv
) : (encInitParam
.bitrate
* 2 / 8);if (NX_VidEncInit( hEnc
, &encInitParam
) != VID_ERR_NONE
){printf("NX_VidEncInit() failed \n");exit(-1);}printf("NX_VidEncInit() success \n");if( fdOut
){int size
;if ( pAppData
->codec
!= NX_JPEG_ENC
)NX_VidEncGetSeqInfo( hEnc
, seqBuffer
, &size
);elseNX_VidEncJpegGetHeader( hEnc
, seqBuffer
, &size
);fwrite( seqBuffer
, 1, size
, fdOut
);dumpdata( seqBuffer
, size
, "sps pps" );StrmTotalSize
+= size
;printf("Encoder Header Size = %d\n", size
);}if( fdLog
){fprintf(fdLog
, "Frame Count\tFrame Size\tEncoding Time\tIs Key\n");}}{NX_VID_MEMORY_HANDLE hMem
[MAX_ENC_BUFFER
]; NX_VID_MEMORY_INFO
*pPrevDsp
= NULL; NX_VID_ENC_IN encIn
;NX_VID_ENC_OUT encOut
;long long totalSize
= 0;double bitRate
= 0.;int32_t frameCnt
= 0, i
, readSize
;uint64_t startTime
, endTime
, totalTime
= 0;uint8_t *pSrcBuf
= (uint8_t*)malloc(inWidth
*inHeight
*3/2);for( i
=0; i
<MAX_ENC_BUFFER
; i
++ ){if ( pAppData
->codec
!= NX_JPEG_ENC
){
#if ENABLE_NV12hMem
[i
] = NX_VideoAllocateMemory( 4096, inWidth
, inHeight
, NX_MEM_MAP_LINEAR
, FOURCC_NV12
);
#elsehMem
[i
] = NX_VideoAllocateMemory( 4096, inWidth
, inHeight
, NX_MEM_MAP_LINEAR
, FOURCC_MVS0
);
#endif}elsehMem
[i
] = NX_VideoAllocateMemory( 4096, inWidth
, inHeight
, NX_MEM_MAP_LINEAR
, FOURCC_MVS0
);}while(1){
#ifdef TEST_CHG_PARATestChangeParameter( pAppData
, hEnc
, frameCnt
);
#endifencIn
.pImage
= hMem
[frameCnt
%MAX_ENC_BUFFER
];if( fdIn
){readSize
= fread(pSrcBuf
, 1, inWidth
*inHeight
*3/2, fdIn
);if( readSize
!= inWidth
*inHeight
*3/2 || readSize
== 0 ){printf("End of Stream!!!\n");break;}}LoadImage( pSrcBuf
, inWidth
, inHeight
, encIn
.pImage
);if ( pAppData
->codec
!= NX_JPEG_ENC
){encIn
.forcedIFrame
= 0;encIn
.forcedSkipFrame
= 0;encIn
.quantParam
= pAppData
->qp
;encIn
.timeStamp
= 0;startTime
= NX_GetTickCount();NX_VidEncEncodeFrame( hEnc
, &encIn
, &encOut
);}else{startTime
= NX_GetTickCount();NX_VidEncJpegRunFrame( hEnc
, encIn
.pImage
, &encOut
);}endTime
= NX_GetTickCount();totalTime
+= (endTime
-startTime
);#ifndef ANDROIDNX_DspQueueBuffer( hDsp
, encIn
.pImage
);if( pPrevDsp
){NX_DspDequeueBuffer( hDsp
);}pPrevDsp
= encIn
.pImage
;
#endifif( fdOut
&& encOut
.bufSize
>0 ){float PSNR
= GetPSNR((uint8_t *)encIn
.pImage
->luVirAddr
, (uint8_t *)encOut
.ReconImg
.luVirAddr
, encOut
.width
, encOut
.height
, encIn
.pImage
->luStride
);totalSize
+= encOut
.bufSize
;bitRate
= (double)totalSize
*8/(double)frameCnt
;fwrite( encOut
.outBuf
, 1, encOut
.bufSize
, fdOut
);printf("[%4d]FrameType = %d, size = %8d, ", frameCnt
, encOut
.frameType
, encOut
.bufSize
);printf("bitRate = %6.3f kbps, Qp = %2d, PSNR = %f, time=%6lld\n", bitRate
*pAppData
->fpsNum
/pAppData
->fpsDen
/1000., encIn
.quantParam
, PSNR
, (endTime
-startTime
) );StrmTotalSize
+= encOut
.bufSize
;PSNRSum
+= PSNR
;if( fdLog
){fprintf(fdLog
, "%5d\t%7d\t%2d\t%lld\t%d\n", frameCnt
, encOut
.bufSize
, encIn
.quantParam
, (endTime
-startTime
), encOut
.frameType
);fflush(fdLog
);}if ( fdRecon
){if ( encOut
.width
== encOut
.ReconImg
.luStride
){fwrite( (void *)encOut
.ReconImg
.luVirAddr
, 1, encOut
.width
* encOut
.height
, fdRecon
);fwrite( (void *)encOut
.ReconImg
.cbVirAddr
, 1, encOut
.width
* encOut
.height
/ 4, fdRecon
);fwrite( (void *)encOut
.ReconImg
.crVirAddr
, 1, encOut
.width
* encOut
.height
/ 4, fdRecon
);}else{int32_t y
;uint8_t *pbyTmp
= (uint8_t *)encOut
.ReconImg
.luVirAddr
;for (y
=0 ; y
<encOut
.height
; y
++){fwrite( (void *)pbyTmp
, 1, encOut
.width
, fdRecon
);pbyTmp
+= encOut
.ReconImg
.luStride
;}pbyTmp
= (uint8_t *)encOut
.ReconImg
.cbVirAddr
;for (y
=0 ; y
<encOut
.height
/2 ; y
++){fwrite( (void *)pbyTmp
, 1, encOut
.width
/2, fdRecon
);pbyTmp
+= encOut
.ReconImg
.cbStride
;}pbyTmp
= (uint8_t *)encOut
.ReconImg
.crVirAddr
;for (y
=0 ; y
<encOut
.height
/2 ; y
++){fwrite( (void *)pbyTmp
, 1, encOut
.width
/2, fdRecon
);pbyTmp
+= encOut
.ReconImg
.crStride
;}}}}frameCnt
++;}{float TotalBps
= (float)((StrmTotalSize
* 8 * pAppData
->fpsNum
/ pAppData
->fpsDen
) / (frameCnt
* 1024));printf("[Summary]Bitrate = %.3fKBps(%.2f%), PSNR = %.3fdB, Frame Count = %d \n", TotalBps
, TotalBps
* 100 / pAppData
->kbitrate
, (PSNRSum
/ frameCnt
), frameCnt
);}}if( fdLog
){fclose(fdLog
);}if( fdIn
){fclose( fdIn
);}if( fdOut
){fclose( fdOut
);}if( hEnc
){NX_VidEncClose( hEnc
);}#ifndef ANDROIDNX_DspClose( hDsp
);
#endifreturn 0;
}int32_t VpuEncMain( CODEC_APP_DATA
*pAppData
)
{if( pAppData
->inFileName
){if( pAppData
->outLogFileName
== NULL ){pAppData
->outLogFileName
= (char*)malloc(strlen(pAppData
->outFileName
) + 5);strcpy(pAppData
->outLogFileName
, pAppData
->outFileName
);strcat(pAppData
->outLogFileName
, ".log");}return VpuEncPerfMain( pAppData
);}return 0;
}
通過(guò)了一些改編寫(xiě)了一個(gè)相關(guān)的類(lèi),可以實(shí)現(xiàn)對(duì)于硬件編碼的快捷使用
Vpu.cpp
#include "Vpu.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/time.h>
#include <math.h>#include <nx_fourcc.h>
#include <nx_vip.h>
#include <nx_dsp.h>
#include <nx_video_api.h> #include "NX_Queue.h"
#include "Util.h"#define MAX_SEQ_BUF_SIZE (4*1024)
#define MAX_ENC_BUFFER 8
#define ENABLE_NV12 1enum
{MODE_NONE
,DECODER_MODE
,ENCODER_MODE
,JPEG_MODE
,MODE_MAX
};int32_t vpu
:: LoadImage( uint8_t *pSrc
, int32_t w
, int32_t h
, NX_VID_MEMORY_INFO
*pImg
)
{int32_t i
, j
;uint8_t *pDst
, *pCb
, *pCr
;pDst
= (uint8_t*)pImg
->luVirAddr
;for( i
=0 ; i
<h
; i
++ ){memcpy(pDst
, pSrc
, w
);pDst
+= pImg
->luStride
;pSrc
+= w
;}pCb
= pSrc
;pCr
= pSrc
+ w
*h
/4;uint8_t *pCbCr
;pDst
= (uint8_t*)pImg
->cbVirAddr
;for( i
=0 ; i
<h
/2 ; i
++ ){pCbCr
= pDst
+ pImg
->cbStride
*i
;for( j
=0 ; j
<w
/2 ; j
++ ){*pCbCr
++ = *pCb
++;*pCbCr
++ = *pCr
++;}}return 0;
}vpu
::vpu(int width
,int height
,int Fps
)
{inWidth
=width
;inHeight
=height
;seqBuffer
= (unsigned char *)malloc( MAX_SEQ_BUF_SIZE
);
long long totalSize
= 0;
long long vipTimeStamp
;
int instanceIdx
;
hEnc
= NX_VidEncOpen(NX_AVC_ENC
, &instanceIdx
);
memset( &encInitParam
, 0, sizeof(encInitParam
));
encInitParam
.width
= inWidth
;
encInitParam
.height
= inHeight
;
encInitParam
.gopSize
= 30/2;
encInitParam
.bitrate
= 1000;
encInitParam
.fpsNum
= Fps
;
encInitParam
.fpsDen
= 1;
encInitParam
.chromaInterleave
= 1;encInitParam
.enableRC
= 1;
encInitParam
.disableSkip
= 0;
encInitParam
.maximumQp
= 51;
encInitParam
.initialQp
= 10;
encInitParam
.enableAUDelimiter
= 1;hInImage
= NULL;
hInImage
= NX_VideoAllocateMemory( 16, inWidth
, inHeight
, NX_MEM_MAP_LINEAR
, FOURCC_NV12
);encIn
.timeStamp
= 0;
encIn
.forcedIFrame
= 0;
encIn
.forcedSkipFrame
= 0;
encIn
.quantParam
= 23;
encIn
.pImage
= hInImage
; if (NX_VidEncInit( hEnc
, &encInitParam
) != VID_ERR_NONE
)
{printf("NX_VidEncInit() failed \n");exit(-1);
}printf("NX_VidEncInit() success \n");
NX_VidEncGetSeqInfo( hEnc
, seqBuffer
, &size
);
}char* vpu
::DecodeNV12_To_H264(void *yuv420p
,int *length
)
{LoadImage((uint8_t*)yuv420p
,inWidth
, inHeight
, encIn
.pImage
);NX_VidEncEncodeFrame( hEnc
, &encIn
, &encOut
);*length
=encOut
.bufSize
;char* data
=(char*)encOut
.outBuf
;return data
;
}vpu
::~vpu()
{
}
Vpu.h
#ifndef VPU_H
#define VPU_H#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <math.h>#include <nx_fourcc.h>
#include <nx_vip.h>
#include <nx_dsp.h>
#include <nx_video_api.h> #include "NX_Queue.h"
#include <Util.h>class vpu
{
private:int32_t opt
;int32_t mode
;NX_VID_ENC_HANDLE hEnc
; NX_VID_ENC_INIT_PARAM encInitParam
;NX_VID_MEMORY_HANDLE hMem
; NX_VID_MEMORY_INFO
*hInImage
; uint8_t *pSrcBuf
;int32_t inWidth
;int32_t inHeight
;FILE
*fdOut
;public:int32_t LoadImage( uint8_t *pSrc
, int32_t w
, int32_t h
, NX_VID_MEMORY_INFO
*pImg
);char* DecodeNV12_To_H264(void *nv12
,int *length
);NX_VID_ENC_IN encIn
;NX_VID_ENC_OUT encOut
;unsigned char *seqBuffer
;int size
;vpu(int width
,int height
,int Fps
);~vpu();
};#endif
總結(jié)
以上是生活随笔為你收集整理的【视频处理】嵌入式硬件编码(6818)进行H264编码的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。