#include "DxDecoderWrap.h" DxDecoderWrap::DxDecoderWrap( const DxConfig * cfg ) { m_pDec = NULL; m_bRun = FALSE; m_bPause = FALSE; m_skip = 0; memset( &m_cfg, 0, sizeof( DxDecoderConfig ) ); memset( &m_frames, 0, sizeof( DxGPUFrames ) ); memcpy( &m_cfg.cfg, cfg, sizeof( DxConfig ) ); InitializeCriticalSection( &m_frames.cir ); memset( m_src_data, 0, sizeof( m_src_data ) ); memset( m_dst_data, 0, sizeof( m_dst_data ) ); memset( m_src_linesize, 0, sizeof( m_src_linesize ) ); memset( m_dst_linesize, 0, sizeof( m_dst_linesize ) ); m_img_convert_ctx = NULL; m_out = NULL; m_outSize = 0; return; } DxDecoderWrap::~DxDecoderWrap() { DxCloseDecoder(); DeleteCriticalSection( &m_frames.cir ); if ( NULL != m_img_convert_ctx ) { sws_freeContext( m_img_convert_ctx ); m_img_convert_ctx = NULL; } if ( NULL != m_out ) { free( m_out ); m_out = NULL; } return; } int DxDecoderWrap::DxOpenDecoder( const char * uri, unsigned int skip ) { int ret = 0; if ( NULL != m_pDec ) { return -1; } m_nums = 0; m_skip = skip; m_bReal = FALSE; m_bPause = FALSE; m_frames.size = DX_GPU_FRAME_DEFAULT_SIZE; m_frames.frames = ( DxGPUFrame * )malloc( sizeof( DxGPUFrame ) * m_frames.size ); if ( NULL == m_frames.frames ) { return -1; } memset( m_frames.frames, 0, sizeof( DxGPUFrame ) * m_frames.size ); m_bRun = TRUE; m_cfg.userPtr = this; if ( DX_DECODER_TYPE_CPU == m_cfg.cfg.type ) { m_cfg.escbk = DxCPUDecoderCallback; m_img_convert_ctx = sws_alloc_context(); if ( NULL == m_img_convert_ctx ) { return -1; } } else if ( DX_DECODER_TYPE_CUDA == m_cfg.cfg.type ) { m_cfg.escbk = DxCUDADecoderCallback; } else { return -1; } m_cfg.logcbk = DxDecoderLogCallback; m_pDec = DxDecoderInterface::AllocDecoder( &m_cfg ); if ( NULL == m_pDec ) { m_bRun = FALSE; return -1; } #ifdef _MSC_VER if ( 0 == _memicmp( uri, "rtsp://", strlen( "rtsp://" ) ) ) #else if ( 0 == memicmp( uri, "rtsp://", strlen( "rtsp://" ) ) ) #endif { m_bReal = TRUE; } ret = m_pDec->OpenDecoder( uri ); if ( 0 != ret ) { m_bRun = FALSE; } return ret; } int DxDecoderWrap::DxCloseDecoder() { int pos = 0; m_bRun = FALSE; if ( NULL != m_pDec ) { m_pDec->CloseDecoder(); DxDecoderInterface::FreeDecoder( m_pDec ); // 2018-09-25 m_pDec = NULL; } if ( NULL != m_frames.frames ) { while ( pos < m_frames.size ) { if ( NULL != m_frames.frames[pos].frame ) { if ( DX_DECODER_TYPE_CPU == m_cfg.cfg.type ) { free( m_frames.frames[pos].frame ); m_frames.frames[pos].frame = NULL; } else if ( DX_DECODER_TYPE_CUDA == m_cfg.cfg.type ) { cudaFree( m_frames.frames[pos].frame ); m_frames.frames[pos].frame = NULL; } } pos++; } free( m_frames.frames ); m_frames.frames = NULL; } return 0; } int DxDecoderWrap::DxGetResolution( int * width, int * height ) { if ( 0 == m_frames.width ) { return -1; } if ( width ) { *width = m_frames.width; } if ( height ) { *height = m_frames.height; } return 0; } int DxDecoderWrap::PauseDecoder() { m_bPause = TRUE; return 0; } int DxDecoderWrap::ResumeDecoder() { m_bPause = FALSE; return 0; } BOOL DxDecoderWrap::DxDecoderIsRun() const { return m_bRun; } BOOL DxDecoderWrap::DxFrameIsEmpty() const { return 0 == m_frames.counts; } int DxDecoderWrap::DxLockFrame( DxGPUFrame * frame ) { if ( NULL == frame ) { return -1; } EnterCriticalSection( &m_frames.cir ); if ( NULL == m_frames.frames || 0 == m_frames.frames[m_frames.read].size ) { DxUnlockFrame(); return -1; } frame->width = m_frames.width; frame->height = m_frames.height; frame->size = m_frames.frames[m_frames.read].size; frame->frame = m_frames.frames[m_frames.read].frame; frame->timestamp = m_frames.frames[m_frames.read].timestamp; m_frames.frames[m_frames.read].size = 0; m_frames.read++; m_frames.counts--; if ( m_frames.read == m_frames.size ) { m_frames.read = 0; } return 0; } void DxDecoderWrap::DxUnlockFrame() { LeaveCriticalSection( &m_frames.cir ); return; } int DxDecoderWrap::DxDecoderLogCallback( const void * userPtr, DxLogLevel level, const char * log, unsigned int logLen ) { int index = 0; DxDecoderWrap * pThis = NULL; pThis = ( DxDecoderWrap * )userPtr; if ( NULL == pThis ) { return 0; } if ( DX_LOG_LEVEL_FATAL == level ) { EnterCriticalSection( &pThis->m_frames.cir ); while ( index < pThis->m_frames.size ) { pThis->m_frames.frames[index].size = 0; if ( pThis->m_frames.frames[index].frame ) { if ( DX_DECODER_TYPE_CPU == pThis->m_cfg.cfg.type ) { free( pThis->m_frames.frames[index].frame ); pThis->m_frames.frames[index].frame = NULL; } else if ( DX_DECODER_TYPE_CUDA == pThis->m_cfg.cfg.type ) { cudaFree( pThis->m_frames.frames[index].frame ); pThis->m_frames.frames[index].frame = NULL; } } index++; } LeaveCriticalSection( &pThis->m_frames.cir ); return 0; } if ( DX_LOG_LEVEL_CLEANUP == level ) { //printf( "%s\n", log ); pThis->m_bRun = FALSE; } return 0; } void DxDecoderWrap::DxCUDADecoderCallback( const void * userPtr, void * buf, unsigned int size, unsigned long long timestamp ) { static unsigned int s_dbg = 0; unsigned int rgbSize = 0; DxDecoderWrap * pThis = NULL; cudaError_t cudaStatus = cudaSuccess; pThis = ( DxDecoderWrap * )userPtr; if ( NULL == pThis ) { return; } if ( 0 == size ) { //#ifdef DX_DXDECODER_OUTPUT_NV12 // cuda_common::setColorSpace( 0 == pThis->m_cfg.cfg.colorFmt ? ITU709 : ITU601, 0 ); //#endif if ((DxVideoConfig *)buf == nullptr) { printf(" ( DxVideoConfig * )buf nullptr\n"); return; } pThis->m_frames.width = ( ( DxVideoConfig * )buf )->width; pThis->m_frames.height = ( (DxVideoConfig * )buf )->height; //printf("wrap %d %d\n", pThis->m_frames.width, pThis->m_frames.height); return; } while ( pThis->m_bRun ) { if ( pThis->m_bPause ) { if ( pThis->m_bReal ) { return; } Sleep( 10 ); continue; } break; } if ( !pThis->m_bRun ) { return; } if ( pThis->m_skip > 0 ) { if ( pThis->m_nums % pThis->m_skip ) { pThis->m_nums++; return; } } if ( !pThis->m_bReal ) { while ( pThis->m_frames.size == pThis->m_frames.counts ) { if ( !pThis->m_bRun ) { return; } Sleep( 10 ); } } //#ifdef DX_DXDECODER_OUTPUT_NV12 // rgbSize = pThis->m_frames.width * pThis->m_frames.height * 3 * sizeof( float ); rgbSize = size * pThis->m_frames.height * 1.5 * sizeof(unsigned char); //#endif EnterCriticalSection( &pThis->m_frames.cir ); if ( NULL == pThis->m_frames.frames[pThis->m_frames.write].frame ) { cudaMalloc((void**)&pThis->m_frames.frames[pThis->m_frames.write].frame, rgbSize ); if ( NULL == pThis->m_frames.frames[pThis->m_frames.write].frame ) { LeaveCriticalSection( &pThis->m_frames.cir ); return; } } if ( pThis->m_frames.frames[pThis->m_frames.write].size ) { pThis->m_frames.counts--; pThis->m_frames.frames[pThis->m_frames.write].size = 0; if ( pThis->m_frames.write == pThis->m_frames.read ) { pThis->m_frames.read++; if ( pThis->m_frames.read == pThis->m_frames.size ) { pThis->m_frames.read = 0; } } } LeaveCriticalSection( &pThis->m_frames.cir ); //#ifndef DX_DXDECODER_OUTPUT_NV12 cudaMemcpy(pThis->m_frames.frames[pThis->m_frames.write].frame, buf, size * pThis->m_frames.height * 1.5, cudaMemcpyDeviceToDevice); //#else // cudaStatus = cuda_common::NV12ToRGB( // ( CUdeviceptr )buf, // size, // ( float * )pThis->m_frames.frames[pThis->m_frames.write].frame, // pThis->m_frames.width, // pThis->m_frames.height // ); // if (cudaStatus != cudaSuccess) // { // fprintf(stderr, "cuda_common::NV12ToRGB failed: %s\n", cudaGetErrorString(cudaStatus)); // // return; // } // size = rgbSize; //#endif EnterCriticalSection( &pThis->m_frames.cir ); pThis->m_frames.frames[pThis->m_frames.write].size = size; pThis->m_frames.frames[pThis->m_frames.write].timestamp = timestamp; pThis->m_frames.write++; pThis->m_frames.counts++; if ( pThis->m_frames.write == pThis->m_frames.size ) { pThis->m_frames.write = 0; } pThis->m_nums++; LeaveCriticalSection( &pThis->m_frames.cir ); return; } void DxDecoderWrap::DxCPUDecoderCallback( const void * userPtr, void * buf, unsigned int size, unsigned long long timestamp ) { AVFrame * pFrame = NULL; DxDecoderWrap * pThis = NULL; cudaError_t cudaStatus = cudaSuccess; pThis = ( DxDecoderWrap * )userPtr; if ( NULL == pThis ) { return; } if ( 0 == size ) { pThis->m_frames.width = ( ( DxVideoConfig * )buf )->width; pThis->m_frames.height = ( (DxVideoConfig * )buf )->height; if ( NULL != pThis->m_out ) { free( pThis->m_out ); pThis->m_out = NULL; } pThis->m_outSize = 0; return; } if ( -1 != size ) { return; } pFrame = ( AVFrame * )buf; if ( NULL == pThis->m_out ) { pThis->m_outSize = pThis->m_frames.width * pThis->m_frames.height * 3; pThis->m_out = ( unsigned char * )malloc( pThis->m_outSize ); if ( NULL == pThis->m_out ) { return; } av_opt_show2( pThis->m_img_convert_ctx, stdout, AV_OPT_FLAG_VIDEO_PARAM, 0); av_opt_set_int( pThis->m_img_convert_ctx, "sws_flags", SWS_FAST_BILINEAR | SWS_PRINT_INFO, 0); av_opt_set_int( pThis->m_img_convert_ctx, "srcw", pThis->m_frames.width, 0); av_opt_set_int( pThis->m_img_convert_ctx, "srch", pThis->m_frames.height, 0); av_opt_set_int( pThis->m_img_convert_ctx, "src_format", pFrame->format, 0); av_opt_set_int( pThis->m_img_convert_ctx, "src_range", 1, 0); av_opt_set_int( pThis->m_img_convert_ctx, "dstw", pThis->m_frames.width, 0); av_opt_set_int( pThis->m_img_convert_ctx, "dsth", pThis->m_frames.height, 0); av_opt_set_int( pThis->m_img_convert_ctx, "dst_format", AV_PIX_FMT_BGR24, 0); //AV_PIX_FMT_RGB24 av_opt_set_int( pThis->m_img_convert_ctx, "dst_range", 1, 0); sws_init_context( pThis->m_img_convert_ctx, 0, 0); pThis->m_dst_data[0] = pThis->m_out; pThis->m_dst_linesize[0] = pThis->m_frames.width * 3; } while ( pThis->m_bRun ) { if ( pThis->m_bPause ) { if ( pThis->m_bReal ) { return; } Sleep( 10 ); continue; } break; } if ( !pThis->m_bRun ) { return; } if ( pThis->m_skip > 0 ) { if ( pThis->m_nums % pThis->m_skip ) { pThis->m_nums++; return; } } /* pFrame->data[0] = pFrame->data[0]+pFrame->linesize[0]*(pContext->height-1); pFrame->data[1] = pFrame->data[1]+pFrame->linesize[1]*(pContext->height/2-1 ); pFrame->data[2] = pFrame->data[2]+pFrame->linesize[2]*(pContext->height/2-1 ); pFrame->linesize[0] *= -1; pFrame->linesize[1] *= -1; pFrame->linesize[2] *= -1; */ sws_scale( pThis->m_img_convert_ctx, pFrame->data, pFrame->linesize, 0, pThis->m_frames.height, pThis->m_dst_data, pThis->m_dst_linesize ); if ( !pThis->m_bReal ) { while ( pThis->m_frames.size == pThis->m_frames.counts ) { if ( !pThis->m_bRun ) { return; } Sleep( 10 ); } } EnterCriticalSection( &pThis->m_frames.cir ); if ( NULL == pThis->m_frames.frames[pThis->m_frames.write].frame ) { pThis->m_frames.frames[pThis->m_frames.write].frame = malloc( pThis->m_outSize ); if ( NULL == pThis->m_frames.frames[pThis->m_frames.write].frame ) { LeaveCriticalSection( &pThis->m_frames.cir ); return; } } if ( pThis->m_frames.frames[pThis->m_frames.write].size ) { pThis->m_frames.counts--; pThis->m_frames.frames[pThis->m_frames.write].size = 0; if ( pThis->m_frames.write == pThis->m_frames.read ) { pThis->m_frames.read++; if ( pThis->m_frames.read == pThis->m_frames.size ) { pThis->m_frames.read = 0; } } } LeaveCriticalSection( &pThis->m_frames.cir ); memcpy( pThis->m_frames.frames[pThis->m_frames.write].frame, pThis->m_out, pThis->m_outSize ); EnterCriticalSection( &pThis->m_frames.cir ); pThis->m_frames.frames[pThis->m_frames.write].size = pThis->m_outSize; pThis->m_frames.frames[pThis->m_frames.write].timestamp = timestamp; pThis->m_frames.write++; pThis->m_frames.counts++; if ( pThis->m_frames.write == pThis->m_frames.size ) { pThis->m_frames.write = 0; } pThis->m_nums++; LeaveCriticalSection( &pThis->m_frames.cir ); return; }