Ticket #7214: 0001-Xilinx-NGcodec-hevc-ffmpeg-plugin.patch

File 0001-Xilinx-NGcodec-hevc-ffmpeg-plugin.patch, 230.3 KB (added by Carl Eugen Hoyos, 8 years ago)
  • new file .gitignore

    From b1af22c4b962bccc57129b21c1eebd598f3ee494 Mon Sep 17 00:00:00 2001
    From: John Nichols <jnichol@xilinx.com>
    Date: Fri, 20 Jul 2018 16:53:02 -0700
    Subject: [PATCH] Xilinx NGcodec hevc ffmpeg plugin
    
    ---
     .gitignore                                         |  46 ++
     ffmpeg.c                                           |  32 +-
     libavcodec/Makefile                                |  12 +
     libavcodec/allcodecs.c                             |   2 +
     libavcodec/xlnx_h264/Makefile                      |   4 +
     libavcodec/xlnx_h264/h264e_csregs.c                | 453 +++++++++++
     libavcodec/xlnx_h264/h264e_csregs.h                |  35 +
     libavcodec/xlnx_h264/h264e_csregs_private.h        | 440 +++++++++++
     libavcodec/xlnx_h264/h264e_sdaccel.c               | 875 +++++++++++++++++++++
     libavcodec/xlnx_h264/h264e_sdaccel.h               | 146 ++++
     libavcodec/xlnx_h264/h264e_sdaccel_private.h       | 107 +++
     libavcodec/xlnx_h264/h264e_sdaccel_utils.c         | 290 +++++++
     libavcodec/xlnx_h264/h264e_sdaccel_utils.h         |  29 +
     libavcodec/xlnx_h264/hw_h264.c                     | 105 +++
     libavcodec/xlnx_h264/xlnx_h264_config.h            |  67 ++
     libavcodec/xlnx_h264_enc.c                         | 122 +++
     libavcodec/xlnx_hevc/Makefile                      |   1 +
     libavcodec/xlnx_hevc/hw_hevc.c                     | 363 +++++++++
     libavcodec/xlnx_hevc/xlnx_hevc_config.h            |  50 ++
     libavcodec/xlnx_hevc_enc.c                         | 271 +++++++
     libavcodec/xlnx_hw/Makefile                        |   3 +
     libavcodec/xlnx_hw/common/inc/xcl.h                |  28 +
     libavcodec/xlnx_hw/common/inc/xlnx_hrm.h           |  12 +
     libavcodec/xlnx_hw/common/inc/xlnx_hw_defines.h    |  34 +
     libavcodec/xlnx_hw/common/inc/xlnx_queue.h         |  17 +
     libavcodec/xlnx_hw/common/inc/xlnx_ts_queue.h      |  18 +
     .../xlnx_hw/common/inc/xlnx_types_internal.h       |  49 ++
     libavcodec/xlnx_hw/common/src/xcl.c                | 478 +++++++++++
     libavcodec/xlnx_hw/common/src/xlnx_hrm.c           | 444 +++++++++++
     libavcodec/xlnx_hw/common/src/xlnx_queue.c         |  86 ++
     libavcodec/xlnx_hw/common/src/xlnx_ts_queue.c      | 107 +++
     libavcodec/xlnx_hw/hevc/Makefile                   |   1 +
     libavcodec/xlnx_hw/hevc/enc_vu9p.c                 | 266 +++++++
     libavcodec/xlnx_hw/hevc/enc_vu9p.h                 |   9 +
     libavcodec/xlnx_hw/hevc/enc_vu9p_2c.c              | 793 +++++++++++++++++++
     libavcodec/xlnx_hw/hevc/enc_vu9p_2c.h              |  16 +
     libavcodec/xlnx_hw/hevc/ku115_hevc_enc_config.h    |  13 +
     libavcodec/xlnx_hw/hevc/vu9p_hevc_enc_config.h     |  24 +
     libavcodec/xlnx_hw/xlnx_hw.c                       |  49 ++
     libavcodec/xlnx_hw/xlnx_hw.h                       |  14 +
     libavcodec/xlnx_hw/xlnx_hw_types.h                 |  55 ++
     libavutil/opencl.c                                 |   2 +-
     42 files changed, 5961 insertions(+), 7 deletions(-)
     create mode 100644 .gitignore
     create mode 100644 libavcodec/xlnx_h264/Makefile
     create mode 100644 libavcodec/xlnx_h264/h264e_csregs.c
     create mode 100644 libavcodec/xlnx_h264/h264e_csregs.h
     create mode 100644 libavcodec/xlnx_h264/h264e_csregs_private.h
     create mode 100644 libavcodec/xlnx_h264/h264e_sdaccel.c
     create mode 100644 libavcodec/xlnx_h264/h264e_sdaccel.h
     create mode 100644 libavcodec/xlnx_h264/h264e_sdaccel_private.h
     create mode 100644 libavcodec/xlnx_h264/h264e_sdaccel_utils.c
     create mode 100644 libavcodec/xlnx_h264/h264e_sdaccel_utils.h
     create mode 100644 libavcodec/xlnx_h264/hw_h264.c
     create mode 100644 libavcodec/xlnx_h264/xlnx_h264_config.h
     create mode 100644 libavcodec/xlnx_h264_enc.c
     create mode 100644 libavcodec/xlnx_hevc/Makefile
     create mode 100644 libavcodec/xlnx_hevc/hw_hevc.c
     create mode 100644 libavcodec/xlnx_hevc/xlnx_hevc_config.h
     create mode 100644 libavcodec/xlnx_hevc_enc.c
     create mode 100644 libavcodec/xlnx_hw/Makefile
     create mode 100755 libavcodec/xlnx_hw/common/inc/xcl.h
     create mode 100644 libavcodec/xlnx_hw/common/inc/xlnx_hrm.h
     create mode 100644 libavcodec/xlnx_hw/common/inc/xlnx_hw_defines.h
     create mode 100644 libavcodec/xlnx_hw/common/inc/xlnx_queue.h
     create mode 100644 libavcodec/xlnx_hw/common/inc/xlnx_ts_queue.h
     create mode 100644 libavcodec/xlnx_hw/common/inc/xlnx_types_internal.h
     create mode 100755 libavcodec/xlnx_hw/common/src/xcl.c
     create mode 100644 libavcodec/xlnx_hw/common/src/xlnx_hrm.c
     create mode 100644 libavcodec/xlnx_hw/common/src/xlnx_queue.c
     create mode 100644 libavcodec/xlnx_hw/common/src/xlnx_ts_queue.c
     create mode 100644 libavcodec/xlnx_hw/hevc/Makefile
     create mode 100644 libavcodec/xlnx_hw/hevc/enc_vu9p.c
     create mode 100644 libavcodec/xlnx_hw/hevc/enc_vu9p.h
     create mode 100644 libavcodec/xlnx_hw/hevc/enc_vu9p_2c.c
     create mode 100644 libavcodec/xlnx_hw/hevc/enc_vu9p_2c.h
     create mode 100644 libavcodec/xlnx_hw/hevc/ku115_hevc_enc_config.h
     create mode 100644 libavcodec/xlnx_hw/hevc/vu9p_hevc_enc_config.h
     create mode 100644 libavcodec/xlnx_hw/xlnx_hw.c
     create mode 100755 libavcodec/xlnx_hw/xlnx_hw.h
     create mode 100644 libavcodec/xlnx_hw/xlnx_hw_types.h
    
    diff --git a/.gitignore b/.gitignore
    new file mode 100644
    index 0000000..0736a38
    - +  
     1*.a
     2*.o
     3*.o.*
     4*.d
     5*.def
     6*.dll
     7*.dylib
     8*.exe
     9*.exp
     10*.gcda
     11*.gcno
     12*.h.c
     13*.ilk
     14*.lib
     15*.pc
     16*.pdb
     17*.so
     18*.so.*
     19*.swp
     20*.ver
     21*_g
     22\#*
     23.\#*
     24/.config
     25/.version
     26/ffmpeg
     27/ffplay
     28/ffprobe
     29/ffserver
     30/config.*
     31/coverage.info
     32/avversion.h
     33/lcov/
     34/src
     35/mapfile
     36doc/*
     37bin/*
     38include/*
     39share/*
     40build/*
     41bavcodec/bsf_list.c
     42libavformat/protocol_list.c
     43libavutil/avconfig.h
     44libavutil/ffversion.h
     45libavcodec/bsf_list.c
     46ffmpeg_build/*
  • ffmpeg.c

    diff --git a/ffmpeg.c b/ffmpeg.c
    index ea03179..b0642eb 100644
    a b static void do_video_out(OutputFile *of,  
    11751175    ost->last_dropped = nb_frames == nb0_frames && next_picture;
    11761176
    11771177  /* duplicates frame if needed */
     1178  if (ost->enc_ctx->codec->name) {
     1179      if (0 == strcmp(ost->enc_ctx->codec->name, "xlnx_hevc_enc")) {
     1180          nb_frames = 1;
     1181      }
     1182  }
    11781183  for (i = 0; i < nb_frames; i++) {
    11791184    AVFrame *in_picture;
    11801185    av_init_packet(&pkt);
    static OutputStream *choose_output(void)  
    38003805    int i;
    38013806    int64_t opts_min = INT64_MAX;
    38023807    OutputStream *ost_min = NULL;
    3803 
     3808    uint64_t frames_min = UINT64_MAX;
     3809    static int frame_based = 1;
     3810    int all_valid_ts = 1;
    38043811    for (i = 0; i < nb_output_streams; i++) {
    38053812        OutputStream *ost = output_streams[i];
    38063813        int64_t opts = ost->st->cur_dts == AV_NOPTS_VALUE ? INT64_MIN :
    static OutputStream *choose_output(void)  
    38093816        if (ost->st->cur_dts == AV_NOPTS_VALUE)
    38103817            av_log(NULL, AV_LOG_DEBUG, "cur_dts is invalid (this is harmless if it occurs once at the start per stream)\n");
    38113818
    3812         if (!ost->initialized && !ost->inputs_done)
     3819        if (!ost->initialized && !ost->inputs_done) {
    38133820            return ost;
    3814 
    3815         if (!ost->finished && opts < opts_min) {
    3816             opts_min = opts;
    3817             ost_min  = ost->unavailable ? NULL : ost;
    38183821        }
     3822        if (frame_based && (!strcmp(ost->enc_ctx->codec->name, "xlnx_hevc_enc"))) {
     3823            if (!ost->finished && ost->frames_encoded < frames_min) {
     3824                frames_min = ost->frames_encoded;
     3825                ost_min  = ost->unavailable ? NULL : ost;
     3826            }
     3827            if (opts == INT64_MIN) {
     3828                all_valid_ts = 0;
     3829            }
     3830        } else {
     3831            if (!ost->finished && opts < opts_min) {
     3832                opts_min = opts;
     3833                ost_min  = ost->unavailable ? NULL : ost;
     3834            }
     3835        }
     3836    }
     3837    if (frame_based && all_valid_ts) {
     3838        frame_based = 0;
    38193839    }
    38203840    return ost_min;
    38213841}
  • libavcodec/Makefile

    diff --git a/libavcodec/Makefile b/libavcodec/Makefile
    index 0dd0c7b..64b3cad 100644
    a b OBJS = allcodecs.o \  
    4949       utils.o                                                          \
    5050       vorbis_parser.o                                                  \
    5151       xiph.o                                                           \
     52           xlnx_h264/hw_h264.o                                                                                          \
     53           xlnx_h264/h264e_csregs.o                                                                             \
     54           xlnx_h264/h264e_sdaccel.o                                                                            \
     55           xlnx_h264/h264e_sdaccel_utils.o
    5256
    5357# subsystems
    5458OBJS-$(CONFIG_AANDCTTABLES)            += aandcttab.o
    OBJS-$(CONFIG_PBM_DECODER) += pnmdec.o pnm.o  
    454458OBJS-$(CONFIG_PBM_ENCODER)             += pnmenc.o
    455459OBJS-$(CONFIG_PCX_DECODER)             += pcx.o
    456460OBJS-$(CONFIG_PCX_ENCODER)             += pcxenc.o
     461OBJS-$(CONFIG_XLNX_H264_ENCODER)       += xlnx_h264_enc.o 
    457462OBJS-$(CONFIG_PGM_DECODER)             += pnmdec.o pnm.o
    458463OBJS-$(CONFIG_PGM_ENCODER)             += pnmenc.o
    459464OBJS-$(CONFIG_PGMYUV_DECODER)          += pnmdec.o pnm.o
    OBJS-$(CONFIG_LIBX265_ENCODER) += libx265.o  
    916921OBJS-$(CONFIG_LIBXAVS_ENCODER)            += libxavs.o
    917922OBJS-$(CONFIG_LIBXVID_ENCODER)            += libxvid.o
    918923OBJS-$(CONFIG_LIBZVBI_TELETEXT_DECODER)   += libzvbi-teletextdec.o ass.o
     924OBJS-$(CONFIG_XLNX_HEVC_ENCODER)          += xlnx_hevc_enc.o xlnx_hw/xlnx_hw.o \
     925                                             xlnx_hw/common/src/xlnx_hrm.o \
     926                                             xlnx_hw/common/src/xcl.o \
     927                                             xlnx_hw/common/src/xlnx_queue.o \
     928                                             xlnx_hw/common/src/xlnx_ts_queue.o \
     929                                             xlnx_hw/hevc/enc_vu9p.o \
     930                                             xlnx_hw/hevc/enc_vu9p_2c.o
    919931
    920932# parsers
    921933OBJS-$(CONFIG_AAC_LATM_PARSER)         += latm_parser.o
  • libavcodec/allcodecs.c

    diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
    index 4df4772..a20a76c 100644
    a b static void register_all(void)  
    673673    REGISTER_ENCODER(VP8_VAAPI,         vp8_vaapi);
    674674    REGISTER_DECODER(VP9_CUVID,         vp9_cuvid);
    675675    REGISTER_DECODER(VP9_MEDIACODEC,    vp9_mediacodec);
     676    REGISTER_ENCODER(XLNX_HEVC,         xlnx_hevc);
     677    REGISTER_ENCODER(XLNX_H264,         xlnx_h264);
    676678
    677679    /* parsers */
    678680    REGISTER_PARSER(AAC,                aac);
  • new file libavcodec/xlnx_h264/Makefile

    diff --git a/libavcodec/xlnx_h264/Makefile b/libavcodec/xlnx_h264/Makefile
    new file mode 100644
    index 0000000..7ca5338
    - +  
     1OBJS                            += xlnx_h264/hw_h264.o \
     2                                                                   xlnx_h264/h264e_csregs.o \
     3                                                                   xlnx_h264/h264e_sdaccel.o \
     4                                                                   xlnx_h264/h264e_sdaccel_utils.o
  • new file libavcodec/xlnx_h264/h264e_csregs.c

    diff --git a/libavcodec/xlnx_h264/h264e_csregs.c b/libavcodec/xlnx_h264/h264e_csregs.c
    new file mode 100644
    index 0000000..dd35da0
    - +  
     1/*
     2-- Copyright notice:
     3-- Copyright (c) 2017 Alma Technologies S.A.
     4-- www.alma-technologies.com
     5-- All rights reserved worldwide.
     6
     7-- This copy is made available under the terms of the GNU General Public
     8-- License version 2.1 as published by the Free Software Foundation; either
     9-- version 2.1 of the License, or (at your option) any later version.
     10--
     11-- This copy is distributed in the hope that it will be useful,
     12-- but WITHOUT ANY WARRANTY; without even the implied warranty of
     13-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Please See the GNU
     14-- General Public License for more details.
     15--
     16-- You should have received a copy of the GNU General Public
     17-- License along with FFmpeg; if not, write to the Free Software
     18-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     19*/
     20
     21#include <stdio.h>
     22#include "h264e_csregs.h"
     23#include "h264e_csregs_private.h"
     24
     25void h264eSetControlRegsDefaults(H264E_CFG_PVT* ph264eCFG);
     26void h264eSetReg(uint *puiRegFile, int regOffs, int regFieldHI, int regFieldLO, int regFieldVal);
     27uint h264eGetReg(uint *puiRegFile, int regOffs, int regFieldHI, int regFieldLO);
     28
     29void h264ePrintStatusRegs(int* pRegFile)
     30{
     31    for(int i = 0; i < 64; i++)
     32    {
     33        H264EMSG(printf("H264-E CORE STATUS[0x%.2X] = 0x%.8X\n", i, pRegFile[i]));
     34    }
     35    return;
     36}
     37
     38void h264ePrintControlRegs(int* pRegFile)
     39{
     40    for(int i = 0; i < 64; i++)
     41    {
     42        H264EMSG(printf("CREG[0x%.2X] = 0x%.8X\n", i, pRegFile[i]));
     43    }
     44    return;
     45}
     46
     47int h264eGetNalSize(int* pRegFile)
     48{
     49    return pRegFile[CSREG_PICLEN];
     50}
     51
     52int h264eGetErrorCode(int* pRegFile)
     53{
     54    return pRegFile[CSREG_ERRID];
     55}
     56
     57int h264eGetDbgStatus(int* pRegFile)
     58{
     59    return pRegFile[CSREG_DEBUG];
     60}
     61
     62void h264eSetControlRegs(H264E_USR* ph264eUsr, char* CRegsFile)
     63{
     64    H264E_CFG_PVT  h264eCFGPvt;
     65    H264E_CFG_PVT* ph264eCFG;
     66    if(!ph264eUsr->bUseUserContextAsCfg)
     67    {
     68        ph264eCFG = &h264eCFGPvt;
     69        h264eSetControlRegsDefaults(ph264eCFG);
     70        ph264eCFG->X = ph264eUsr->FrameX;
     71        ph264eCFG->Y = ph264eUsr->FrameY;
     72        if(ph264eUsr->HWOptimizeScanFormat)
     73        {
     74             ph264eCFG->VInputFormat = ph264eUsr->ScanFormat == H264E_MACROBLOCK ? 0 : 2;
     75        }
     76        else
     77        {
     78            ph264eCFG->VInputFormat = ph264eUsr->ScanFormat == H264E_MACROBLOCK       ? 0 :
     79                                      ph264eUsr->ScanFormat == H264E_PLANAR_PACKED    ? 1 :
     80                                      ph264eUsr->ScanFormat == H264E_PLANAR_SEPARATED ? 1 : 2;
     81        }
     82        ph264eCFG->Timescale            = ph264eUsr->Timescale;
     83        ph264eCFG->NUIT                 = ph264eUsr->Nuit;
     84        ph264eCFG->Level                = ph264eUsr->Level;
     85        ph264eCFG->IPeriod              = ph264eUsr->GOPLength         == -1 ? ph264eCFG->IPeriod              : ph264eUsr->GOPLength;
     86        ph264eCFG->IRefColumns          = ph264eUsr->IntraRefreshCol   == -1 ? ph264eCFG->IRefColumns          : ph264eUsr->IntraRefreshCol;
     87        ph264eCFG->nMBRowsInSliceReq    = ph264eUsr->MBRowsPerSlice    == -1 ? ph264eCFG->nMBRowsInSliceReq    : ph264eUsr->MBRowsPerSlice;
     88        ph264eCFG->UseDeBlockingFilter  = ph264eUsr->DeblockingFilter  == -1 ? ph264eCFG->UseDeBlockingFilter  :
     89                                          ph264eUsr->DeblockingFilter  ==  0 ? 0                               :
     90                                          ph264eUsr->DBRestrict        ==  1 ? 2                               : 1;
     91        ph264eCFG->InterMVSliceRestrict = ph264eUsr->MVRestrict        == -1 ? ph264eCFG->InterMVSliceRestrict : (bool)ph264eUsr->MVRestrict;
     92        ph264eCFG->QPI                  = ph264eUsr->QPI               == -1 ? ph264eCFG->QPI                  : ph264eUsr->QPI;
     93        ph264eCFG->QPP                  = ph264eUsr->QPP               == -1 ? ph264eCFG->QPP                  : ph264eUsr->QPP;
     94        ph264eCFG->QPChrOffs            = ph264eUsr->QPChrOffset       == -1 ? ph264eCFG->QPChrOffs            : ph264eUsr->QPChrOffset;
     95        ph264eCFG->Rate                 = ph264eUsr->Bitrate;
     96        ph264eCFG->nMBsInBasicUnit      = ph264eUsr->BUSize            == -1 ? ph264eCFG->nMBsInBasicUnit      : ph264eUsr->BUSize;
     97        ph264eCFG->FIFOSize             = ph264eUsr->RCFIFOSize        == -1 ? ph264eCFG->FIFOSize             : ph264eUsr->RCFIFOSize;
     98        ph264eCFG->bCABAC               = ph264eUsr->UseCABAC          == -1 ? ph264eCFG->bCABAC               : (bool)ph264eUsr->UseCABAC;
     99    }
     100    else
     101    {
     102        ph264eCFG = (H264E_CFG_PVT*)ph264eUsr->UserContext;
     103        if(ph264eUsr->HWOptimizeScanFormat)
     104        {
     105            ph264eCFG->VInputFormat = ph264eUsr->ScanFormat == H264E_MACROBLOCK ? 0 : 2;
     106        }
     107        if(ph264eCFG->VInputFormat == 2 && ph264eCFG->UseFrameBuffer)
     108        {
     109            ph264eCFG->VInputFormat = 3;
     110        }
     111    }
     112    uint vidinres_reg;
     113    uint vidinscan_reg;
     114    uint vidints_reg;
     115    uint vidinuit_reg;
     116    uint vidinlevel_reg;
     117    uint vidinvuist_reg;
     118    uint gopattr_reg;
     119    uint sliceattr_reg;
     120    uint qpsliceattr_reg;
     121    uint rcattr_reg;
     122    uint rcqplims_reg;
     123    uint rcxopts_reg;
     124    uint predattr_reg;
     125    uint encopts_reg;
     126    uint xpredattr_reg;
     127    uint xrcxopts_reg;
     128    uint xrcxopts_pid_reg[5];
     129    uint instruction_reg;
     130    uint xtmemptr_reg;
     131    static const int LevelLUT[52] = {
     132       0, 0, 0, 0, 0, 0, 0, 0,  /*  0-7 */
     133       0, 1, 0, 2,              /*  8-11 */
     134       3, 4, 0, 0, 0, 0, 0, 0,  /* 12-19 */
     135       5, 6, 7, 0, 0, 0, 0, 0,  /* 20-27 */
     136       0, 0, 8, 9,10, 0, 0, 0,  /* 28-35 */
     137       0, 0, 0, 0,11,12,13, 0,  /* 36-43 */
     138       0, 0, 0, 0, 0, 0,14,15   /* 44-51 */
     139    };
     140    vidinres_reg = 0;
     141    h264eSetReg(&vidinres_reg, 0, FRAME_X_HI, FRAME_X_LO, ph264eCFG->X);
     142    h264eSetReg(&vidinres_reg, 0, FRAME_Y_HI, FRAME_Y_LO, ph264eCFG->Y * (ph264eCFG->bInterlaced ? 2 : 1));
     143    vidinscan_reg = 0;
     144#ifdef USE_UHT_CORE
     145    h264eSetReg(&vidinscan_reg, 0, SCAN_FORMAT_HI, SCAN_FORMAT_LO, ph264eCFG->csp);
     146#else
     147    h264eSetReg(&vidinscan_reg, 0, SCAN_FORMAT_HI, SCAN_FORMAT_LO, (ph264eCFG->csp == YUV420 ? ph264eCFG->VInputFormat : 4 + ph264eCFG->VInputFormat));
     148#endif
     149    h264eSetReg(&vidinscan_reg, 0, PSP_HI,         PSP_LO,         ph264eCFG->bpp);
     150    h264eSetReg(&vidinscan_reg, 0, FRAMEDROP_FLAG, FRAMEDROP_FLAG, (int) ph264eCFG->bFrameDrop);
     151    vidints_reg = 0;
     152    h264eSetReg(&vidints_reg, 0, TIMESCALE_HI, TIMESCALE_LO, ph264eCFG->Timescale);
     153    vidinuit_reg = 0;
     154    h264eSetReg(&vidinuit_reg, 0, NUIT_HI, NUIT_LO, ph264eCFG->NUIT);
     155    vidinlevel_reg = 0;
     156    h264eSetReg(&vidinlevel_reg, 0, LEVEL_HI, LEVEL_LO, LevelLUT[ph264eCFG->Level]);
     157    vidinvuist_reg = 0;
     158    h264eSetReg(&vidinvuist_reg, 0, V_VIDEO_SIGNAL_TYPE_PRESENT_FLAG, V_VIDEO_SIGNAL_TYPE_PRESENT_FLAG, (ph264eCFG->VUI_VideoFormat > 0 || ph264eCFG->VUI_VideoFullRangeFlag ? 1 : 0));
     159    h264eSetReg(&vidinvuist_reg, 0, V_VIDEO_FORMAT_HI,                V_VIDEO_FORMAT_LO,                (ph264eCFG->VUI_VideoFormat > 0 ? ph264eCFG->VUI_VideoFormat : 0));
     160    h264eSetReg(&vidinvuist_reg, 0, V_VIDEO_FULL_RANGE_FLAG,          V_VIDEO_FULL_RANGE_FLAG,           ph264eCFG->VUI_VideoFullRangeFlag);
     161    gopattr_reg = 0;
     162    if (ph264eCFG->IPeriod == 0xFFFFFFFF)
     163    {
     164       h264eSetReg(&gopattr_reg, 0, IPERIOD_HI, IPERIOD_LO, 0);
     165    }
     166    else
     167    {
     168       h264eSetReg(&gopattr_reg, 0, IPERIOD_HI, IPERIOD_LO, ph264eCFG->IPeriod);
     169    }
     170    h264eSetReg(&gopattr_reg, 0, IREFCOLS_HI, IREFCOLS_LO, ph264eCFG->IRefColumns);
     171    sliceattr_reg = 0;
     172    h264eSetReg(&sliceattr_reg, 0, SLICE_MBROWS_HI,      SLICE_MBROWS_L0,      ph264eCFG->nMBRowsInSliceReq);
     173    h264eSetReg(&sliceattr_reg, 0, DB_EN_FLAG,           DB_EN_FLAG,           ph264eCFG->UseDeBlockingFilter  > 0 ? 1 : 0);
     174#ifndef USE_UHT_CORE
     175    h264eSetReg(&sliceattr_reg, 0, DB_SLCBNDRS_FLAG,     DB_SLCBNDRS_FLAG,     ph264eCFG->UseDeBlockingFilter == 2 ? 1 : 0);
     176#endif
     177    h264eSetReg(&sliceattr_reg, 0, DB_ALPHA_HI,          DB_ALPHA_LO,          ph264eCFG->sliceAlphaOffset);
     178    h264eSetReg(&sliceattr_reg, 0, DB_BETA_HI,           DB_BETA_LO,           ph264eCFG->sliceBetaOffset);
     179#ifndef USE_UHT_CORE
     180    h264eSetReg(&sliceattr_reg, 0, INTERSLICECROSS_FLAG, INTERSLICECROSS_FLAG, (int) ph264eCFG->InterMVSliceRestrict);
     181#endif
     182    qpsliceattr_reg = 0;
     183    h264eSetReg(&qpsliceattr_reg, 0, QPINIT_I_HI,  QPINIT_I_LO,  ph264eCFG->QPI + ph264eCFG->QpBdOffset);
     184    h264eSetReg(&qpsliceattr_reg, 0, QPINIT_P_HI,  QPINIT_P_LO,  ph264eCFG->QPP + ph264eCFG->QpBdOffset);
     185    h264eSetReg(&qpsliceattr_reg, 0, QPCHROFFS_HI, QPCHROFFS_LO, ph264eCFG->QPChrOffs);
     186    h264eSetReg(&qpsliceattr_reg, 0, QPTHR_HI,     QPTHR_LO,     ph264eCFG->bTQThresholding ? 1 : 0);
     187    rcattr_reg = 0;
     188    h264eSetReg(&rcattr_reg, 0, RCBITRATE_HI,    RCBITRATE_LO,    ph264eCFG->Rate    >> 3);
     189    h264eSetReg(&rcattr_reg, 0, RCMAXBITRATE_HI, RCMAXBITRATE_LO, ph264eCFG->MaxRate >> 3);
     190    rcqplims_reg = 0;
     191    h264eSetReg(&rcqplims_reg, 0, QPI_MIN_HI, QPI_MIN_LO, ph264eCFG->QPI_min + ph264eCFG->QpBdOffset);
     192    h264eSetReg(&rcqplims_reg, 0, QPI_MAX_HI, QPI_MAX_LO, ph264eCFG->QPI_max + ph264eCFG->QpBdOffset);
     193    h264eSetReg(&rcqplims_reg, 0, QPP_MIN_HI, QPP_MIN_LO, ph264eCFG->QPP_min + ph264eCFG->QpBdOffset);
     194    h264eSetReg(&rcqplims_reg, 0, QPP_MAX_HI, QPP_MAX_LO, ph264eCFG->QPP_max + ph264eCFG->QpBdOffset);
     195    rcxopts_reg = 0;
     196    h264eSetReg(&rcxopts_reg, 0, BUSIZE_HI, BUSIZE_LO, (ph264eCFG->nMBsInBasicUnit < 0 ? 0 : ph264eCFG->nMBsInBasicUnit));
     197    if (ph264eCFG->RCMethod == RCM_PID)
     198    {
     199        h264eSetReg(&rcxopts_reg, 0, RCPERIOD_HI, RCPERIOD_LO, ph264eCFG->FIFOSize >> 3);
     200    }
     201    else
     202    {
     203        h264eSetReg(&rcxopts_reg, 0, RCPERIOD_HI, RCPERIOD_LO, ph264eCFG->RCPeriod);
     204    }
     205    encopts_reg = 0;
     206    h264eSetReg(&encopts_reg, 0, CABAC_FLAG,      CABAC_FLAG,      (int) ph264eCFG->bCABAC);
     207    h264eSetReg(&encopts_reg, 0, FLUSHFRAME_FLAG, FLUSHFRAME_FLAG, 1);
     208    h264eSetReg(&encopts_reg, 0, NALTRZWORD_FLAG, NALTRZWORD_FLAG, (ph264eCFG->NALTrZeros == 2 ? 1 : 0));
     209#ifdef USE_UHT_CORE
     210    h264eSetReg(&encopts_reg, 0, ACTCENGS_HI,     ACTCENGS_LO,     (int) ph264eCFG->nCEngines);
     211#endif
     212    predattr_reg = 0;
     213    h264eSetReg(&predattr_reg, 0, MEVBS_P16X16_FLAG, MEVBS_P16X16_FLAG, ph264eCFG->bVBSEnableMask[0]);
     214    h264eSetReg(&predattr_reg, 0, MEVBS_P16X8_FLAG,  MEVBS_P16X8_FLAG,  ph264eCFG->bInterVBSenable & ph264eCFG->bVBSEnableMask[1]);
     215    h264eSetReg(&predattr_reg, 0, MEVBS_P8X16_FLAG,  MEVBS_P8X16_FLAG,  ph264eCFG->bInterVBSenable & ph264eCFG->bVBSEnableMask[2]);
     216    h264eSetReg(&predattr_reg, 0, MEVBS_P8X8_FLAG,   MEVBS_P8X8_FLAG,   ph264eCFG->bInterVBSenable & ph264eCFG->bVBSEnableMask[3]);
     217    h264eSetReg(&predattr_reg, 0, MEPXLAC_HI,        MEPXLAC_LO,        ph264eCFG->InterAccuracy/2);
     218    h264eSetReg(&predattr_reg, 0, XTRACOST_FLAG,     XTRACOST_FLAG,    !ph264eCFG->bVBSOptions[VBS_USE_XTRA_PART_COST]);
     219    h264eSetReg(&predattr_reg, 0, XTRACOSTP8x8_FLAG, XTRACOSTP8x8_FLAG, ph264eCFG->bVBSOptions[VBS_USE_XTRA_PART_COST_P8x8]);
     220    h264eSetReg(&predattr_reg, 0, INTRA_IN_P_FLAG,   INTRA_IN_P_FLAG,   ph264eCFG->bUseIntraInInter);
     221    h264eSetReg(&predattr_reg, 0, I16x16_FLAG,       I16x16_FLAG,      !ph264eCFG->bI16x16Dis);
     222    h264eSetReg(&predattr_reg, 0, I4x4_FLAG,         I4x4_FLAG,        !ph264eCFG->bI4x4Dis);
     223    int i, mask;
     224    for (mask=0, i=0; i<4; i++) mask |= ((int) ph264eCFG->bIntraLuma16x16Mask[i]) << i;
     225    h264eSetReg(&predattr_reg, 0, I16x16_MASK_HI,    I16x16_MASK_LO,    mask);
     226    for (mask=0, i=0; i<4; i++) mask |= ((int) ph264eCFG->bIntraChromaMask[i]) << i;
     227    h264eSetReg(&predattr_reg, 0, ICHR_MASK_HI,      ICHR_MASK_LO,      mask);
     228    for (mask=0, i=0; i<9; i++) mask |= ((int) ph264eCFG->bIntraLuma4x4Mask[i]) << i;
     229    h264eSetReg(&predattr_reg, 0, I4x4_MASK_HI,      I4x4_MASK_LO,      mask);
     230    xpredattr_reg = 0;
     231    h264eSetReg(&xpredattr_reg, 0, SRX_HI,   SRX_LO,   ph264eCFG->InterSearchRangeWidth/8);
     232    h264eSetReg(&xpredattr_reg, 0, SRY_HI,   SRY_LO,   ph264eCFG->InterSearchRangeHeight/2);
     233    h264eSetReg(&xpredattr_reg, 0, VIMPW_HI, VIMPW_LO, ph264eCFG->MPPriorities[0]);
     234    h264eSetReg(&xpredattr_reg, 0, VIMPR_HI, VIMPR_LO, ph264eCFG->MPPriorities[1]);
     235    h264eSetReg(&xpredattr_reg, 0, VOMPW_HI, VOMPW_LO, ph264eCFG->MPPriorities[2]);
     236    h264eSetReg(&xpredattr_reg, 0, REFWR_HI, REFWR_LO, ph264eCFG->MPPriorities[3]);
     237    xrcxopts_reg = 0;
     238    h264eSetReg(&xrcxopts_reg, 0, QPADJSTRENGTH_HI,  QPADJSTRENGTH_LO,  ph264eCFG->AQStrength);
     239    h264eSetReg(&xrcxopts_reg, 0, USEINITQP_FLAG,    USEINITQP_FLAG,    ph264eCFG->bRcExtraOpt[0]);
     240    h264eSetReg(&xrcxopts_reg, 0, USESCENECUT_FLAG,  USESCENECUT_FLAG,  ph264eCFG->bRcExtraOpt[1]);
     241    h264eSetReg(&xrcxopts_reg, 0, USERCOVERDUE_FLAG, USERCOVERDUE_FLAG, ph264eCFG->bRcExtraOpt[2]);
     242    h264eSetReg(&xrcxopts_reg, 0, STRICTCBR_FLAG,    STRICTCBR_FLAG,    ph264eCFG->bRcExtraOpt[3]);
     243    h264eSetReg(&xrcxopts_reg, 0, DISMADTH_FLAG,     DISMADTH_FLAG,     ph264eCFG->bRcExtraOpt[4]);
     244    h264eSetReg(&xrcxopts_reg, 0, VBRF_HI,           VBRF_LO,           ph264eCFG->rcVbrFactor);
     245    h264eSetReg(&xrcxopts_reg, 0, ICPBRDFR_HI,       ICPBRDFR_LO,       ph264eCFG->initialCbpRdInfr);
     246    for (int i=0; i<5; i++)
     247    {
     248        xrcxopts_pid_reg[i] = ph264eCFG->xrcxopts_pid[i];
     249    }
     250    instruction_reg = 0;
     251    h264eSetReg(&instruction_reg, 0, SWCLR_FLAG,     SWCLR_FLAG,     0);
     252    h264eSetReg(&instruction_reg, 0, SWSUSPEND_FLAG, SWSUSPEND_FLAG, 0);
     253    xtmemptr_reg = 0;
     254    h264eSetReg(&xtmemptr_reg, 0, XTMEMPTR_HI, XTMEMPTR_LO, ph264eCFG->XtmemPtr);
     255    h264eSetReg((uint*)CRegsFile, CSREG_VIDINRES,      31, 0, vidinres_reg);
     256    h264eSetReg((uint*)CRegsFile, CSREG_VIDINSCAN,     31, 0, vidinscan_reg);
     257    h264eSetReg((uint*)CRegsFile, CSREG_VIDINTS,       31, 0, vidints_reg);
     258    h264eSetReg((uint*)CRegsFile, CSREG_VIDINUIT,      31, 0, vidinuit_reg);
     259    h264eSetReg((uint*)CRegsFile, CSREG_VIDINLEVEL,    31, 0, vidinlevel_reg);
     260    h264eSetReg((uint*)CRegsFile, CSREG_VIDINVUIST,    31, 0, vidinvuist_reg);
     261    h264eSetReg((uint*)CRegsFile, CSREG_GOPATTR,       31, 0, gopattr_reg);
     262    h264eSetReg((uint*)CRegsFile, CSREG_SLICEATTR,     31, 0, sliceattr_reg);
     263    h264eSetReg((uint*)CRegsFile, CSREG_QPSLICEATTR,   31, 0, qpsliceattr_reg);
     264    h264eSetReg((uint*)CRegsFile, CSREG_RCATTR,        31, 0, rcattr_reg);
     265    h264eSetReg((uint*)CRegsFile, CSREG_RCQPLIMS,      31, 0, rcqplims_reg);
     266    h264eSetReg((uint*)CRegsFile, CSREG_RCXOPTS,       31, 0, rcxopts_reg);
     267    h264eSetReg((uint*)CRegsFile, CSREG_PREDATTR,      31, 0, predattr_reg);
     268    h264eSetReg((uint*)CRegsFile, CSREG_ENCOPTS,       31, 0, encopts_reg);
     269    h264eSetReg((uint*)CRegsFile, CSREG_XPREDATTR,     31, 0, xpredattr_reg);
     270    h264eSetReg((uint*)CRegsFile, CSREG_XRCXOPTS,      31, 0, xrcxopts_reg);
     271    h264eSetReg((uint*)CRegsFile, CSREG_INSTRUCTION,   31, 0, instruction_reg);
     272    h264eSetReg((uint*)CRegsFile, CSREG_XTMEMPTR,      31, 0, xtmemptr_reg);
     273    h264eSetReg((uint*)CRegsFile, CSREG_XRCXOPTS_PID0, 31, 0, xrcxopts_pid_reg[0]);
     274    h264eSetReg((uint*)CRegsFile, CSREG_XRCXOPTS_PID1, 31, 0, xrcxopts_pid_reg[1]);
     275    h264eSetReg((uint*)CRegsFile, CSREG_XRCXOPTS_PID2, 31, 0, xrcxopts_pid_reg[2]);
     276    h264eSetReg((uint*)CRegsFile, CSREG_XRCXOPTS_PID3, 31, 0, xrcxopts_pid_reg[3]);
     277    h264eSetReg((uint*)CRegsFile, CSREG_XRCXOPTS_PID4, 31, 0, xrcxopts_pid_reg[4]);
     278    if(ph264eCFG->PrintControlRegisters)
     279    {
     280        h264ePrintControlRegs((int*)CRegsFile);
     281    }
     282    return;
     283}
     284
     285void h264eSetControlRegsDefaults(H264E_CFG_PVT* ph264eCFG)
     286{
     287    ph264eCFG->X                      = 1280;
     288    ph264eCFG->Y                      = 720;
     289    ph264eCFG->bInterlaced            = false;
     290    ph264eCFG->VInputFormat           = VIPLANAR;
     291    ph264eCFG->bpp                    = 8;
     292    ph264eCFG->csp                    = YUV420;
     293    ph264eCFG->Timescale              = 50000;
     294    ph264eCFG->NUIT                   = 1000;
     295    ph264eCFG->Level                  = 31;
     296    ph264eCFG->QPI                    = 25;
     297    ph264eCFG->QPP                    = 25;
     298    ph264eCFG->QPChrOffs              = 0;
     299    ph264eCFG->QpBdOffset             = 0;
     300    ph264eCFG->bTQThresholding        = true;
     301    ph264eCFG->UseDeBlockingFilter    = 1;
     302    ph264eCFG->sliceAlphaOffset       = 0;
     303    ph264eCFG->sliceBetaOffset        = 0;
     304    ph264eCFG->nMBRowsInSliceReq      = 0;
     305    ph264eCFG->InterSearchRangeWidth  = 32;
     306    ph264eCFG->InterSearchRangeHeight = 20;
     307    ph264eCFG->InterAccuracy          = 4;
     308    ph264eCFG->InterMVSliceRestrict   = false;
     309    ph264eCFG->bInterVBSenable        = true;
     310    ph264eCFG->bUseIntraInInter       = true;
     311    ph264eCFG->NALTrZeros             = 0;
     312    ph264eCFG->NALFlushOnFrame        = 1;
     313    ph264eCFG->bFrameDrop             = false;
     314    ph264eCFG->VUI_VideoFormat        = -1;
     315    ph264eCFG->VUI_VideoFullRangeFlag = 0;
     316#ifdef USE_CABAC
     317    ph264eCFG->bCABAC                 = true;
     318#else
     319    ph264eCFG->bCABAC                 = false;
     320#endif
     321    ph264eCFG->AQStrength             = 4;
     322    ph264eCFG->XtmemPtr               = 0;
     323    ph264eCFG->nCEngines              = 1;
     324    ph264eCFG->MPPriorities[0]        = 3;
     325    ph264eCFG->MPPriorities[1]        = 2;
     326    ph264eCFG->MPPriorities[2]        = 1;
     327    ph264eCFG->MPPriorities[3]        = 1;
     328    ph264eCFG->Rate                   = 0;
     329    ph264eCFG->FIFOSize               = 0;
     330    ph264eCFG->MaxRate                = 0;
     331    ph264eCFG->nMBsInBasicUnit        = 0;
     332    ph264eCFG->RCPeriod               = 0;
     333    ph264eCFG->QPI_min                = 0;
     334    ph264eCFG->QPI_max                = 51;
     335    ph264eCFG->QPP_min                = 0;
     336    ph264eCFG->QPP_max                = 51;
     337    ph264eCFG->IPeriod                = 30;
     338    ph264eCFG->IRefColumns            = 0;
     339    ph264eCFG->RCMethod               = RCM_PID;
     340    ph264eCFG->initialCbpRdInfr       = 0;
     341    ph264eCFG->rcVbrFactor            = 16;
     342    for (int i = 1; i < RC_EXTRA_OPT_MASK_WIDTH; i++)
     343    {
     344        ph264eCFG->bRcExtraOpt[i] = false;
     345    }
     346    for(int i = 0; i < 7; i++)
     347    {
     348        if(i < 4)
     349        {
     350            ph264eCFG->bVBSEnableMask[i] = true;
     351        }
     352        else
     353        {
     354            ph264eCFG->bVBSEnableMask[i] = false;
     355        }
     356        if(i < 5)
     357        {
     358            ph264eCFG->bVBSOptions[i] = true;
     359        }
     360        else
     361        {
     362            ph264eCFG->bVBSOptions[i] = false;
     363        }
     364    }
     365    ph264eCFG->bVBSOptions[3] = false;
     366    ph264eCFG->bI16x16Dis     = 0;
     367    ph264eCFG->bI4x4Dis       = false;
     368    for(int i = 0; i < 9; i++)
     369    {
     370        if(i < 4)
     371        {
     372            ph264eCFG->bIntraLuma16x16Mask[i] = true;
     373            ph264eCFG->bIntraChromaMask[i]    = true;
     374        }
     375        ph264eCFG->bIntraLuma4x4Mask[i] = true;
     376    }
     377    h264eSetReg(&ph264eCFG->xrcxopts_pid[0], 0, PID_KU_IONPY_HI,             PID_KU_IONPY_LO,              PID_KU_IONPY);
     378    h264eSetReg(&ph264eCFG->xrcxopts_pid[0], 0, PID_KU_IP_HI,                PID_KU_IP_LO,                 PID_KU_IP);
     379    h264eSetReg(&ph264eCFG->xrcxopts_pid[0], 0, PID_KI_UPD_IONPY_HI,         PID_KI_UPD_IONPY_LO,          PID_KI_UPD_IONPY);
     380    h264eSetReg(&ph264eCFG->xrcxopts_pid[0], 0, PID_KI_UPD_IP_HI,            PID_KI_UPD_IP_LO,             PID_KI_UPD_IP);
     381    h264eSetReg(&ph264eCFG->xrcxopts_pid[0], 0, PID_USE_IBU_THR_FLAG,        PID_USE_IBU_THR_FLAG,         PID_USE_IBU_THR);
     382    h264eSetReg(&ph264eCFG->xrcxopts_pid[0], 0, PID_FIFO_STATUS_TARGET_HI,   PID_FIFO_STATUS_TARGET_LO,    PID_FIFO_STATUS_TARGET);
     383    h264eSetReg(&ph264eCFG->xrcxopts_pid[1], 0, PID_USE_COLOCATED_FLAG,      PID_USE_COLOCATED_FLAG,       PID_USE_COLOCATED);
     384    h264eSetReg(&ph264eCFG->xrcxopts_pid[1], 0, PID_IFRAME_BUFFER_FACTOR_HI, PID_IFRAME_BUFFER_FACTOR_LO,  PID_IFRAME_BUFFER_FACTOR);
     385    h264eSetReg(&ph264eCFG->xrcxopts_pid[1], 0, PID_QP_STEP_FR_HI,           PID_QP_STEP_FR_LO,            PID_QP_STEP_FR);
     386    h264eSetReg(&ph264eCFG->xrcxopts_pid[1], 0, PID_QP_STEP_IBU_HI,          PID_QP_STEP_IBU_LO,           PID_QP_STEP_IBU);
     387    h264eSetReg(&ph264eCFG->xrcxopts_pid[1], 0, PID_FSTATUS_0_HI,            PID_FSTATUS_0_LO,             PID_FSTATUS_0);
     388    h264eSetReg(&ph264eCFG->xrcxopts_pid[1], 0, PID_THRFRMLIM_0_FLAG,        PID_THRFRMLIM_0_FLAG,         PID_THRFRMLIM_0);
     389    h264eSetReg(&ph264eCFG->xrcxopts_pid[1], 0, PID_FSTATUS_1_HI,            PID_FSTATUS_1_LO,             PID_FSTATUS_1);
     390    h264eSetReg(&ph264eCFG->xrcxopts_pid[1], 0, PID_THRFRMLIM_1_FLAG,        PID_THRFRMLIM_1_FLAG,         PID_THRFRMLIM_1);
     391    h264eSetReg(&ph264eCFG->xrcxopts_pid[2], 0, PID_FSTATUS_2_HI,            PID_FSTATUS_2_LO,             PID_FSTATUS_2);
     392    h264eSetReg(&ph264eCFG->xrcxopts_pid[2], 0, PID_THRFRMLIM_2_FLAG,        PID_THRFRMLIM_2_FLAG,         PID_THRFRMLIM_2);
     393    h264eSetReg(&ph264eCFG->xrcxopts_pid[2], 0, PID_FSTATUS_3_HI,            PID_FSTATUS_3_LO,             PID_FSTATUS_3);
     394    h264eSetReg(&ph264eCFG->xrcxopts_pid[2], 0, PID_THRFRMLIM_3_FLAG,        PID_THRFRMLIM_3_FLAG,         PID_THRFRMLIM_3);
     395    h264eSetReg(&ph264eCFG->xrcxopts_pid[2], 0, PID_FSTATUS_4_HI,            PID_FSTATUS_4_LO,             PID_FSTATUS_4);
     396    h264eSetReg(&ph264eCFG->xrcxopts_pid[2], 0, PID_THRFRMLIM_4_FLAG,        PID_THRFRMLIM_4_FLAG,         PID_THRFRMLIM_4);
     397    h264eSetReg(&ph264eCFG->xrcxopts_pid[2], 0, PID_QP_STEP_0_HI,            PID_QP_STEP_0_LO,             PID_QP_STEP_0);
     398    h264eSetReg(&ph264eCFG->xrcxopts_pid[2], 0, PID_QP_THR_0_HI,             PID_QP_THR_0_LO,              PID_QP_THR_0);
     399    h264eSetReg(&ph264eCFG->xrcxopts_pid[3], 0, PID_QP_STEP_1_HI,            PID_QP_STEP_1_LO,             PID_QP_STEP_1);
     400    h264eSetReg(&ph264eCFG->xrcxopts_pid[3], 0, PID_QP_THR_1_HI,             PID_QP_THR_1_LO,              PID_QP_THR_1);
     401    h264eSetReg(&ph264eCFG->xrcxopts_pid[3], 0, PID_QP_STEP_2_HI,            PID_QP_STEP_2_LO,             PID_QP_STEP_2);
     402    h264eSetReg(&ph264eCFG->xrcxopts_pid[3], 0, PID_QP_THR_2_HI,             PID_QP_THR_2_LO,              PID_QP_THR_2);
     403    h264eSetReg(&ph264eCFG->xrcxopts_pid[3], 0, PID_QP_STEP_3_HI,            PID_QP_STEP_3_LO,             PID_QP_STEP_3);
     404    h264eSetReg(&ph264eCFG->xrcxopts_pid[3], 0, PID_QP_THR_3_HI,             PID_QP_THR_3_LO,              PID_QP_THR_3);
     405    h264eSetReg(&ph264eCFG->xrcxopts_pid[3], 0, PID_QP_STEP_4_HI,            PID_QP_STEP_4_LO,             PID_QP_STEP_4);
     406    h264eSetReg(&ph264eCFG->xrcxopts_pid[3], 0, PID_QP_THR_4_HI,             PID_QP_THR_4_LO,              PID_QP_THR_4);
     407    h264eSetReg(&ph264eCFG->xrcxopts_pid[4], 0, PID_RAMP_METHOD_HI,          PID_RAMP_METHOD_LO,           PID_RAMP_METHOD);
     408    h264eSetReg(&ph264eCFG->xrcxopts_pid[4], 0, PID_USE_KD_FLAG,             PID_USE_KD_FLAG,              PID_USE_KD);
     409    h264eSetReg(&ph264eCFG->xrcxopts_pid[4], 0, PID_USE_KI_UPD_FLAG,         PID_USE_KI_UPD_FLAG,          PID_USE_KI_UPD);
     410    h264eSetReg(&ph264eCFG->xrcxopts_pid[4], 0, PID_USE_KI_UPDM_FLAG,        PID_USE_KI_UPDM_FLAG,         PID_USE_KI_UPDM);
     411    h264eSetReg(&ph264eCFG->xrcxopts_pid[4], 0, PID_USE_SCENE_THR_FLAG,      PID_USE_SCENE_THR_FLAG,       PID_USE_SCENE_THR);
     412    h264eSetReg(&ph264eCFG->xrcxopts_pid[4], 0, PID_USE_AVG_QP_THR_FLAG,     PID_USE_AVG_QP_THR_FLAG,      PID_USE_AVG_QP_THR);
     413    h264eSetReg(&ph264eCFG->xrcxopts_pid[4], 0, PID_AVG_QP_THR_HI,           PID_AVG_QP_THR_LO,            PID_AVG_QP_THR);
     414    h264eSetReg(&ph264eCFG->xrcxopts_pid[4], 0, PID_SCENE_THR_HI,            PID_SCENE_THR_LO,             PID_SCENE_THR);
     415    return;
     416}
     417
     418void h264eSetReg(uint      *puiRegFile,
     419                 int        regOffs,
     420                 int        regFieldHI,
     421                 int        regFieldLO,
     422                 int        regFieldVal)
     423{
     424    uint FieldMask;
     425    uint regVal;
     426    uint regFieldValP;
     427    FieldMask      = 0xFFFFFFFF;
     428    FieldMask    >>= ((8*sizeof(uint)) - (regFieldHI - regFieldLO + 1));
     429    regFieldValP   = regFieldVal & FieldMask;
     430    FieldMask    <<= regFieldLO;
     431    regFieldValP <<= regFieldLO;
     432    FieldMask      = ~FieldMask;
     433    regVal         = puiRegFile[regOffs];
     434    regVal        &= FieldMask;
     435    regVal        |= regFieldValP;
     436    puiRegFile[regOffs] = regVal;
     437    return;
     438}
     439
     440uint h264eGetReg(uint *puiRegFile,
     441                 int   regOffs,
     442                 int   regFieldHI,
     443                 int   regFieldLO)
     444{
     445    uint retval;
     446    uint FieldMask;
     447    FieldMask     = 0xFFFFFFFF;
     448    FieldMask   >>= ((8*sizeof(uint)) - (regFieldHI - regFieldLO + 1));
     449    retval        = puiRegFile[regOffs];
     450    retval      >>= regFieldLO;
     451    retval       &= FieldMask;
     452    return retval;
     453}
  • new file libavcodec/xlnx_h264/h264e_csregs.h

    diff --git a/libavcodec/xlnx_h264/h264e_csregs.h b/libavcodec/xlnx_h264/h264e_csregs.h
    new file mode 100644
    index 0000000..43556b1
    - +  
     1/*
     2-- Copyright notice:
     3-- Copyright (c) 2017 Alma Technologies S.A.
     4-- www.alma-technologies.com
     5-- All rights reserved worldwide.
     6
     7-- This copy is made available under the terms of the GNU General Public
     8-- License version 2.1 as published by the Free Software Foundation; either
     9-- version 2.1 of the License, or (at your option) any later version.
     10--
     11-- This copy is distributed in the hope that it will be useful,
     12-- but WITHOUT ANY WARRANTY; without even the implied warranty of
     13-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Please See the GNU
     14-- General Public License for more details.
     15--
     16-- You should have received a copy of the GNU General Public
     17-- License along with FFmpeg; if not, write to the Free Software
     18-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     19*/
     20
     21#ifndef _H264E_SDACCEL_CSREGS_H_
     22#define _H264E_SDACCEL_CSREGS_H_
     23
     24#include "h264e_sdaccel.h"
     25
     26void h264eSetControlRegs   (H264E_USR* ph264eUsr, char* CRegsFile);
     27void h264ePrintStatusRegs  (int* pRegFile);
     28void h264ePrintControlRegs (int* pRegFile);
     29int  h264eGetNalSize       (int* pRegFile);
     30int  h264eGetErrorCode     (int* pRegFile);
     31int  h264eGetDbgStatus     (int* pRegFile);
     32
     33#endif // _H264E_SDACCEL_CSREGS_H_
     34
     35
  • new file libavcodec/xlnx_h264/h264e_csregs_private.h

    diff --git a/libavcodec/xlnx_h264/h264e_csregs_private.h b/libavcodec/xlnx_h264/h264e_csregs_private.h
    new file mode 100644
    index 0000000..64e796b
    - +  
     1/*
     2-- Copyright notice:
     3-- Copyright (c) 2017 Alma Technologies S.A.
     4-- www.alma-technologies.com
     5-- All rights reserved worldwide.
     6
     7-- This copy is made available under the terms of the GNU General Public
     8-- License version 2.1 as published by the Free Software Foundation; either
     9-- version 2.1 of the License, or (at your option) any later version.
     10--
     11-- This copy is distributed in the hope that it will be useful,
     12-- but WITHOUT ANY WARRANTY; without even the implied warranty of
     13-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Please See the GNU
     14-- General Public License for more details.
     15--
     16-- You should have received a copy of the GNU General Public
     17-- License along with FFmpeg; if not, write to the Free Software
     18-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     19*/
     20
     21#ifndef _H264E_CSREGS_PRIVATE_H_
     22#define _H264E_CSREGS_PRIVATE_H_
     23
     24#include <stdbool.h>
     25
     26typedef unsigned int uint;
     27
     28typedef struct _QPs {
     29
     30   int QPIPic;
     31   int QPPPic;
     32   int dQPISlice;
     33   int dQPPSlice;
     34   int dQPIMB;
     35   int dQPPMB;
     36   int QPEffectiveI;
     37   int QPEffectiveP;
     38   int QpBdOffset;
     39
     40} QPs;
     41
     42#define RC_EXTRA_OPT_MASK_WIDTH 5
     43
     44typedef struct _H264E_CFG_PVT {
     45
     46   int      X;
     47   int      Y;
     48   int      nMBRowsInSlice;
     49   int      nMBRowsInSliceReq;
     50   int      QPI;
     51   int      QPP;
     52   int      QPChrOffs;
     53   int      QpBdOffset;
     54   bool     bTQThresholding;
     55   unsigned IPeriod;
     56   unsigned IRefColumns;
     57   int      UseDeBlockingFilter;
     58   int      sliceAlphaOffset;
     59   int      sliceBetaOffset;
     60   float    FrameRate;
     61   unsigned Timescale;
     62   unsigned NUIT;
     63   int      nMBsInBasicUnit;
     64   unsigned RCMethod;
     65   int      RCPeriod;
     66   int      Rate;
     67   int      MaxRate;
     68   int      FIFOSize;
     69   int      QPI_min;
     70   int      QPI_max;
     71   int      QPP_min;
     72   int      QPP_max;
     73   int      FramesToBeEncoded;
     74   bool     bInputFromPipe;
     75   int      pipeType;
     76   int      InterSearchAlgorithm;
     77   int      InterSearchRangeWidth;
     78   int      InterSearchRangeHeight;
     79   int      InterSRWOriginPolicy;
     80   int      InterAccuracy;
     81   int      InterQPELWindow;
     82   int      InterPSKIPPolicy;
     83   int      InterSADBits;
     84   bool     InterMVSliceRestrict;
     85   int      InterIMENeighborA;
     86   int      InterFMENeighborA;
     87   int      MPPriorities[4];
     88   bool     bInterUseP0;
     89   bool     bInterQP2S;
     90   bool     bInterVBSenable;
     91   bool     bVBSEnableMask[7];
     92   bool     bVBSOptions[7];
     93   int      bI16x16Dis;
     94   bool     bIntraLuma16x16Mask[4];
     95   bool     bI4x4Dis;
     96   bool     bIntraLuma4x4Mask[9];
     97   bool     bIntraChromaMask[4];
     98   bool     bUseIntraInInter;
     99   bool     bForceIPCMInIntra;
     100   int      NALTrZeros;
     101   int      NALFlushOnFrame;
     102   bool     bFrameDrop;
     103   QPs      h264eQPs;
     104   int      VInputFormat;
     105   int      bpp;
     106   int      csp;
     107   int      subWidthC;
     108   int      subHeightC;
     109   int      endianess;
     110   int      Level;
     111   unsigned XtmemPtr;
     112   int      TBA;
     113   bool     TBASMask[9];
     114   void*    pPFIFile;
     115   char     cClipInfo[2048];
     116   int      Profile;
     117   bool     bCABAC;
     118   bool     bInterlaced;
     119   bool     bIsTopFieldYUV;
     120   bool     bBatch;
     121   bool     bRcExtraOpt[RC_EXTRA_OPT_MASK_WIDTH];
     122   char     rcExtraOpt[512];
     123   unsigned rcVbrFactor;
     124   unsigned estatsLevel;
     125   char     rcRegsFileName[512];
     126   FILE*    rcRegsFile;
     127   bool     bUseSMAPData;
     128   bool     bHrdEnable;
     129   bool     bCbr;
     130   uint     cpbSizeInKbps;
     131   uint     initialCbpRdIn90Khz;
     132   uint     initialCbpRdInfr;
     133   bool     bRcHrd;
     134   int      AQStrength;
     135   uint     xrcxopts_pid[5];
     136   bool     bDumpIOFrames;
     137   uint     nNALOutWidth;
     138   uint     nCEngines;
     139   uint     YSecNomPad16;
     140   int      TBDBG;
     141   int      VUI_VideoFormat;
     142   int      VUI_VideoFullRangeFlag;
     143   int      UseHW;
     144   char     KernelFile[2048];
     145   char     TargetDevice[2048];
     146   char     KernelName[2048];
     147   FILE*    pYUVFile;
     148   int      UsePlanarSeparated;
     149   int      PackPlanarSeparated;
     150   int      PlanarToInterleavedInHW;
     151   int      HWBench;
     152   int      UseFrameBuffer;
     153   int      FrameOffset;
     154   int      PrintControlRegisters;
     155
     156} H264E_CFG_PVT;
     157
     158#define CSREG_VIDINRES      0x00
     159#define CSREG_VIDINSCAN     0x01
     160#define CSREG_VIDINTS       0x02
     161#define CSREG_VIDINUIT      0x03
     162#define CSREG_VIDINLEVEL    0x04
     163#define CSREG_VIDINVUIST    0x05
     164#define CSREG_GOPATTR       0x10
     165#define CSREG_SLICEATTR     0x11
     166#define CSREG_QPSLICEATTR   0x12
     167#define CSREG_RCATTR        0x13
     168#define CSREG_RCQPLIMS      0x14
     169#define CSREG_RCXOPTS       0x15
     170#define CSREG_PREDATTR      0x16
     171#define CSREG_ENCOPTS       0x17
     172#define CSREG_XPREDATTR     0x3F
     173#define CSREG_XRCXOPTS      0x3E
     174#define CSREG_COREVER       0x3D
     175#define CSREG_CORECFG       0x3C
     176#define CSREG_XRCXOPTS_PID0 0x3B
     177#define CSREG_XRCXOPTS_PID1 0x3A
     178#define CSREG_XRCXOPTS_PID2 0x39
     179#define CSREG_XRCXOPTS_PID3 0x38
     180#define CSREG_XRCXOPTS_PID4 0x37
     181#define CSREG_RCSTATUS      0x36
     182#define CSREG_INSTRUCTION   0x20
     183#define CSREG_STATUS        0x21
     184#define CSREG_ERRID         0x22
     185#define CSREG_IDRCNT        0x23
     186#define CSREG_FRAMECNT      0x24
     187#define CSREG_SEQLEN        0x25
     188#define CSREG_PICLEN        0x26
     189#define CSREG_SLICELEN      0x27
     190#define CSREG_FRAMEDROPCNT  0x28
     191#define CSREG_XTMEMPTR      0x30
     192#define CSREG_DEBUG         0x3F
     193#define FRAME_X_LO      0
     194#define FRAME_X_HI     15
     195#define FRAME_Y_LO     16
     196#define FRAME_Y_HI     31
     197#define SCAN_FORMAT_LO  0
     198#define SCAN_FORMAT_HI  3
     199#define PSP_LO          4
     200#define PSP_HI          7
     201#define FRAMEDROP_FLAG 16
     202#define TIMESCALE_LO    0
     203#define TIMESCALE_HI   31
     204#define NUIT_LO         0
     205#define NUIT_HI        31
     206#define LEVEL_LO        0
     207#define LEVEL_HI        4
     208#define V_VIDEO_SIGNAL_TYPE_PRESENT_FLAG 0
     209#define V_VIDEO_FORMAT_LO                4
     210#define V_VIDEO_FORMAT_HI                7
     211#define V_VIDEO_FULL_RANGE_FLAG          8
     212#define IPERIOD_LO   0
     213#define IPERIOD_HI  15
     214#define IREFCOLS_LO 16
     215#define IREFCOLS_HI 31
     216#define SLICE_MBROWS_L0       0
     217#define SLICE_MBROWS_HI      15
     218#define DB_EN_FLAG           16
     219#define DB_SLCBNDRS_FLAG     17
     220#define DB_ALPHA_LO          20
     221#define DB_ALPHA_HI          23
     222#define DB_BETA_LO           24
     223#define DB_BETA_HI           27
     224#define INTERSLICECROSS_FLAG 28
     225#define QPINIT_I_LO      0
     226#define QPINIT_I_HI      7
     227#define QPINIT_P_LO      8
     228#define QPINIT_P_HI     15
     229#define QPCHROFFS_LO    16
     230#define QPCHROFFS_HI    23
     231#define QPTHR_LO        24
     232#define QPTHR_HI        25
     233#define RCBITRATE_LO     0
     234#define RCBITRATE_HI    15
     235#define RCMAXBITRATE_LO 16
     236#define RCMAXBITRATE_HI 31
     237#define QPI_MIN_LO       0
     238#define QPI_MIN_HI       7
     239#define QPI_MAX_LO       8
     240#define QPI_MAX_HI      15
     241#define QPP_MIN_LO      16
     242#define QPP_MIN_HI      23
     243#define QPP_MAX_LO      24
     244#define QPP_MAX_HI      31
     245#define BUSIZE_LO        0
     246#define BUSIZE_HI       15
     247#define RCPERIOD_LO     16
     248#define RCPERIOD_HI     31
     249#define CABAC_FLAG       0
     250#define FLUSHFRAME_FLAG  4
     251#define NALTRZWORD_FLAG  8
     252#define ACTCENGS_LO     12
     253#define ACTCENGS_HI     15
     254#define MEVBS_P16X16_FLAG  0
     255#define MEVBS_P16X8_FLAG   1
     256#define MEVBS_P8X16_FLAG   2
     257#define MEVBS_P8X8_FLAG    3
     258#define MEPXLAC_LO         4
     259#define MEPXLAC_HI         5
     260#define XTRACOST_FLAG      6
     261#define XTRACOSTP8x8_FLAG  7
     262#define INTRA_IN_P_FLAG    8
     263#define I16x16_FLAG        9
     264#define I4x4_FLAG         10
     265#define I16x16_MASK_LO    12
     266#define I16x16_MASK_HI    15
     267#define ICHR_MASK_LO      16
     268#define ICHR_MASK_HI      19
     269#define I4x4_MASK_LO      20
     270#define I4x4_MASK_HI      28
     271#define SRX_LO             0
     272#define SRX_HI             7
     273#define SRY_LO             8
     274#define SRY_HI            15
     275#define VIMPW_LO          16
     276#define VIMPW_HI          19
     277#define VIMPR_LO          20
     278#define VIMPR_HI          23
     279#define VOMPW_LO          24
     280#define VOMPW_HI          27
     281#define REFWR_LO          28
     282#define REFWR_HI          31
     283#define QPADJSTRENGTH_LO   0
     284#define QPADJSTRENGTH_HI   3
     285#define USEINITQP_FLAG     4
     286#define USESCENECUT_FLAG   5
     287#define USERCOVERDUE_FLAG  6
     288#define STRICTCBR_FLAG     7
     289#define DISMADTH_FLAG      8
     290#define VBRF_LO            9
     291#define VBRF_HI            15
     292#define ICPBRDFR_LO        16
     293#define ICPBRDFR_HI        23
     294#define SWCLR_FLAG     0
     295#define SWSUSPEND_FLAG 1
     296#define XTMEMPTR_LO    0
     297#define XTMEMPTR_HI   31
     298#define PID_KU_IONPY_LO              0
     299#define PID_KU_IONPY_HI              3
     300#define PID_KU_IP_LO                 4
     301#define PID_KU_IP_HI                 7
     302#define PID_KI_UPD_IONPY_LO          8
     303#define PID_KI_UPD_IONPY_HI         15
     304#define PID_KI_UPD_IP_LO            16
     305#define PID_KI_UPD_IP_HI            23
     306#define PID_FIFO_STATUS_TARGET_LO   24
     307#define PID_FIFO_STATUS_TARGET_HI   29
     308#define PID_USE_COLOCATED_FLAG      30
     309#define PID_USE_IBU_THR_FLAG        31
     310#define PID_IFRAME_BUFFER_FACTOR_LO  0
     311#define PID_IFRAME_BUFFER_FACTOR_HI  7
     312#define PID_QP_STEP_FR_LO            8
     313#define PID_QP_STEP_FR_HI           11
     314#define PID_QP_STEP_IBU_LO          12
     315#define PID_QP_STEP_IBU_HI          15
     316#define PID_FSTATUS_0_LO            16
     317#define PID_FSTATUS_0_HI            22
     318#define PID_THRFRMLIM_0_FLAG        23
     319#define PID_FSTATUS_1_LO            24
     320#define PID_FSTATUS_1_HI            30
     321#define PID_THRFRMLIM_1_FLAG        31
     322#define PID_FSTATUS_2_LO             0
     323#define PID_FSTATUS_2_HI             6
     324#define PID_THRFRMLIM_2_FLAG         7
     325#define PID_FSTATUS_3_LO             8
     326#define PID_FSTATUS_3_HI            14
     327#define PID_THRFRMLIM_3_FLAG        15
     328#define PID_FSTATUS_4_LO            16
     329#define PID_FSTATUS_4_HI            22
     330#define PID_THRFRMLIM_4_FLAG        23
     331#define PID_QP_STEP_0_LO            24
     332#define PID_QP_STEP_0_HI            27
     333#define PID_QP_THR_0_LO             28
     334#define PID_QP_THR_0_HI             31
     335#define PID_QP_STEP_1_LO             0
     336#define PID_QP_STEP_1_HI             3
     337#define PID_QP_THR_1_LO              4
     338#define PID_QP_THR_1_HI              7
     339#define PID_QP_STEP_2_LO             8
     340#define PID_QP_STEP_2_HI            11
     341#define PID_QP_THR_2_LO             12
     342#define PID_QP_THR_2_HI             15
     343#define PID_QP_STEP_3_LO            16
     344#define PID_QP_STEP_3_HI            19
     345#define PID_QP_THR_3_LO             20
     346#define PID_QP_THR_3_HI             23
     347#define PID_QP_STEP_4_LO            24
     348#define PID_QP_STEP_4_HI            27
     349#define PID_QP_THR_4_LO             28
     350#define PID_QP_THR_4_HI             31
     351#define PID_RAMP_METHOD_LO           0
     352#define PID_RAMP_METHOD_HI           1
     353#define PID_USE_KD_FLAG              2
     354#define PID_USE_KI_UPD_FLAG          3
     355#define PID_USE_KI_UPDM_FLAG         4
     356#define PID_USE_SCENE_THR_FLAG       5
     357#define PID_USE_AVG_QP_THR_FLAG      6
     358#define PID_AVG_QP_THR_LO           16
     359#define PID_AVG_QP_THR_HI           23
     360#define PID_SCENE_THR_LO            24
     361#define PID_SCENE_THR_HI            31
     362#define PID_USE_COLOCATED          0
     363#define PID_RAMP_METHOD            1
     364#define PID_KU_IONPY               8
     365#define PID_KU_IP                  4
     366#define PID_KI_UPD_IONPY          16
     367#define PID_KI_UPD_IP              8
     368#define PID_USE_KP                 1
     369#define PID_USE_KI                 1
     370#define PID_USE_KD                 1
     371#define PID_USE_KI_UPD             1
     372#define PID_USE_KI_UPDM            1
     373#define PID_USE_IBU_THR            1
     374#define PID_USE_AVG_QP_THR         1
     375#define PID_USE_SCENE_THR          1
     376#define PID_AVG_QP_THR            16
     377#define PID_SCENE_THR             64
     378#define PID_FIFO_STATUS_TARGET    25
     379#define PID_IFRAME_BUFFER_FACTOR  65
     380#define PID_QP_STEP_FR             3
     381#define PID_QP_STEP_IBU            2
     382#define PID_FSTATUS_4              0
     383#define PID_QP_STEP_4              4
     384#define PID_QP_THR_4              12
     385#define PID_THRFRMLIM_4            0
     386#define PID_FSTATUS_3             50
     387#define PID_QP_STEP_3              3
     388#define PID_QP_THR_3               9
     389#define PID_THRFRMLIM_3            0
     390#define PID_FSTATUS_2             37
     391#define PID_QP_STEP_2              2
     392#define PID_QP_THR_2               6
     393#define PID_THRFRMLIM_2            1
     394#define PID_FSTATUS_1             12
     395#define PID_QP_STEP_1              1
     396#define PID_QP_THR_1               3
     397#define PID_THRFRMLIM_1            1
     398#define PID_FSTATUS_0              5
     399#define PID_QP_STEP_0              0
     400#define PID_QP_THR_0               0
     401#define PID_THRFRMLIM_0            1
     402#define VBS_DIFF_8x16_16x8_PREDICTOR 0
     403#define VBS_DIFF_8x8_PREDICTOR       1
     404#define VBS_USE_XTRA_PART_COST       2
     405#define VBS_USE_XTRA_PART_COST_P8x8  3
     406#define PSKIP_USE_HIGH_COST          4
     407#define VIMBPLANAR     0
     408#define VIPLANAR       1
     409#define VIINTERLEAVED  2
     410#define VIINTERLEAVEDF 3
     411#define TBA_DISABLE 0
     412#define TBA_INIT    1
     413#define TBA_APPEND  2
     414#define TBA_FINISH  3
     415#define TBA_SINGLE  4
     416#define BASELINE  66
     417#define MAIN      77
     418#define HIGH     100
     419#define HIGH10P  110
     420#define HIGH422  122
     421#define HIGH444  244
     422#define YUV400 0
     423#define YUV420 1
     424#define YUV422 2
     425#define YUV444 3
     426#define RC_MASK_SMARTINIT_QP     0
     427#define RC_MASK_SCENE_CUT_DETECT 1
     428#define RC_MASK_DISOVERDUE       2
     429#define RC_MASK_STRICTCBR        3
     430#define RC_MASK_DISMATH          4
     431#define RCM_PID 0
     432#define RCM_M1  1
     433#define RCM_M0  2
     434#define RCM_M2  3
     435
     436static const int SUB_WIDTH_C_PVT[4]  = {0, 2, 2, 1};
     437static const int SUB_HEIGHT_C_PVT[4] = {0, 2, 1, 1};
     438
     439
     440#endif // _H264E_CSREGS_PRIVATE_H_
  • new file libavcodec/xlnx_h264/h264e_sdaccel.c

    diff --git a/libavcodec/xlnx_h264/h264e_sdaccel.c b/libavcodec/xlnx_h264/h264e_sdaccel.c
    new file mode 100644
    index 0000000..6b0b8e4
    - +  
     1/*
     2-- Copyright notice:
     3-- Copyright (c) 2017 Alma Technologies S.A.
     4-- www.alma-technologies.com
     5-- All rights reserved worldwide.
     6
     7-- This copy is made available under the terms of the GNU General Public
     8-- License version 2.1 as published by the Free Software Foundation; either
     9-- version 2.1 of the License, or (at your option) any later version.
     10--
     11-- This copy is distributed in the hope that it will be useful,
     12-- but WITHOUT ANY WARRANTY; without even the implied warranty of
     13-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Please See the GNU
     14-- General Public License for more details.
     15--
     16-- You should have received a copy of the GNU General Public
     17-- License along with FFmpeg; if not, write to the Free Software
     18-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     19*/
     20
     21#include <stdio.h>
     22#include <stdlib.h>
     23#include <string.h>
     24#include <time.h>
     25#include <CL/opencl.h>
     26#include <CL/cl_ext.h>
     27#include "libavutil/atomic.h"
     28#include "h264e_sdaccel.h"
     29#include "h264e_sdaccel_private.h"
     30#include "h264e_sdaccel_utils.h"
     31#include "h264e_csregs.h"
     32
     33static int kernel_number = -1;
     34static const int kernel_ddr_map[] = {
     35        XCL_MEM_DDR_BANK0,
     36        XCL_MEM_DDR_BANK0,
     37        XCL_MEM_DDR_BANK1,
     38        XCL_MEM_DDR_BANK1,
     39        XCL_MEM_DDR_BANK2,
     40        XCL_MEM_DDR_BANK2,
     41        XCL_MEM_DDR_BANK3,
     42        XCL_MEM_DDR_BANK3
     43        };
     44
     45static const int kernel_map[] = {0,2,4,6,1,3,5,7};
     46
     47int h264eInitSW(H264E_KCFG* ph264eKCFG);
     48int h264eEndSW (H264E_KCFG* ph264eKCFG);
     49int h264eInitHW(H264E_KCFG* ph264eKCFG);
     50int h264eEndHW (H264E_KCFG* ph264eKCFG);
     51int h264eClear (H264E_KCFG* ph264eKCFG);
     52
     53int h264eWriteDeviceBuffer(H264E_CL* ph264eCL,
     54                           char*     pHostBuffer,
     55                           cl_mem    DeviceBuffer,
     56                           int       HostOffset,
     57                           int       DeviceOffset,
     58                           int       ByteSize,
     59                           bool      bSync
     60                           );
     61
     62int h264eReadDeviceBuffer(H264E_CL* ph264eCL,
     63                          char*     pHostBuffer,
     64                          cl_mem    DeviceBuffer,
     65                          int       HostOffset,
     66                          int       DeviceOffset,
     67                          int       ByteSize
     68                          );
     69
     70int h264eSetKernelArguments(H264E_KCFG* ph264eKCFG,
     71                            int         KernelRunType
     72                            );
     73
     74int h264eExecuteKernel(H264E_CL* ph264eCL, cl_event *event);
     75
     76
     77int h264eWriteYUV(H264E_KERNEL_HANDLE h264eKernelHandle,
     78                  char* pHostYBuffer,
     79                  char* pHostUBuffer,
     80                  char* pHostVBuffer);
     81
     82void *h264eEncoderThread(void *h264eKernelHandle);
     83
     84void h264eUpdateStats(H264E_TIME* ph264eTime);
     85void h264eReportDebugStatus(int DebugStatus);
     86
     87H264E_KERNEL_HANDLE h264eInit(const H264E_USR* pch264eUsr)
     88{
     89    H264E_KCFG* ph264eKCFG;
     90    int         ans;
     91    if(pch264eUsr == NULL) return NULL;
     92    ph264eKCFG = malloc(sizeof(H264E_KCFG));
     93    if(ph264eKCFG == NULL) return NULL;
     94    H264E_CL*   ph264eCL   = &ph264eKCFG->h264eCL;
     95    H264E_USR*  ph264eUsr  = &ph264eKCFG->h264eUsr;
     96    H264E_CNTX* ph264eCntx = &ph264eKCFG->h264eCntx;
     97    memcpy(ph264eUsr, pch264eUsr, sizeof(H264E_USR));
     98    ans  = h264eInitSW(ph264eKCFG);
     99    ans |= h264eInitHW(ph264eKCFG);
     100    if(ans < 0)
     101    {
     102        h264eEndSW(ph264eKCFG);
     103        h264eEndHW(ph264eKCFG);
     104
     105        free(ph264eKCFG);
     106        return NULL;
     107    }
     108    memset(ph264eCntx->CRegsFile, 0, sizeof(ph264eCntx->CRegsFile));
     109    memset(ph264eCntx->SRegsFile, 0, sizeof(ph264eCntx->SRegsFile));
     110    h264eSetControlRegs(ph264eUsr, ph264eCntx->CRegsFile);
     111    ans = h264eWriteDeviceBuffer(ph264eCL,
     112                                 ph264eCntx->CRegsFile,
     113                                 ph264eCntx->DeviceBuffer,
     114                                 0,
     115                                 ph264eCntx->CRegsPtr,
     116                                 sizeof(ph264eCntx->CRegsFile),
     117                                 true
     118                                 );
     119    ans |= h264eSetKernelArguments(ph264eKCFG, CONTROL_RT);
     120    ans |= h264eExecuteKernel(ph264eCL, NULL);
     121    ans |= h264eSetKernelArguments(ph264eKCFG, STATUS_RT);
     122    ans |= h264eExecuteKernel(ph264eCL, NULL);
     123    if(ans < 0)
     124    {
     125        h264eEndSW(ph264eKCFG);
     126        h264eEndHW(ph264eKCFG);
     127        free(ph264eKCFG);
     128        return NULL;
     129    }
     130    ans = h264eReadDeviceBuffer(ph264eCL,
     131                                ph264eKCFG->h264eCntx.SRegsFile,
     132                                ph264eKCFG->h264eCntx.DeviceBuffer,
     133                                0,
     134                                ph264eKCFG->h264eCntx.SRegsPtr,
     135                                sizeof(ph264eKCFG->h264eCntx.SRegsFile)
     136                                );
     137    if(ans < 0)
     138    {
     139        h264eEndSW(ph264eKCFG);
     140        h264eEndHW(ph264eKCFG);
     141
     142        free(ph264eKCFG);
     143        return NULL;
     144    }
     145    int ErrID = h264eGetErrorCode((int*)ph264eKCFG->h264eCntx.SRegsFile);
     146    if(ErrID)
     147    {
     148        H264EMSG(printf("ERROR: H.264 core programming error\n"));
     149        h264eClear(ph264eKCFG);
     150        h264eEndSW(ph264eKCFG);
     151        h264eEndHW(ph264eKCFG);
     152        free(ph264eKCFG);
     153        return NULL;
     154    }
     155    else
     156    {
     157        return (void*)ph264eKCFG;
     158    }
     159}
     160
     161int h264eEnd(H264E_KERNEL_HANDLE h264eKernelHandle)
     162{
     163    int ans;
     164    if(h264eKernelHandle == NULL)
     165    {
     166        H264EMSG(printf("ERROR: Invalid kernel handle\n"));
     167        return H264E_BAD_KERNEL_HANDLE;
     168    }
     169    H264E_KCFG* ph264eKCFG = (H264E_KCFG*)h264eKernelHandle;
     170    ans  = h264eEndSW(ph264eKCFG);
     171    ans |= h264eEndHW(ph264eKCFG);
     172    if(ans < 0)
     173    {
     174        return H264E_END_ERR;
     175    }
     176    else
     177    {
     178        return H264E_OK;
     179    }
     180}
     181
     182int h264eWriteYUV(H264E_KERNEL_HANDLE h264eKernelHandle,
     183                  char* pHostYBuffer,
     184                  char* pHostUBuffer,
     185                  char* pHostVBuffer)
     186{
     187    H264E_KCFG* ph264eKCFG = (H264E_KCFG*)h264eKernelHandle;
     188    int  YSizeInBytes     = 0;
     189    int  ChrSizeInBytes   = 0;
     190    int  FrameSizeInBytes = 0;
     191    int  VDataIdx         = 0;
     192    H264E_CL* ph264eCL = &ph264eKCFG->h264eCL;
     193    H264E_CNTX *ph264eCNTX = &ph264eKCFG->h264eCntx;
     194    VDataIdx = ph264eCNTX->VDataIdx;
     195    H264ETIME(timespec tss);
     196    H264ETIME(timespec tse);
     197    H264ETIME(clock_gettime(CLOCK_MONOTONIC_RAW, &tss));
     198    if(ph264eKCFG->h264eUsr.ScanFormat == H264E_PLANAR_SEPARATED)
     199    {
     200        if(pHostYBuffer == NULL || pHostUBuffer == NULL || pHostVBuffer == NULL)
     201        {
     202            H264EMSG(printf("ERROR: Invalid Y, U or V data pointer(s)\n"));
     203            return H264E_BAD_COMP_PTR;
     204        }
     205        YSizeInBytes     =  ph264eKCFG->h264eUsr.FrameX * ph264eKCFG->h264eUsr.FrameY;
     206        ChrSizeInBytes   = (ph264eKCFG->h264eUsr.FrameX * ph264eKCFG->h264eUsr.FrameY) / 4;
     207        FrameSizeInBytes = YSizeInBytes + 2*ChrSizeInBytes;
     208        if(ph264eKCFG->h264eUsr.PackPlanarSeparated)
     209        {
     210            memcpy(ph264eKCFG->h264eCntx.pPackedPlanarHostBuffer,                                 pHostYBuffer, YSizeInBytes);
     211            memcpy(ph264eKCFG->h264eCntx.pPackedPlanarHostBuffer + YSizeInBytes,                  pHostUBuffer, ChrSizeInBytes);
     212            memcpy(ph264eKCFG->h264eCntx.pPackedPlanarHostBuffer + YSizeInBytes + ChrSizeInBytes, pHostVBuffer, ChrSizeInBytes);
     213            h264eWriteDeviceBuffer(ph264eCL,
     214                                   ph264eKCFG->h264eCntx.pPackedPlanarHostBuffer,
     215                                   ph264eKCFG->h264eCntx.DeviceBuffer,
     216                                   0,
     217                                   ph264eKCFG->h264eCntx.VDataPtr[VDataIdx],
     218                                   FrameSizeInBytes,
     219                                   true
     220                                   );
     221            if(ph264eCL->bWRDeviceBufferFailed) return H264E_DEVBUFF_WR_ERR;
     222        }
     223        else
     224        {
     225            h264eWriteDeviceBuffer(ph264eCL,
     226                                   pHostYBuffer,
     227                                   ph264eKCFG->h264eCntx.DeviceBuffer,
     228                                   0,
     229                                   ph264eKCFG->h264eCntx.VDataPtr[VDataIdx],
     230                                   YSizeInBytes,
     231                                   true
     232                                   );
     233            if(ph264eCL->bWRDeviceBufferFailed) return H264E_DEVBUFF_WR_ERR;
     234            h264eWriteDeviceBuffer(ph264eCL,
     235                                   pHostUBuffer,
     236                                   ph264eKCFG->h264eCntx.DeviceBuffer,
     237                                   0,
     238                                   ph264eKCFG->h264eCntx.VDataPtr[VDataIdx] + YSizeInBytes,
     239                                   ChrSizeInBytes,
     240                                   true
     241                                   );
     242            if(ph264eCL->bWRDeviceBufferFailed) return H264E_DEVBUFF_WR_ERR;
     243            h264eWriteDeviceBuffer(ph264eCL,
     244                                   pHostVBuffer,
     245                                   ph264eKCFG->h264eCntx.DeviceBuffer,
     246                                   0,
     247                                   ph264eKCFG->h264eCntx.VDataPtr[VDataIdx] + YSizeInBytes + ChrSizeInBytes,
     248                                   ChrSizeInBytes,
     249                                   true
     250                                   );
     251            if(ph264eCL->bWRDeviceBufferFailed) return H264E_DEVBUFF_WR_ERR;
     252        }
     253
     254        if(ph264eKCFG->h264eUsr.HWOptimizeScanFormat)
     255        {
     256              ph264eKCFG->h264eCntx.Format = PLANAR_TO_INTERLEAVED_FRMT;
     257        }
     258        else
     259        {
     260            ph264eKCFG->h264eCntx.Format = NO_CHANGE_FRMT;
     261        }
     262    }
     263    else
     264    {
     265        if(pHostYBuffer == NULL)
     266        {
     267            H264EMSG(printf("ERROR: Invalid Y data pointer\n"));
     268            return H264E_BAD_COMP_PTR;
     269        }
     270        if(ph264eKCFG->h264eUsr.ScanFormat == H264E_PLANAR_PACKED)
     271        {
     272            YSizeInBytes     =  ph264eKCFG->h264eUsr.FrameX * ph264eKCFG->h264eUsr.FrameY;
     273            ChrSizeInBytes   = (ph264eKCFG->h264eUsr.FrameX * ph264eKCFG->h264eUsr.FrameY) / 4;
     274            FrameSizeInBytes = YSizeInBytes + 2*ChrSizeInBytes;
     275            if(ph264eKCFG->h264eUsr.HWOptimizeScanFormat)
     276            {
     277                ph264eKCFG->h264eCntx.Format = PLANAR_TO_INTERLEAVED_FRMT;
     278            }
     279            else
     280            {
     281                ph264eKCFG->h264eCntx.Format = NO_CHANGE_FRMT;
     282            }
     283        }
     284        else if(ph264eKCFG->h264eUsr.ScanFormat == H264E_INTERLEAVED_YC)
     285        {
     286            YSizeInBytes     =  ph264eKCFG->h264eUsr.FrameX * ph264eKCFG->h264eUsr.FrameY;
     287            ChrSizeInBytes   = (ph264eKCFG->h264eUsr.FrameX * ph264eKCFG->h264eUsr.FrameY) / 4;
     288            FrameSizeInBytes = YSizeInBytes + 2*ChrSizeInBytes;
     289            ph264eKCFG->h264eCntx.Format = NO_CHANGE_FRMT;
     290        }
     291        else if(ph264eKCFG->h264eUsr.ScanFormat == H264E_INTERLEAVED_CY)
     292        {
     293            YSizeInBytes     =  ph264eKCFG->h264eUsr.FrameX * ph264eKCFG->h264eUsr.FrameY;
     294            ChrSizeInBytes   = (ph264eKCFG->h264eUsr.FrameX * ph264eKCFG->h264eUsr.FrameY) / 4;
     295            FrameSizeInBytes = YSizeInBytes + 2*ChrSizeInBytes;
     296            ph264eKCFG->h264eCntx.Format = NO_CHANGE_FRMT;
     297        }
     298        else if(ph264eKCFG->h264eUsr.ScanFormat == H264E_MACROBLOCK)
     299        {
     300            int FrameX = ph264eKCFG->h264eUsr.FrameX;
     301            int FrameY = ph264eKCFG->h264eUsr.FrameY;
     302            FrameX = ((FrameX + 15) / 16) * 16;
     303            FrameY = ((FrameY + 15) / 16) * 16;
     304            YSizeInBytes     =  FrameX * FrameY;
     305            ChrSizeInBytes   = (FrameX * FrameY) / 4;
     306            FrameSizeInBytes = YSizeInBytes + 2*ChrSizeInBytes;
     307            ph264eKCFG->h264eCntx.Format = NO_CHANGE_FRMT;
     308        }
     309        h264eWriteDeviceBuffer(ph264eCL,
     310                               pHostYBuffer,
     311                               ph264eKCFG->h264eCntx.DeviceBuffer,
     312                               0,
     313                               ph264eKCFG->h264eCntx.VDataPtr[VDataIdx],
     314                               FrameSizeInBytes,
     315                               true
     316                               );
     317        if(ph264eCL->bWRDeviceBufferFailed) return H264E_DEVBUFF_WR_ERR;
     318    }
     319    H264ETIME(clock_gettime(CLOCK_MONOTONIC_RAW, &tse));
     320    H264ETIME(ph264eKCFG->h264eTime.WriteDeviceBufferTime = tse.tv_nsec - tss.tv_nsec);
     321    return H264E_OK;
     322}
     323
     324int h264eEncodeFrame(H264E_KERNEL_HANDLE h264eKernelHandle,
     325                     char* pHostYBuffer,
     326                     char* pHostUBuffer,
     327                     char* pHostVBuffer,
     328                     char* pHostNALBuffer,
     329                     int   frame_count
     330                     )
     331{
     332    int  rc;
     333    int  NalSizeInBytes   = 0;
     334    if(h264eKernelHandle == NULL)
     335    {
     336        H264EMSG(printf("ERROR: Invalid kernel handle\n"));
     337        return H264E_BAD_KERNEL_HANDLE;
     338    }
     339    if(pHostNALBuffer == NULL)
     340    {
     341        H264EMSG(printf("ERROR: Invalid NAL pointer\n"));
     342        return H264E_BAD_NAL_PTR;
     343    }
     344    H264E_KCFG* ph264eKCFG = (H264E_KCFG*)h264eKernelHandle;
     345    H264E_CL* ph264eCL = &ph264eKCFG->h264eCL;
     346    H264ETIME(timespec tss);
     347    H264ETIME(timespec tse);
     348    H264ETIME(clock_gettime(CLOCK_MONOTONIC_RAW, &tss));
     349    rc = h264eWriteYUV(h264eKernelHandle,
     350                       pHostYBuffer,
     351                       pHostUBuffer,
     352                       pHostVBuffer);
     353    if (rc != H264E_OK) return rc;
     354    if (frame_count == 0)
     355    {
     356        H264ETIME(clock_gettime(CLOCK_MONOTONIC_RAW, &tss));
     357        h264eSetKernelArguments(ph264eKCFG, ENCODE_RT);
     358        if(ph264eCL->bSetKernelArgsFailed) return H264E_ARGSET_ERR;
     359        h264eExecuteKernel(ph264eCL, &ph264eCL->kernel_event);
     360        if(ph264eCL->bExecuteKernelFailed) return H264E_EXEC_ERR;
     361        return H264E_DEFER_DATA;
     362    }
     363    else
     364    {
     365        clWaitForEvents(1, &ph264eCL->kernel_event);
     366        H264ETIME(clock_gettime(CLOCK_MONOTONIC_RAW, &tss));
     367        h264eReadDeviceBuffer(ph264eCL,
     368                            ph264eKCFG->h264eCntx.SRegsFile,
     369                            ph264eKCFG->h264eCntx.DeviceBuffer,
     370                            0,
     371                            ph264eKCFG->h264eCntx.SRegsPtr,
     372                            sizeof(ph264eKCFG->h264eCntx.SRegsFile)
     373                            );
     374        if(ph264eCL->bRDDeviceBufferFailed) return H264E_DEVBUFF_RD_ERR;
     375        H264ETIME(clock_gettime(CLOCK_MONOTONIC_RAW, &tse));
     376        H264ETIME(ph264eKCFG->h264eTime.EncodeAndReadNALSizeTime = tse.tv_nsec - tss.tv_nsec);
     377        NalSizeInBytes = h264eGetNalSize((int*)ph264eKCFG->h264eCntx.SRegsFile);
     378        if(NalSizeInBytes == 0)
     379        {
     380            H264EMSG(printf("ERROR: H.264 core returned 0 NAL size\n"));
     381            return H264E_CORE_ERR;
     382        }
     383        H264ETIME(clock_gettime(CLOCK_MONOTONIC_RAW, &tss));
     384        h264eReadDeviceBuffer(ph264eCL,
     385                              pHostNALBuffer,
     386                              ph264eKCFG->h264eCntx.DeviceBuffer,
     387                              0,
     388                              ph264eKCFG->h264eCntx.NALPtr,
     389                              NalSizeInBytes
     390                            );
     391        if(ph264eCL->bRDDeviceBufferFailed) return H264E_DEVBUFF_RD_ERR;
     392        H264ETIME(clock_gettime(CLOCK_MONOTONIC_RAW, &tse));
     393        H264ETIME(ph264eKCFG->h264eTime.ReadNALBufferTime = tse.tv_nsec - tss.tv_nsec);
     394        H264ETIME(h264eUpdateStats(&ph264eKCFG->h264eTime));
     395        H264ETIME(clock_gettime(CLOCK_MONOTONIC_RAW, &tss));
     396        h264eSetKernelArguments(ph264eKCFG, ENCODE_RT);
     397        if(ph264eCL->bSetKernelArgsFailed) return H264E_ARGSET_ERR;
     398        h264eExecuteKernel(ph264eCL, &ph264eCL->kernel_event);
     399        if(ph264eCL->bExecuteKernelFailed) return H264E_EXEC_ERR;
     400        H264ETIME(clock_gettime(CLOCK_MONOTONIC_RAW, &tse));
     401        H264ETIME(ph264eKCFG->h264eTime.ExecuteKernelTime = tse.tv_nsec - tss.tv_nsec);
     402        rc = NalSizeInBytes;
     403    }
     404    return rc;
     405}
     406
     407int h264eInitSW(H264E_KCFG* ph264eKCFG)
     408{
     409    int rc = 0;
     410    int IPCoreMemSizeInBytes;
     411    int CRegsSizeInBytes;
     412    int SRegsSizeInBytes;
     413    int VDataSizeInBytes;
     414    int NALSizeInBytes;
     415    H264E_USR*  ph264eUsr  = &ph264eKCFG->h264eUsr;
     416    H264E_CNTX* ph264eCntx = &ph264eKCFG->h264eCntx;
     417    CRegsSizeInBytes = 64 * 4;
     418    SRegsSizeInBytes = 64 * 4;
     419    VDataSizeInBytes     = ph264eUsr->FrameX * ph264eUsr->FrameY * 1.5;
     420    IPCoreMemSizeInBytes = VDataSizeInBytes * 4;
     421    NALSizeInBytes       = VDataSizeInBytes;
     422    IPCoreMemSizeInBytes *= 1.1;
     423    VDataSizeInBytes     *= 1.1;
     424    NALSizeInBytes       *= 1.1;
     425    IPCoreMemSizeInBytes = ((IPCoreMemSizeInBytes / 4096) + 1) * 4096;
     426    CRegsSizeInBytes     = ((CRegsSizeInBytes     / 4096) + 1) * 4096;
     427    SRegsSizeInBytes     = ((SRegsSizeInBytes     / 4096) + 1) * 4096;
     428    VDataSizeInBytes     = ((VDataSizeInBytes     / 4096) + 1) * 4096;
     429    NALSizeInBytes       = ((NALSizeInBytes       / 4096) + 1) * 4096;
     430    ph264eCntx->NALPtr   = IPCoreMemSizeInBytes;
     431    ph264eCntx->SRegsPtr = ph264eCntx->NALPtr   + NALSizeInBytes;
     432    ph264eCntx->CRegsPtr = ph264eCntx->SRegsPtr + SRegsSizeInBytes;
     433    ph264eCntx->VDataPtr[0] = ph264eCntx->CRegsPtr + CRegsSizeInBytes;
     434    ph264eCntx->VDataPtr[1] = ph264eCntx->VDataPtr[0] + VDataSizeInBytes;
     435    ph264eCntx->VDataIdx                = 0;
     436    ph264eCntx->Format                  = 0;
     437    ph264eCntx->DeviceBuffer            = 0;
     438    ph264eCntx->DeviceBufferSizeInBytes = ph264eCntx->VDataPtr[1] + VDataSizeInBytes;
     439    memset(&ph264eKCFG->h264eTime, 0, sizeof(H264E_TIME));
     440    ph264eCntx->pPackedPlanarHostBuffer = NULL;
     441    if(ph264eUsr->ScanFormat == H264E_PLANAR_SEPARATED && ph264eUsr->PackPlanarSeparated)
     442    {
     443        ph264eCntx->pPackedPlanarHostBuffer = malloc(ph264eUsr->FrameX *
     444                                                                                                         ph264eUsr->FrameY *
     445                                                                                                         2);
     446        if(ph264eCntx->pPackedPlanarHostBuffer == NULL)
     447        {
     448            H264EMSG(printf("ERROR: Failed to allocate host buffer for packing planar separated input\n"));
     449            return H264E_INITSW_ERR;
     450        }
     451    }
     452    if(ph264eUsr->PackPlanarSeparated  < 0 || ph264eUsr->PackPlanarSeparated  > 0) ph264eUsr->PackPlanarSeparated  = 1;
     453    if(ph264eUsr->HWOptimizeScanFormat < 0 || ph264eUsr->HWOptimizeScanFormat > 0) ph264eUsr->HWOptimizeScanFormat = 1;
     454        printf("Creating request message queue\n");
     455        rc = av_thread_message_queue_alloc(&ph264eKCFG->h264eReqMsgQ, 1, sizeof(H264E_REQ_MSG));
     456        printf("Creating response message queue\n");
     457        rc |= av_thread_message_queue_alloc(&ph264eKCFG->h264eRspMsgQ,
     458                                                                           5, sizeof(H264E_RSP_MSG));
     459        if (rc < 0)
     460        {
     461                printf("Failed to allocate message queue\n");
     462                exit(1);
     463        }
     464        rc = pthread_create(&ph264eKCFG->h264eThread, NULL,
     465                                                h264eEncoderThread, ph264eKCFG);
     466    return H264E_OK;
     467}
     468
     469int h264eEndSW(H264E_KCFG* ph264eKCFG)
     470{
     471        H264E_REQ_MSG reqMsg;
     472        reqMsg.endThread = 1;
     473        av_thread_message_queue_send(ph264eKCFG->h264eReqMsgQ, &reqMsg, 0);
     474        pthread_join(ph264eKCFG->h264eThread, NULL);
     475        av_thread_message_queue_free(&ph264eKCFG->h264eReqMsgQ);
     476        av_thread_message_queue_free(&ph264eKCFG->h264eRspMsgQ);
     477    if(ph264eKCFG->h264eCntx.pPackedPlanarHostBuffer != NULL)
     478    {
     479        free(ph264eKCFG->h264eCntx.pPackedPlanarHostBuffer);
     480        ph264eKCFG->h264eCntx.pPackedPlanarHostBuffer = NULL;
     481    }
     482    H264EMSG(printf("\n"));
     483    H264EMSG(printf("\t\t======================================================\n"));
     484    H264EMSG(printf("\t\tTotal Write Device Buffer Run-Time    : %8.2f sec\n",  ph264eKCFG->h264eTime.WriteDeviceBufferTotalTimeMS    / 1000.0));
     485    H264EMSG(printf("\t\tTotal Execute Kernel Run-Time         : %8.2f sec\n",  ph264eKCFG->h264eTime.ExecuteKernelTotalTimeMS        / 1000.0));
     486    H264EMSG(printf("\t\tTotal Encode & Read NAL Size Run-Time : %8.2f sec\n",  ph264eKCFG->h264eTime.EncodeAndReadNALSizeTotalTimeMS / 1000.0));
     487    H264EMSG(printf("\t\tTotal Read NAL Buffer Run-Time        : %8.2f sec\n",  ph264eKCFG->h264eTime.ReadNALBufferTotalTimeMS        / 1000.0));
     488    H264ETIME(
     489        double TotalCLTime;
     490        TotalCLTime = ph264eKCFG->h264eTime.WriteDeviceBufferTotalTimeMS    +
     491                      ph264eKCFG->h264eTime.ExecuteKernelTotalTimeMS        +
     492                      ph264eKCFG->h264eTime.EncodeAndReadNALSizeTotalTimeMS +
     493                      ph264eKCFG->h264eTime.ReadNALBufferTotalTimeMS;
     494        TotalCLTime /= 1000.0;
     495    );
     496    H264EMSG(printf("\t\t======================================================\n"));
     497    H264EMSG(printf("\t\tTotal CL Run-Time                     : %8.2f sec\n", TotalCLTime));
     498    H264EMSG(printf("\t\t======================================================\n"));
     499    H264EMSG(printf("\n"));
     500    return H264E_OK;
     501}
     502
     503int h264eInitHW(H264E_KCFG* ph264eKCFG)
     504{
     505   int k_num;
     506   if(!ph264eKCFG->h264eUsr.bCLIsOK)
     507   {
     508           k_num = avpriv_atomic_int_add_and_fetch(&kernel_number, 1);
     509           ph264eKCFG->h264eCL.kernel_num = kernel_map[k_num];
     510       ph264eKCFG->h264eCL.pDeviceName        = ph264eKCFG->h264eUsr.pDeviceName;
     511       ph264eKCFG->h264eCL.pKernelBinFileName = ph264eKCFG->h264eUsr.pKernelBinFileName;
     512           snprintf(ph264eKCFG->h264eCL.pKernelName, 64, "%s_%d",
     513                ph264eKCFG->h264eUsr.pKernelName,
     514                ph264eKCFG->h264eCL.kernel_num);
     515       h264e_cl_init(&ph264eKCFG->h264eCL);
     516       if(!ph264eKCFG->h264eCL.bCLIsOK)
     517       {
     518           H264EMSG(printf("ERROR: Failed to initialize CL\n"));
     519           return H264E_INITHW_ERR;
     520       }
     521   }
     522   else
     523   {
     524       ph264eKCFG->h264eCL.commands = ph264eKCFG->h264eUsr.commands;
     525       ph264eKCFG->h264eCL.context  = ph264eKCFG->h264eUsr.context;
     526       ph264eKCFG->h264eCL.kernel   = ph264eKCFG->h264eUsr.kernel;
     527   }
     528        cl_mem_ext_ptr_t cl_mem_ptr;
     529        cl_mem_ptr.obj = 0;
     530        cl_mem_ptr.param = 0;
     531        cl_mem_ptr.flags = kernel_ddr_map[ph264eKCFG->h264eCL.kernel_num];
     532   ph264eKCFG->h264eCntx.DeviceBuffer = clCreateBuffer(ph264eKCFG->h264eCL.context,
     533                                                       CL_MEM_READ_WRITE | CL_MEM_EXT_PTR_XILINX,
     534                                                       ph264eKCFG->h264eCntx.DeviceBufferSizeInBytes,
     535                                                       &cl_mem_ptr,
     536                                                       NULL);
     537   if(!ph264eKCFG->h264eCntx.DeviceBuffer)
     538   {
     539       H264EMSG(printf("ERROR: Failed to allocate device memory\n"));
     540        return H264E_DEVBUFF_ERR;
     541   }
     542    return H264E_OK;
     543}
     544
     545int h264eEndHW(H264E_KCFG* ph264eKCFG)
     546{
     547    int err;
     548    int ans;
     549    int retval = H264E_OK;
     550   if(ph264eKCFG->h264eCntx.DeviceBuffer)
     551   {
     552        err = clReleaseMemObject(ph264eKCFG->h264eCntx.DeviceBuffer);
     553        if(err != CL_SUCCESS)
     554        {
     555            H264EMSG(printf("ERROR: Failed to release device buffer\n"));
     556            retval = H264E_DEVBUFF_ERR;
     557   }
     558   }
     559   if(ph264eKCFG->h264eCL.bCLIsOK && !ph264eKCFG->h264eUsr.bCLIsOK)
     560   {
     561        ans = h264e_cl_end(&(ph264eKCFG->h264eCL));
     562        if(ans < 0) retval = ans;
     563   }
     564   return retval;
     565}
     566
     567int h264eWriteDeviceBuffer(H264E_CL* ph264eCL,
     568                           char*     pHostBuffer,
     569                           cl_mem    DeviceBuffer,
     570                           int       HostOffset,
     571                           int       DeviceOffset,
     572                           int       ByteSize,
     573                           bool      bSync
     574                           )
     575{
     576   int      err;
     577   cl_event writeevent;
     578   if(bSync)
     579   {
     580       err = clEnqueueWriteBuffer(ph264eCL->commands,
     581                                  DeviceBuffer,
     582                                  CL_TRUE,
     583                                  DeviceOffset,
     584                                  ByteSize,
     585                                  pHostBuffer + HostOffset,
     586                                  0,
     587                                  NULL,
     588                                  &writeevent
     589                                  );
     590   }
     591   else
     592   {
     593       err = clEnqueueWriteBuffer(ph264eCL->commands,
     594                                  DeviceBuffer,
     595                                  CL_TRUE,
     596                                  DeviceOffset,
     597                                  ByteSize,
     598                                  pHostBuffer + HostOffset,
     599                                  0,
     600                                  NULL,
     601                                  NULL
     602                                  );
     603   }
     604   if(err != CL_SUCCESS)
     605   {
     606      H264EMSG(printf("ERROR: Failed to write to device buffer\n"));
     607        ph264eCL->bWRDeviceBufferFailed = true;
     608        return H264E_DEVBUFF_WR_ERR;
     609   }
     610   if(bSync)
     611   {
     612      clWaitForEvents(1, &writeevent);
     613   }
     614    ph264eCL->bWRDeviceBufferFailed = false;
     615    return H264E_OK;
     616}
     617
     618int h264eReadDeviceBuffer(H264E_CL* ph264eCL,
     619                          char*     pHostBuffer,
     620                          cl_mem    DeviceBuffer,
     621                          int       HostOffset,
     622                          int       DeviceOffset,
     623                          int       ByteSize)
     624{
     625    int err;
     626    cl_event readevent;
     627    err = clEnqueueReadBuffer(ph264eCL->commands,
     628                              DeviceBuffer,
     629                              CL_TRUE,
     630                              DeviceOffset,
     631                              ByteSize,
     632                              pHostBuffer + HostOffset,
     633                              0,
     634                              NULL,
     635                              &readevent
     636                              );
     637    if(err != CL_SUCCESS)
     638    {
     639        H264EMSG(printf("ERROR: Failed to read device buffer (error %d)\n", err));
     640        ph264eCL->bRDDeviceBufferFailed = true;
     641        return H264E_DEVBUFF_RD_ERR;
     642    }
     643    clWaitForEvents(1, &readevent);
     644    ph264eCL->bRDDeviceBufferFailed = false;
     645    return H264E_OK;
     646}
     647
     648int h264eSetKernelArguments(H264E_KCFG* ph264eKCFG,
     649                            int         KernelRunType
     650                            )
     651{
     652    int err;
     653    H264E_CL*   ph264eCL   = &ph264eKCFG->h264eCL;
     654    H264E_USR*  ph264eUsr  = &ph264eKCFG->h264eUsr;
     655    H264E_CNTX* ph264eCntx = &ph264eKCFG->h264eCntx;
     656    int CRegsPtr = ph264eCntx->CRegsPtr;
     657    int SRegsPtr = ph264eCntx->SRegsPtr;
     658    int VDataPtr = ph264eCntx->VDataPtr[ph264eCntx->VDataIdx];
     659    int NALPtr   = ph264eCntx->NALPtr;
     660    int Format   = ph264eCntx->Format;
     661    int FrameX   = ph264eUsr->FrameX;
     662    int FrameY   = ph264eUsr->FrameY;
     663    if(ph264eUsr->ScanFormat == H264E_MACROBLOCK)
     664    {
     665        FrameX = ((FrameX + 15) / 16) * 16;
     666        FrameY = ((FrameY + 15) / 16) * 16;
     667    }
     668    cl_kernel kernel       = ph264eCL->kernel;
     669    cl_mem    DeviceBuffer = ph264eCntx->DeviceBuffer;
     670    err  = 0;
     671    err  = clSetKernelArg(kernel, 0, sizeof(cl_mem), &DeviceBuffer);
     672    err |= clSetKernelArg(kernel, 1, sizeof(int), &CRegsPtr);
     673    err |= clSetKernelArg(kernel, 2, sizeof(int), &SRegsPtr);
     674    err |= clSetKernelArg(kernel, 3, sizeof(int), &VDataPtr);
     675    err |= clSetKernelArg(kernel, 4, sizeof(int), &NALPtr);
     676    err |= clSetKernelArg(kernel, 5, sizeof(int), &FrameX);
     677    err |= clSetKernelArg(kernel, 6, sizeof(int), &FrameY);
     678    err |= clSetKernelArg(kernel, 7, sizeof(int), &Format);
     679    err |= clSetKernelArg(kernel, 8, sizeof(int), &KernelRunType);
     680    if(err != CL_SUCCESS)
     681    {
     682        H264EMSG(printf("ERROR: Failed to set kernel arguments (error %d)\n", err));
     683        ph264eKCFG->h264eCL.bSetKernelArgsFailed = true;
     684        return H264E_ARGSET_ERR;
     685    }
     686    ph264eKCFG->h264eCL.bSetKernelArgsFailed = false;
     687    return H264E_OK;
     688}
     689
     690int h264eExecuteKernel(H264E_CL* ph264eCL, cl_event *event)
     691{
     692    int err;
     693    cl_event execwait;
     694    cl_event *pEvent;
     695    if (event)
     696        pEvent = event;
     697    else
     698        pEvent = &execwait;
     699    err = clEnqueueTask(ph264eCL->commands, ph264eCL->kernel, 0, NULL, pEvent);
     700    if(err != CL_SUCCESS)
     701    {
     702        H264EMSG(printf("ERROR: Failed to execute kernel (error %d)\n", err));
     703        ph264eCL->bExecuteKernelFailed = true;
     704        return H264E_EXEC_ERR;
     705    }
     706    if (event == NULL)
     707    {
     708        clWaitForEvents(1, &execwait);
     709        ph264eCL->bExecuteKernelFailed = false;
     710    }
     711    return H264E_OK;
     712}
     713
     714const char* h264eReadStatusRegs(H264E_KERNEL_HANDLE h264eKernelHandle)
     715{
     716    if(h264eKernelHandle == NULL)
     717    {
     718        H264EMSG(printf("ERROR: Invalid kernel handle\n"));
     719        return NULL;
     720    }
     721   H264E_KCFG* ph264eKCFG = (H264E_KCFG*)h264eKernelHandle;
     722   h264eSetKernelArguments(ph264eKCFG, STATUS_RT);
     723    if(ph264eKCFG->h264eCL.bSetKernelArgsFailed) return NULL;
     724
     725   h264eExecuteKernel(&ph264eKCFG->h264eCL, NULL);
     726    if(ph264eKCFG->h264eCL.bExecuteKernelFailed) return NULL;
     727   h264eReadDeviceBuffer(&ph264eKCFG->h264eCL,
     728                         ph264eKCFG->h264eCntx.SRegsFile,
     729                         ph264eKCFG->h264eCntx.DeviceBuffer,
     730                         0,
     731                         ph264eKCFG->h264eCntx.SRegsPtr,
     732                         sizeof(ph264eKCFG->h264eCntx.SRegsFile)
     733                         );
     734    if(ph264eKCFG->h264eCL.bRDDeviceBufferFailed) return NULL;
     735   return ph264eKCFG->h264eCntx.SRegsFile;
     736}
     737
     738int h264eClear(H264E_KCFG* ph264eKCFG)
     739{
     740   h264eSetKernelArguments(ph264eKCFG, CLEAR_RT);
     741    if(ph264eKCFG->h264eCL.bSetKernelArgsFailed) return H264E_ARGSET_ERR;
     742   h264eExecuteKernel(&ph264eKCFG->h264eCL, NULL);
     743    if(ph264eKCFG->h264eCL.bExecuteKernelFailed) return H264E_EXEC_ERR;
     744    return H264E_OK;
     745}
     746
     747int h264eSetUserContext(H264E_KERNEL_HANDLE h264eKernelHandle, void* Context)
     748{
     749    if(h264eKernelHandle == NULL)
     750    {
     751        H264EMSG(printf("ERROR: Invalid kernel handle\n"));
     752        return H264E_BAD_KERNEL_HANDLE;
     753    }
     754    H264E_KCFG* ph264eKCFG = (H264E_KCFG*)h264eKernelHandle;
     755    ph264eKCFG->h264eUsr.UserContext = Context;
     756    return H264E_OK;
     757}
     758
     759void* h264eGetUserContext(H264E_KERNEL_HANDLE h264eKernelHandle)
     760{
     761    if(h264eKernelHandle == NULL)
     762    {
     763        H264EMSG(printf("ERROR: Invalid kernel handle\n"));
     764        return NULL;
     765    }
     766    H264E_KCFG* ph264eKCFG = (H264E_KCFG*)h264eKernelHandle;
     767    return ph264eKCFG->h264eUsr.UserContext;
     768}
     769
     770void h264eUpdateStats(H264E_TIME* ph264eTime)
     771{
     772    ph264eTime->nFrames++;
     773    ph264eTime->WriteDeviceBufferTimeMS    = (double)ph264eTime->WriteDeviceBufferTime    / 1E6;
     774    ph264eTime->ExecuteKernelTimeMS        = (double)ph264eTime->ExecuteKernelTime        / 1E6;
     775    ph264eTime->EncodeAndReadNALSizeTimeMS = (double)ph264eTime->EncodeAndReadNALSizeTime / 1E6;
     776    ph264eTime->ReadNALBufferTimeMS        = (double)ph264eTime->ReadNALBufferTime        / 1E6;
     777    if(ph264eTime->WriteDeviceBufferTimeMS    < 0) ph264eTime->WriteDeviceBufferTimeMS    += 1000.0;
     778    if(ph264eTime->ExecuteKernelTimeMS        < 0) ph264eTime->ExecuteKernelTimeMS        += 1000.0;
     779    if(ph264eTime->EncodeAndReadNALSizeTimeMS < 0) ph264eTime->EncodeAndReadNALSizeTimeMS += 1000.0;
     780    if(ph264eTime->ReadNALBufferTimeMS        < 0) ph264eTime->ReadNALBufferTimeMS        += 1000.0;
     781    ph264eTime->WriteDeviceBufferTotalTimeMS    += ph264eTime->WriteDeviceBufferTimeMS;
     782    ph264eTime->ExecuteKernelTotalTimeMS        += ph264eTime->ExecuteKernelTimeMS;
     783    ph264eTime->EncodeAndReadNALSizeTotalTimeMS += ph264eTime->EncodeAndReadNALSizeTimeMS;
     784    ph264eTime->ReadNALBufferTotalTimeMS        += ph264eTime->ReadNALBufferTimeMS;
     785    return;
     786}
     787
     788const H264E_TIME* h264eGetStats(H264E_KERNEL_HANDLE h264eKernelHandle)
     789{
     790    if(h264eKernelHandle == NULL)
     791    {
     792        H264EMSG(printf("ERROR: Invalid kernel handle\n"));
     793        return NULL;
     794    }
     795    H264E_KCFG* ph264eKCFG = (H264E_KCFG*)h264eKernelHandle;
     796    return &ph264eKCFG->h264eTime;
     797}
     798
     799void h264eReportDebugStatus(int DebugStatus)
     800{
     801    int i = 0;
     802    printf("TIMEOUT: xtmem_req_val     = %d\n", DebugStatus & (0x20000000 >> i++) ? 1 : 0);
     803    printf("TIMEOUT: xtmem_req_rdy     = %d\n", DebugStatus & (0x20000000 >> i++) ? 1 : 0);
     804    printf("TIMEOUT: xtmem_wdata_val   = %d\n", DebugStatus & (0x20000000 >> i++) ? 1 : 0);
     805    printf("TIMEOUT: xtmem_wdata_rdy   = %d\n", DebugStatus & (0x20000000 >> i++) ? 1 : 0);
     806    printf("TIMEOUT: xtmem_rdata_val   = %d\n", DebugStatus & (0x20000000 >> i++) ? 1 : 0);
     807    printf("TIMEOUT: xtmem_rdata_rdy   = %d\n", DebugStatus & (0x20000000 >> i++) ? 1 : 0);
     808    printf("TIMEOUT: sreg_wrreq_val    = %d\n", DebugStatus & (0x20000000 >> i++) ? 1 : 0);
     809    printf("TIMEOUT: sreg_wrreq_rdy    = %d\n", DebugStatus & (0x20000000 >> i++) ? 1 : 0);
     810    printf("TIMEOUT: vdata_rdreq_val   = %d\n", DebugStatus & (0x20000000 >> i++) ? 1 : 0);
     811    printf("TIMEOUT: vdata_rdreq_rdy   = %d\n", DebugStatus & (0x20000000 >> i++) ? 1 : 0);
     812    printf("TIMEOUT: nal_wrreq_val     = %d\n", DebugStatus & (0x20000000 >> i++) ? 1 : 0);
     813    printf("TIMEOUT: nal_wrreq_rdy     = %d\n", DebugStatus & (0x20000000 >> i++) ? 1 : 0);
     814    printf("TIMEOUT: xtmemin_wrreq_val = %d\n", DebugStatus & (0x20000000 >> i++) ? 1 : 0);
     815    printf("TIMEOUT: xtmemin_wrreq_rdy = %d\n", DebugStatus & (0x20000000 >> i++) ? 1 : 0);
     816    printf("TIMEOUT: xtmemin_rdreq_val = %d\n", DebugStatus & (0x20000000 >> i++) ? 1 : 0);
     817    printf("TIMEOUT: xtmemin_rdreq_rdy = %d\n", DebugStatus & (0x20000000 >> i++) ? 1 : 0);
     818    printf("TIMEOUT: vdata_rdata_val   = %d\n", DebugStatus & (0x20000000 >> i++) ? 1 : 0);
     819    printf("TIMEOUT: vdata_rdata_rdy   = %d\n", DebugStatus & (0x20000000 >> i++) ? 1 : 0);
     820    printf("TIMEOUT: nal_wdata_val     = %d\n", DebugStatus & (0x20000000 >> i++) ? 1 : 0);
     821    printf("TIMEOUT: nal_wdata_rdy     = %d\n", DebugStatus & (0x20000000 >> i++) ? 1 : 0);
     822    printf("TIMEOUT: xtmemin_wdata_val = %d\n", DebugStatus & (0x20000000 >> i++) ? 1 : 0);
     823    printf("TIMEOUT: xtmemin_wdata_rdy = %d\n", DebugStatus & (0x20000000 >> i++) ? 1 : 0);
     824    printf("TIMEOUT: xtmemin_rdata_val = %d\n", DebugStatus & (0x20000000 >> i++) ? 1 : 0);
     825    printf("TIMEOUT: xtmemin_rdata_rdy = %d\n", DebugStatus & (0x20000000 >> i++) ? 1 : 0);
     826    printf("TIMEOUT: vdata_dout_val    = %d\n", DebugStatus & (0x20000000 >> i++) ? 1 : 0);
     827    printf("TIMEOUT: vdata_dout_rdy    = %d\n", DebugStatus & (0x20000000 >> i++) ? 1 : 0);
     828    printf("TIMEOUT: vdata_val         = %d\n", DebugStatus & (0x20000000 >> i++) ? 1 : 0);
     829    printf("TIMEOUT: vdata_rdy         = %d\n", DebugStatus & (0x20000000 >> i++) ? 1 : 0);
     830    printf("TIMEOUT: nal_val           = %d\n", DebugStatus & (0x20000000 >> i++) ? 1 : 0);
     831    printf("TIMEOUT: nal_rdy           = %d\n", DebugStatus & (0x20000000 >> i++) ? 1 : 0);
     832    return;
     833}
     834
     835void *h264eEncoderThread(void *h264eKernelHandle)
     836{
     837        H264E_KCFG* ph264eKCFG = (H264E_KCFG*)h264eKernelHandle;
     838    H264E_CNTX *ph264eCNTX = &ph264eKCFG->h264eCntx;
     839    H264E_CL   *ph264eCL   = &ph264eKCFG->h264eCL;
     840        AVThreadMessageQueue *reqMq = ph264eKCFG->h264eReqMsgQ;
     841        AVThreadMessageQueue *rspMq = ph264eKCFG->h264eRspMsgQ;
     842        H264E_REQ_MSG reqMsg;
     843        H264E_RSP_MSG rspMsg;
     844    int frame_count = 0;
     845    int NalSizeInBytes;
     846        printf("Starting thread for kernel %d\n", ph264eCL->kernel_num);
     847    printf("Using latest version of Alma plugin\n");
     848        while(1)
     849        {
     850        ph264eCNTX->VDataIdx = frame_count & 1;
     851                av_thread_message_queue_recv(reqMq, &reqMsg, 0);
     852                if (reqMsg.endThread)
     853        {
     854            clWaitForEvents(1, &ph264eCL->kernel_event);
     855                        break;
     856        }
     857                else
     858                {
     859                        NalSizeInBytes = h264eEncodeFrame(ph264eKCFG,
     860                                                                  reqMsg.pHostYBuffer,
     861                                                                  reqMsg.pHostUBuffer,
     862                                                                  reqMsg.pHostVBuffer,
     863                                                                  reqMsg.pHostNALBuffer,
     864                                              frame_count);
     865            frame_count++;
     866            if (NalSizeInBytes == H264E_DEFER_DATA)
     867                continue;
     868            rspMsg.NalSizeInBytes = NalSizeInBytes;
     869                        rspMsg.pHostNALBuffer = reqMsg.pHostNALBuffer;
     870                        rspMsg.pFrame = reqMsg.pFrame;
     871                        av_thread_message_queue_send(rspMq, &rspMsg, 0);
     872                }
     873        }
     874        pthread_exit(NULL);
     875}
  • new file libavcodec/xlnx_h264/h264e_sdaccel.h

    diff --git a/libavcodec/xlnx_h264/h264e_sdaccel.h b/libavcodec/xlnx_h264/h264e_sdaccel.h
    new file mode 100644
    index 0000000..d79116f
    - +  
     1/*
     2-- Copyright notice:
     3-- Copyright (c) 2017 Alma Technologies S.A.
     4-- www.alma-technologies.com
     5-- All rights reserved worldwide.
     6
     7-- This copy is made available under the terms of the GNU General Public
     8-- License version 2.1 as published by the Free Software Foundation; either
     9-- version 2.1 of the License, or (at your option) any later version.
     10--
     11-- This copy is distributed in the hope that it will be useful,
     12-- but WITHOUT ANY WARRANTY; without even the implied warranty of
     13-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Please See the GNU
     14-- General Public License for more details.
     15--
     16-- You should have received a copy of the GNU General Public
     17-- License along with FFmpeg; if not, write to the Free Software
     18-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     19*/
     20
     21#ifndef _H264E_SDACCEL_H_
     22#define _H264E_SDACCEL_H_
     23
     24#include <stdbool.h>
     25#include <CL/opencl.h>
     26#include <CL/cl_ext.h>
     27#include "libavcodec/avcodec.h"
     28
     29struct _H264E_RSP_MSG;
     30typedef struct _H264E_RSP_MSG H264E_RSP_MSG;
     31
     32#ifdef H264E_DEBUG
     33    #define H264E_PROFILING
     34    #define H264EMSG(s) s
     35#else
     36    #define H264EMSG(s) ;
     37#endif
     38
     39#ifdef H264E_PROFILING
     40    #define H264ETIME(s) s
     41#else
     42    #define H264ETIME(s) ;
     43#endif
     44
     45typedef void* H264E_KERNEL_HANDLE;
     46#define H264E_PLANAR_PACKED     0
     47#define H264E_PLANAR_SEPARATED  1
     48#define H264E_INTERLEAVED_YC    2
     49#define H264E_INTERLEAVED_CY    3
     50#define H264E_MACROBLOCK        4
     51
     52typedef struct _H264E_USR {
     53    char*            pKernelBinFileName;
     54    char*            pDeviceName;
     55    char*            pKernelName;
     56    bool             bCLIsOK;
     57    cl_context        context;
     58    cl_command_queue  commands;
     59    cl_kernel         kernel;
     60    int               FrameX;
     61    int               FrameY;
     62    int               ScanFormat;
     63    int               PackPlanarSeparated;
     64    int               HWOptimizeScanFormat;
     65    int               Timescale;
     66    int               Nuit;
     67    int               Level;
     68    int               GOPLength;
     69    int               IntraRefreshCol;
     70    int               MBRowsPerSlice;
     71    int               DeblockingFilter;
     72    int               DBRestrict;
     73    int               MVRestrict;
     74    int               QPI;
     75    int               QPP;
     76    int               QPChrOffset;
     77    int               Bitrate;
     78    int               BUSize;
     79    int               RCFIFOSize;
     80    int               UseCABAC;
     81    void*             UserContext;
     82    bool              bUseUserContextAsCfg;
     83
     84} H264E_USR;
     85
     86typedef struct _H264E_TIME {
     87
     88    long int WriteDeviceBufferTime;
     89    long int ExecuteKernelTime;
     90    long int EncodeAndReadNALSizeTime;
     91    long int ReadNALBufferTime;
     92
     93    double   WriteDeviceBufferTimeMS;
     94    double   ExecuteKernelTimeMS;
     95    double   EncodeAndReadNALSizeTimeMS;
     96    double   ReadNALBufferTimeMS;
     97
     98    double   WriteDeviceBufferTotalTimeMS;
     99    double   ExecuteKernelTotalTimeMS;
     100    double   EncodeAndReadNALSizeTotalTimeMS;
     101    double   ReadNALBufferTotalTimeMS;
     102
     103    unsigned long int nFrames;
     104
     105} H264E_TIME;
     106
     107H264E_KERNEL_HANDLE h264eInit(const H264E_USR* ph264eUsr);
     108int                 h264eEnd (H264E_KERNEL_HANDLE h264eKernelHandle);
     109
     110int h264eEncodeFrame(H264E_KERNEL_HANDLE h264eKernelHandle,
     111                     char* pHostYBuffer,
     112                     char* pHostUBuffer,
     113                     char* pHostVBuffer,
     114                     char* pHostNALBuffer,
     115                     int   frame_count
     116                     );
     117
     118void h264eSendEncodeFrame(H264E_KERNEL_HANDLE h264eKernelHandle,
     119                          AVFrame *pic, char *pCurrentBuffer);
     120
     121int h264eRecvEncodeFrame(H264E_KERNEL_HANDLE h264eKernelHandle,
     122                                                 H264E_RSP_MSG           *rspMsg);
     123
     124const char* h264eReadStatusRegs(H264E_KERNEL_HANDLE h264eKernelHandle);
     125int               h264eSetUserContext(H264E_KERNEL_HANDLE h264eKernelHandle, void* Context);
     126void*       h264eGetUserContext(H264E_KERNEL_HANDLE h264eKernelHandle);
     127const H264E_TIME* h264eGetStats      (H264E_KERNEL_HANDLE h264eKernelHandle);
     128
     129#define H264E_OK                 0
     130#define H264E_END_ERR           -1
     131#define H264E_BAD_KERNEL_HANDLE -2
     132#define H264E_BAD_COMP_PTR      -3
     133#define H264E_BAD_NAL_PTR       -4
     134#define H264E_CORE_ERR          -5
     135#define H264E_INITSW_ERR        -6
     136#define H264E_INITHW_ERR        -7
     137#define H264E_DEVBUFF_ERR       -8
     138#define H264E_DEVBUFF_WR_ERR    -9
     139#define H264E_DEVBUFF_RD_ERR    -10
     140#define H264E_ARGSET_ERR        -11
     141#define H264E_EXEC_ERR          -12
     142#define H264E_CL_INIT_ERR       -13
     143#define H264E_CL_END_ERR        -14
     144#define H264E_DEFER_DATA        -15
     145
     146#endif // _H264E_SDACCEL_H_
  • new file libavcodec/xlnx_h264/h264e_sdaccel_private.h

    diff --git a/libavcodec/xlnx_h264/h264e_sdaccel_private.h b/libavcodec/xlnx_h264/h264e_sdaccel_private.h
    new file mode 100644
    index 0000000..e9db942
    - +  
     1/*
     2-- Copyright notice:
     3-- Copyright (c) 2017 Alma Technologies S.A.
     4-- www.alma-technologies.com
     5-- All rights reserved worldwide.
     6
     7-- This copy is made available under the terms of the GNU General Public
     8-- License version 2.1 as published by the Free Software Foundation; either
     9-- version 2.1 of the License, or (at your option) any later version.
     10--
     11-- This copy is distributed in the hope that it will be useful,
     12-- but WITHOUT ANY WARRANTY; without even the implied warranty of
     13-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Please See the GNU
     14-- General Public License for more details.
     15--
     16-- You should have received a copy of the GNU General Public
     17-- License along with FFmpeg; if not, write to the Free Software
     18-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     19*/
     20
     21#ifndef _H264E_SDACCEL_PRIVATE_H_
     22#define _H264E_SDACCEL_PRIVATE_H_
     23
     24#include <CL/opencl.h>
     25#include <pthread.h>
     26#include <libavutil/threadmessage.h>
     27#include "libavcodec/avcodec.h"
     28#include "h264e_sdaccel.h"
     29
     30#define CLEAR_RT          0
     31#define CONTROL_RT        1
     32#define STATUS_RT         2
     33#define CONTROL_STATUS_RT 3
     34#define CONTROL_ENCODE_RT 4
     35#define ENCODE_RT         5
     36#define TEST0_RT          6
     37#define TEST1_RT          7
     38#define NO_CHANGE_FRMT                     0
     39#define PLANAR_TO_INTERLEAVED_FRMT         1
     40#define INTERLEAVED_YC_TO_INTERLEAVED_FRMT 2
     41#define INTERLEAVED_CY_TO_INTERLEAVED_FRMT 3
     42
     43typedef struct _H264E_CL {
     44
     45    char*            pDeviceName;
     46    char*            pKernelBinFileName;
     47    char             pKernelName[64];
     48    cl_platform_id   platform_id;
     49    cl_device_id     device_id;
     50    cl_context       context;
     51    cl_command_queue commands;
     52    cl_program       program;
     53    cl_kernel        kernel;
     54    cl_event         kernel_event;
     55        int              kernel_num;
     56    bool             bCLIsOK;
     57    bool             bWRDeviceBufferFailed;
     58    bool             bRDDeviceBufferFailed;
     59    bool             bSetKernelArgsFailed;
     60    bool             bExecuteKernelFailed;
     61
     62} H264E_CL;
     63
     64typedef struct _H264E_CNTX {
     65
     66    cl_mem DeviceBuffer;
     67    int    DeviceBufferSizeInBytes;
     68    int    CRegsPtr;
     69    int    SRegsPtr;
     70    int    VDataIdx;
     71    int    VDataPtr[2];
     72    int    NALPtr;
     73    int    Format;
     74    char   CRegsFile[256];
     75    char   SRegsFile[256];
     76    char*  pPackedPlanarHostBuffer;
     77
     78} H264E_CNTX;
     79
     80typedef struct _H264E_KCFG {
     81
     82    H264E_USR                    h264eUsr;
     83    H264E_CL                     h264eCL;
     84    H264E_CNTX                   h264eCntx;
     85    H264E_TIME           h264eTime;
     86        pthread_t                        h264eThread;
     87        AVThreadMessageQueue *h264eReqMsgQ;
     88        AVThreadMessageQueue *h264eRspMsgQ;
     89
     90} H264E_KCFG;
     91
     92typedef struct _H264E_REQ_MSG {
     93        char    *pHostYBuffer;
     94        char    *pHostUBuffer;
     95        char    *pHostVBuffer;
     96        char    *pHostNALBuffer;
     97        AVFrame *pFrame;
     98        int              endThread;
     99} H264E_REQ_MSG;
     100
     101typedef struct _H264E_RSP_MSG {
     102        int              NalSizeInBytes;
     103        char    *pHostNALBuffer;
     104        AVFrame *pFrame;
     105} H264E_RSP_MSG;
     106
     107#endif // _H264E_SDACCEL_PRIVATE_H_
  • new file libavcodec/xlnx_h264/h264e_sdaccel_utils.c

    diff --git a/libavcodec/xlnx_h264/h264e_sdaccel_utils.c b/libavcodec/xlnx_h264/h264e_sdaccel_utils.c
    new file mode 100644
    index 0000000..562a395
    - +  
     1/*
     2-- Copyright notice:
     3-- Copyright (c) 2017 Alma Technologies S.A.
     4-- www.alma-technologies.com
     5-- All rights reserved worldwide.
     6
     7-- This copy is made available under the terms of the GNU General Public
     8-- License version 2.1 as published by the Free Software Foundation; either
     9-- version 2.1 of the License, or (at your option) any later version.
     10--
     11-- This copy is distributed in the hope that it will be useful,
     12-- but WITHOUT ANY WARRANTY; without even the implied warranty of
     13-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Please See the GNU
     14-- General Public License for more details.
     15--
     16-- You should have received a copy of the GNU General Public
     17-- License along with FFmpeg; if not, write to the Free Software
     18-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     19*/
     20
     21#include <stdio.h>
     22#include <stdlib.h>
     23#include <string.h>
     24#include <pthread.h>
     25#include "libavutil/log.h"
     26#include "h264e_sdaccel.h"
     27#include "h264e_sdaccel_utils.h"
     28
     29static pthread_mutex_t g_cl_mutex = PTHREAD_MUTEX_INITIALIZER;
     30static cl_program      g_cl_program;
     31static int             g_is_loaded = 0;
     32
     33#define TARGET_DEVICE "xilinx:xil-accel-rd-vu9p:4ddr-xpr:4.1"
     34
     35#if defined(SDX_PLATFORM) && !defined(TARGET_DEVICE)
     36   #define STR_VALUE(arg)   #arg
     37   #define GET_STRING(name) STR_VALUE(name)
     38   #define TARGET_DEVICE    GET_STRING(SDX_PLATFORM)
     39#endif
     40
     41int load_file_to_memory(const char *filename, unsigned char **result);
     42
     43int h264e_cl_init(H264E_CL* ph264eCL)
     44{
     45    char             cl_platform_vendor[1001];
     46    char             target_device_name[2048];
     47    char             kernel_name[2048];
     48   cl_platform_id   platform_id;
     49   cl_device_id     device_id;
     50   cl_context       context;
     51   cl_command_queue commands;
     52   cl_kernel        kernel;
     53    cl_int           err;
     54    const char* default_target_device_name = TARGET_DEVICE;
     55    const char* default_kernel_name        = "ALMA_H264_E_KERNEL";
     56   ph264eCL->bCLIsOK = false;
     57    if(ph264eCL->pDeviceName != NULL)
     58   {
     59        strcpy(target_device_name, ph264eCL->pDeviceName);
     60   }
     61    else
     62    {
     63        strcpy(target_device_name, default_target_device_name);
     64    }
     65    if(ph264eCL->pKernelName != NULL)
     66    {
     67        strcpy(kernel_name, ph264eCL->pKernelName);
     68    }
     69    else
     70    {
     71        strcpy(kernel_name, default_kernel_name);
     72    }
     73   cl_platform_id platforms[16];
     74   cl_uint        platform_count;
     75   int            platform_found = 0;
     76   err = clGetPlatformIDs(16, platforms, &platform_count);
     77   if(err != CL_SUCCESS)
     78   {
     79      H264EMSG(printf("ERROR: Failed to find an OpenCL platform\n"));
     80        return H264E_CL_INIT_ERR;
     81   }
     82   H264EMSG(printf("INFO: Found %d platforms\n", platform_count));
     83   for(unsigned int iplat=0; iplat<platform_count; iplat++)
     84   {
     85      err = clGetPlatformInfo(platforms[iplat], CL_PLATFORM_VENDOR, 1000, (void *)cl_platform_vendor,NULL);
     86
     87      if(err != CL_SUCCESS)
     88      {
     89            H264EMSG(printf("ERROR: clGetPlatformInfo(CL_PLATFORM_VENDOR) failed\n"));
     90            return H264E_CL_INIT_ERR;
     91      }
     92
     93      if(strcmp(cl_platform_vendor, "Xilinx") == 0)
     94      {
     95         H264EMSG(printf("INFO: Selected platform %d from %s\n", iplat, cl_platform_vendor));
     96         platform_id = platforms[iplat];
     97         platform_found = 1;
     98      }
     99   }
     100   if(!platform_found)
     101   {
     102      H264EMSG(printf("ERROR: Platform Xilinx not found\n"));
     103        return H264E_CL_INIT_ERR;
     104   }
     105   cl_uint      num_devices;
     106   unsigned int device_found = 0;
     107   cl_device_id devices[16];
     108   char         cl_device_name[1001];
     109   err = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_ACCELERATOR, 16, devices, &num_devices);
     110   if(err != CL_SUCCESS)
     111   {
     112      H264EMSG(printf("ERROR: Failed to create a device group\n"));
     113        return H264E_CL_INIT_ERR;
     114   }
     115   for(unsigned int i=0; i<num_devices; i++)
     116   {
     117      err = clGetDeviceInfo(devices[i], CL_DEVICE_NAME, 1024, cl_device_name, 0);
     118
     119      if(err != CL_SUCCESS)
     120      {
     121         H264EMSG(printf("ERROR: Failed to get device name for device %d\n", i));
     122            return H264E_CL_INIT_ERR;
     123      }
     124      else
     125      {
     126         H264EMSG(printf("INFO: CL_DEVICE_NAME[%d / %d] = %s\n", i, num_devices, cl_device_name));
     127      }
     128
     129      if(strcmp(cl_device_name, target_device_name) == 0)
     130      {
     131         device_id = devices[i];
     132         device_found = 1;
     133         H264EMSG(printf("INFO: Selected %s as the target device\n", cl_device_name));
     134      }
     135   }
     136   if(!device_found)
     137   {
     138      H264EMSG(printf("ERROR: Target device %s not found\n", target_device_name));
     139        return H264E_CL_INIT_ERR;
     140   }
     141   context = clCreateContext(0, 1, &device_id, NULL, NULL, &err);
     142   if(!context)
     143   {
     144      H264EMSG(printf("ERROR: Failed to create a compute context\n"));
     145        return H264E_CL_INIT_ERR;
     146   }
     147   commands = clCreateCommandQueue(context, device_id, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE, &err);
     148   if(!commands)
     149   {
     150      H264EMSG(printf("ERROR: Failed to create commands queue\n"));
     151      return H264E_CL_INIT_ERR;
     152   }
     153   pthread_mutex_lock(&g_cl_mutex);
     154   cl_int status;
     155   unsigned char *kernelbinary;
     156   if (!g_is_loaded)
     157   {
     158                H264EMSG(printf("INFO: loading kernel binary %s\n", ph264eCL->pKernelFileName));
     159        int n_i0 = load_file_to_memory(ph264eCL->pKernelBinFileName, (unsigned char **) &kernelbinary);
     160        if(n_i0 < 0)
     161        {
     162            H264EMSG(printf("ERROR: failed to load kernel binary from: %s\n", ph264eCL->pKernelBinFileName));
     163            return H264E_CL_INIT_ERR;
     164        }
     165        size_t n0 = n_i0;
     166            g_cl_program = clCreateProgramWithBinary(context,
     167                                                                                                 1,
     168                                                                                                 &device_id,
     169                                                                                                 &n0,
     170                                                                                                 (const unsigned char **) &kernelbinary,
     171                                                                                                 &status,
     172                                                                                                 &err);
     173                if((!g_cl_program) || (err!=CL_SUCCESS))
     174                {
     175                        H264EMSG(printf("ERROR: Failed to create compute program from binary %d\n", err));
     176            return H264E_CL_INIT_ERR;
     177                }
     178            free(kernelbinary);
     179                err = clBuildProgram(g_cl_program, 0, NULL, NULL, NULL, NULL);
     180                if(err != CL_SUCCESS)
     181                {
     182                        size_t len;
     183                        char   buffer[2048];
     184
     185                        H264EMSG(printf("ERROR: Failed to build program executable\n"));
     186                        clGetProgramBuildInfo(g_cl_program, device_id, CL_PROGRAM_BUILD_LOG, sizeof(buffer), buffer, &len);
     187                        H264EMSG(printf("%s\n", buffer));
     188            return H264E_CL_INIT_ERR;
     189                }
     190                        g_is_loaded = 1;
     191                }
     192                else
     193                {
     194                        clRetainProgram(g_cl_program);
     195                }
     196                pthread_mutex_unlock(&g_cl_mutex);
     197            kernel = clCreateKernel(g_cl_program, ph264eCL->pKernelName, &err);
     198   if(!kernel || err != CL_SUCCESS)
     199   {
     200      H264EMSG(printf("ERROR: Failed to create compute kernel\n"));
     201      return -1;
     202   }
     203   ph264eCL->platform_id = platform_id;
     204   ph264eCL->device_id   = device_id;
     205   ph264eCL->context     = context;
     206   ph264eCL->commands    = commands;
     207   ph264eCL->program     = g_cl_program;
     208   ph264eCL->kernel      = kernel;
     209   ph264eCL->bCLIsOK     = true;
     210    return H264E_OK;
     211}
     212
     213int h264e_cl_end(H264E_CL* ph264eCL)
     214{
     215    cl_int err;
     216    int    retval = H264E_OK;
     217    err = clReleaseProgram(ph264eCL->program);
     218    if(err != CL_SUCCESS)
     219    {
     220        H264EMSG(printf("ERROR: Failed to release program\n"));
     221        retval = H264E_CL_END_ERR;
     222    }
     223    else
     224    {
     225        H264EMSG(printf("INFO: Released program\n"));
     226    }
     227   clReleaseKernel(ph264eCL->kernel);
     228    if(err != CL_SUCCESS)
     229    {
     230        H264EMSG(printf("ERROR: Failed to release kernel\n"));
     231        retval = H264E_CL_END_ERR;
     232    }
     233    else
     234    {
     235        H264EMSG(printf("INFO: Released kernel\n"));
     236    }
     237   clReleaseCommandQueue(ph264eCL->commands);
     238    if(err != CL_SUCCESS)
     239    {
     240        H264EMSG(printf("ERROR: Failed to release commands queue\n"));
     241        retval = H264E_CL_END_ERR;
     242    }
     243    else
     244    {
     245        H264EMSG(printf("INFO: Released commands queue\n"));
     246    }
     247   clReleaseContext(ph264eCL->context);
     248    if(err != CL_SUCCESS)
     249    {
     250        H264EMSG(printf("ERROR: Failed to release context\n"));
     251        retval = H264E_CL_END_ERR;
     252    }
     253    else
     254    {
     255        H264EMSG(printf("INFO: Released context\n"));
     256    }
     257    clReleaseDevice(ph264eCL->device_id);
     258    if(err != CL_SUCCESS)
     259    {
     260        H264EMSG(printf("ERROR: Failed to release device\n"));
     261        retval = H264E_CL_END_ERR;
     262    }
     263    else
     264    {
     265        H264EMSG(printf("INFO: Released device\n"));
     266}
     267    return retval;
     268}
     269
     270int load_file_to_memory(const char *filename, unsigned char **result)
     271{
     272   int size = 0;
     273   FILE *f = fopen(filename, "rb");
     274   if(f == NULL)
     275   {
     276       *result = NULL;
     277        return -1; // -1 means file opening fail
     278   }
     279   fseek(f, 0, SEEK_END);
     280   size = ftell(f);
     281   fseek(f, 0, SEEK_SET);
     282   *result = malloc(size);
     283   if(size != fread(*result, sizeof(char), size, f))
     284   {
     285      free(*result);
     286      return -2; // -2 means file reading fail
     287   }
     288   fclose(f);
     289   return size;
     290 }
  • new file libavcodec/xlnx_h264/h264e_sdaccel_utils.h

    diff --git a/libavcodec/xlnx_h264/h264e_sdaccel_utils.h b/libavcodec/xlnx_h264/h264e_sdaccel_utils.h
    new file mode 100644
    index 0000000..ebaad55
    - +  
     1/*
     2-- Copyright notice:
     3-- Copyright (c) 2017 Alma Technologies S.A.
     4-- www.alma-technologies.com
     5-- All rights reserved worldwide.
     6
     7-- This copy is made available under the terms of the GNU General Public
     8-- License version 2.1 as published by the Free Software Foundation; either
     9-- version 2.1 of the License, or (at your option) any later version.
     10--
     11-- This copy is distributed in the hope that it will be useful,
     12-- but WITHOUT ANY WARRANTY; without even the implied warranty of
     13-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Please See the GNU
     14-- General Public License for more details.
     15--
     16-- You should have received a copy of the GNU General Public
     17-- License along with FFmpeg; if not, write to the Free Software
     18-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     19*/
     20
     21#ifndef _H264E_SDACCEL_UTILS_H_
     22#define _H264E_SDACCEL_UTILS_H_
     23
     24#include "h264e_sdaccel_private.h"
     25
     26int h264e_cl_init(H264E_CL* ph264eCL);
     27int h264e_cl_end (H264E_CL* ph264eCL);
     28
     29#endif // _H264E_SDACCEL_UTILS_H_
  • new file libavcodec/xlnx_h264/hw_h264.c

    diff --git a/libavcodec/xlnx_h264/hw_h264.c b/libavcodec/xlnx_h264/hw_h264.c
    new file mode 100644
    index 0000000..e2571f0
    - +  
     1/*
     2-- Copyright notice:
     3-- Copyright (c) 2017 Alma Technologies S.A.
     4-- www.alma-technologies.com
     5-- All rights reserved worldwide.
     6
     7-- This copy is made available under the terms of the GNU General Public
     8-- License version 2.1 as published by the Free Software Foundation; either
     9-- version 2.1 of the License, or (at your option) any later version.
     10--
     11-- This copy is distributed in the hope that it will be useful,
     12-- but WITHOUT ANY WARRANTY; without even the implied warranty of
     13-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Please See the GNU
     14-- General Public License for more details.
     15--
     16-- You should have received a copy of the GNU General Public
     17-- License along with FFmpeg; if not, write to the Free Software
     18-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     19*/
     20
     21#include <inttypes.h>
     22#include <stdlib.h>
     23#include <linux/limits.h>
     24#include <unistd.h>
     25#include <string.h>
     26#include <assert.h>
     27#include "libavutil/opencl.h"
     28#include "libavutil/log.h"
     29#include "h264e_sdaccel.h"
     30#include "h264e_sdaccel_private.h"
     31#include "h264e_csregs.h"
     32#include "xlnx_h264_config.h"
     33
     34void ff_init_h264_xlnx_hw(AVCodecContext *avctx)
     35{
     36    H264E_USR           h264eUsr;
     37        unsigned char* xcl_path = getenv("XLNX_XCLBIN_PATH");
     38        if (NULL == xcl_path)
     39        {
     40       av_log(NULL, AV_LOG_INFO, " * XLNX_XCLBIN_PATH not found\n");
     41       return;
     42        }
     43        char *xcl_fullpath = malloc(PATH_MAX);
     44        snprintf(xcl_fullpath, PATH_MAX, "%s/h264_8k1c.xclbin", xcl_path);
     45        h264eUsr.pKernelBinFileName   = xcl_fullpath;
     46        h264eUsr.pDeviceName              = "xilinx:xil-accel-rd-vu9p:4ddr-xpr:4.1";
     47        h264eUsr.pKernelName              = "ALMA_H264_E_KERNEL";
     48    h264eUsr.bCLIsOK              = false;
     49    h264eUsr.FrameX               = avctx->width;
     50    h264eUsr.FrameY               = avctx->height;
     51    h264eUsr.ScanFormat           = H264E_PLANAR_SEPARATED;
     52    h264eUsr.PackPlanarSeparated  = 0;
     53    h264eUsr.HWOptimizeScanFormat = 1;
     54        h264eUsr.Timescale                = 60000;
     55        h264eUsr.Nuit                 = 1000;
     56        h264eUsr.Level                = 42;
     57        h264eUsr.GOPLength                = avctx->gop_size;
     58        h264eUsr.IntraRefreshCol      = -1;
     59        h264eUsr.MBRowsPerSlice       = -1;
     60        h264eUsr.DeblockingFilter     = -1;
     61        h264eUsr.DBRestrict           = -1;
     62        h264eUsr.MVRestrict           = -1;
     63        h264eUsr.QPI                  = avctx->global_quality;
     64        h264eUsr.QPP                  = avctx->global_quality;
     65        h264eUsr.QPChrOffset          = -1;
     66        h264eUsr.Bitrate              = (avctx->bit_rate)/1000;
     67        h264eUsr.BUSize               = -1;
     68        h264eUsr.RCFIFOSize           = -1;
     69        h264eUsr.UseCABAC             = -1;
     70    h264eUsr.bUseUserContextAsCfg = false;
     71    avctx->priv_data = h264eInit(&h264eUsr);
     72}
     73
     74void h264eSendEncodeFrame(H264E_KERNEL_HANDLE h264eKernelHandle,
     75                                                  AVFrame *pic, char *pCurrentBuffer)
     76{
     77        H264E_KCFG *ph264eKCFG = (H264E_KCFG*)h264eKernelHandle;
     78        H264E_REQ_MSG reqMsg;
     79        reqMsg.pHostYBuffer = pic->data[Y];
     80        reqMsg.pHostUBuffer = pic->data[U];
     81        reqMsg.pHostVBuffer = pic->data[V];
     82        reqMsg.pHostNALBuffer = pCurrentBuffer;
     83        reqMsg.pFrame           = pic;
     84        reqMsg.endThread        = 0;
     85        av_thread_message_queue_send(ph264eKCFG->h264eReqMsgQ, &reqMsg, 0);
     86}
     87
     88int h264eRecvEncodeFrame(H264E_KERNEL_HANDLE h264eKernelHandle,
     89                                                 H264E_RSP_MSG          *rsp)
     90{
     91        H264E_KCFG *ph264eKCFG = (H264E_KCFG*)h264eKernelHandle;
     92        int rc;
     93        rc = av_thread_message_queue_recv(ph264eKCFG->h264eRspMsgQ, rsp,
     94                                                                  AV_THREAD_MESSAGE_NONBLOCK);
     95        if (rc == AVERROR(EAGAIN))
     96                return 0;
     97        return 1;
     98}
     99
     100void ff_uninit_h264_xlnx_hw(AVCodecContext *avctx)
     101{
     102   h264eEnd(avctx->priv_data);
     103}
     104
     105
  • new file libavcodec/xlnx_h264/xlnx_h264_config.h

    diff --git a/libavcodec/xlnx_h264/xlnx_h264_config.h b/libavcodec/xlnx_h264/xlnx_h264_config.h
    new file mode 100644
    index 0000000..517b3e5
    - +  
     1/*
     2-- Copyright notice:
     3-- Copyright (c) 2017 Alma Technologies S.A.
     4-- www.alma-technologies.com
     5-- All rights reserved worldwide.
     6
     7-- This copy is made available under the terms of the GNU General Public
     8-- License version 2.1 as published by the Free Software Foundation; either
     9-- version 2.1 of the License, or (at your option) any later version.
     10--
     11-- This copy is distributed in the hope that it will be useful,
     12-- but WITHOUT ANY WARRANTY; without even the implied warranty of
     13-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Please See the GNU
     14-- General Public License for more details.
     15--
     16-- You should have received a copy of the GNU General Public
     17-- License along with FFmpeg; if not, write to the Free Software
     18-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     19*/
     20
     21#ifndef _XLNX_H264_CONFIG_H_
     22#define _XLNX_H264_CONFIG_H_
     23
     24#include "libavcodec/avcodec.h"
     25
     26#define OCLCHECK(method, ... )                                                 \
     27do {                                                                           \
     28    status = method(__VA_ARGS__);                                              \
     29    if (status != CL_SUCCESS) {                                                \
     30        av_log(NULL, AV_LOG_ERROR, # method " error '%s'\n",                   \
     31               av_opencl_errstr(status));                                      \
     32        return;                                                                \
     33    }                                                                          \
     34} while (0)
     35
     36#define OCLCHECK1(method, ... )                                                \
     37do {                                                                           \
     38    status = method(__VA_ARGS__);                                              \
     39    if (status != CL_SUCCESS) {                                                \
     40        av_log(NULL, AV_LOG_ERROR, # method " error '%s'\n",                   \
     41               av_opencl_errstr(status));                                      \
     42        return AVERROR_EXTERNAL;                                               \
     43    }                                                                          \
     44} while (0)
     45
     46#define CREATEBUF(out, flags, size)                                            \
     47do {                                                                           \
     48    out = clCreateBuffer(cl_env->context, flags, size, NULL, &status);         \
     49    if (status != CL_SUCCESS) {                                                \
     50        av_log(NULL, AV_LOG_ERROR, "Could not create OpenCL buffer\n");        \
     51        return;                                                                \
     52    }                                                                          \
     53} while (0)
     54
     55typedef enum
     56{
     57        Y = 0,
     58        U = 1,
     59        V = 2
     60}col_fmt_t;
     61
     62void ff_init_h264_xlnx_hw(AVCodecContext *c);
     63void ff_uninit_h264_xlnx_hw(AVCodecContext *c);
     64uint8_t *ff_h264_xlnx_hw(AVCodecContext *avctx, AVFrame *pic,
     65                                           char *pCurrentBuffer, uint32_t *dstSize);
     66
     67#endif //_XLNX_H264_CONFIG_H_
  • new file libavcodec/xlnx_h264_enc.c

    diff --git a/libavcodec/xlnx_h264_enc.c b/libavcodec/xlnx_h264_enc.c
    new file mode 100644
    index 0000000..97f85a5
    - +  
     1/*
     2 * Xilinx H.264 Alma encoder
     3 *
     4 * Copyright (C) 2017 Xilinx Inc.
     5 *
     6 * This file is part of FFmpeg.
     7 *
     8 * FFmpeg is free software; you can redistribute it and/or
     9 * modify it under the terms of the GNU Lesser General Public
     10 * License as published by the Free Software Foundation; either
     11 * version 2.1 of the License, or (at your option) any later version.
     12 *
     13 * FFmpeg is distributed in the hope that it will be useful,
     14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     16 * Lesser General Public License for more details.
     17 *
     18 * You should have received a copy of the GNU Lesser General Public
     19 * License along with FFmpeg; if not, write to the Free Software
     20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     21 */
     22#include <stdio.h>
     23#include "avcodec.h"
     24#include "internal.h"
     25#include "xlnx_h264/xlnx_h264_config.h"
     26#include "xlnx_h264/h264e_sdaccel_private.h"
     27
     28static int xlnx_h264_encode_init(AVCodecContext *avctx)
     29{
     30    //printf("xlnx_h264_encode_init IN\n");
     31    switch(avctx->pix_fmt)
     32    {
     33         case AV_PIX_FMT_YUV420P:
     34            avctx->bits_per_raw_sample = 8;
     35            break;
     36         default:
     37            av_log(NULL, AV_LOG_ERROR,"ERROR: Pixel format not supported...\n");
     38            return AVERROR(EINVAL);
     39            break;
     40    }
     41    ff_init_h264_xlnx_hw(avctx);
     42    return 0;
     43}
     44
     45static int xlnx_h264_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pic, int *got_packet)
     46{
     47
     48    //av_log(NULL, AV_LOG_DEBUG, "xlnx_h264_encode_frame IN\n");
     49    int EntrySize = avctx->bits_per_raw_sample == 8 ? 1 : 2;
     50    int EntryCount = 0;
     51    uint64_t EncodeBuffSize = 0;
     52        uint8_t *pBuffer = NULL;
     53        AVFrame *pFrame;
     54        H264E_RSP_MSG   rspMsg;
     55        int             rc;
     56
     57        if (!pic)
     58        {
     59                *got_packet = 0;
     60                return 0;
     61        }
     62
     63    switch(pic->format)
     64    {
     65        case AV_PIX_FMT_YUV420P:
     66            EntryCount = 2;
     67            break;
     68        default:
     69            av_log(NULL, AV_LOG_ERROR,"Error. Encoding unknown pixel format.\n");
     70            return AVERROR_INVALIDDATA;
     71            break;
     72    }
     73   
     74        pFrame = av_frame_clone(pic);
     75    EncodeBuffSize = EntryCount * (pic->width) * (pic->height) * EntrySize;
     76
     77        pBuffer = av_malloc(EncodeBuffSize);
     78
     79        // Send the encode request
     80        h264eSendEncodeFrame(avctx->priv_data, pFrame, pBuffer);
     81
     82        // Check if the encode has completed
     83        rc = h264eRecvEncodeFrame(avctx->priv_data, &rspMsg);
     84
     85        if (rc == 1)
     86        {
     87                *got_packet = 1;
     88                av_packet_from_data(pkt, rspMsg.pHostNALBuffer,
     89                                                        rspMsg.NalSizeInBytes);
     90                pkt->pts = pkt->dts = (int64_t)rspMsg.pFrame->pts;
     91                av_frame_unref(rspMsg.pFrame);
     92                av_frame_free(&rspMsg.pFrame);
     93        }
     94        else
     95        {
     96        *got_packet = 0;
     97        }
     98       
     99    return 0;
     100}
     101
     102static int xlnx_h264_encode_close(AVCodecContext *avctx)
     103{
     104    printf("xlnx_h264_encode_close IN\n");
     105    ff_uninit_h264_xlnx_hw(avctx);
     106    return 0;
     107}
     108
     109AVCodec ff_xlnx_h264_encoder = {
     110    .name           = "xlnx_h264_enc",
     111    .long_name      = NULL_IF_CONFIG_SMALL("Xilinx Advanced Video Codec (H.264) Encoder"),
     112    .type           = AVMEDIA_TYPE_VIDEO,
     113    .id             = AV_CODEC_ID_H264,
     114        .priv_data_size = sizeof(H264E_KCFG),
     115    .init           = xlnx_h264_encode_init,
     116    .encode2        = xlnx_h264_encode_frame,
     117    .close          = xlnx_h264_encode_close,
     118    .capabilities   = CODEC_CAP_DR1 | CODEC_CAP_DELAY,
     119    .pix_fmts       = (const enum AVPixelFormat[]) {
     120                                      AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE
     121                                  },
     122};
  • new file libavcodec/xlnx_hevc/Makefile

    diff --git a/libavcodec/xlnx_hevc/Makefile b/libavcodec/xlnx_hevc/Makefile
    new file mode 100644
    index 0000000..b32df98
    - +  
     1OBJS                            += xlnx_hevc/hw_hevc.o
  • new file libavcodec/xlnx_hevc/hw_hevc.c

    diff --git a/libavcodec/xlnx_hevc/hw_hevc.c b/libavcodec/xlnx_hevc/hw_hevc.c
    new file mode 100644
    index 0000000..a35da42
    - +  
     1//
     2// NOTE: currently using ICD for DSA 2.0 50Mhz ...
     3// TODO: update this when new DSA is available
     4//
     5
     6#include <inttypes.h>
     7#include <stdlib.h>
     8#include <linux/limits.h>
     9#include <unistd.h>
     10#include "libavutil/opencl.h"
     11#include "libavutil/log.h"
     12#include "xlnx_hevc_config.h"
     13
     14// Header based loading
     15//#include "opencl_image.h"
     16
     17//Globals - for opencl
     18static AVOpenCLExternalEnv *cl_env;
     19static cl_kernel kernel = NULL;
     20static cl_program program = NULL;
     21
     22// OpenCL Buffers
     23static cl_mem CSR3_INPUT_FP_Y_V;
     24static cl_mem CSR4_INPUT_FP_U_V;
     25static cl_mem CSR5_INPUT_FP_V_V;
     26static cl_mem CSR6_NEXT_FP_Y_V;
     27static cl_mem CSR7_NEXT_FP_U_V;
     28static cl_mem CSR8_NEXT_FP_V_V;
     29static cl_mem CSR12_RECON_BASE_V;
     30static cl_mem CSR13_BITSTREAM_BASE_V;
     31static cl_mem CSR14_BITSTREAM_LEN_V;
     32
     33static cl_int status;
     34static unsigned int CurSourceImageSize[3] = { 0, 0, 0 };
     35static unsigned int EncodedFrameSize = 0;
     36static unsigned int EncodedFrameLengthSize = 0;
     37static int frameNumber = 0;
     38
     39int load_file_to_memory_hevc(const char *filename, unsigned char **result);
     40
     41//
     42// HEVC init function
     43//
     44void ff_init_hevc_xlnx_hw(AVCodecContext *avctx)
     45{
     46    unsigned char *kernelbinary = 0;
     47    size_t kernel_len = 0;
     48    AVOpenCLDeviceList *device_list;
     49    AVOpenCLDeviceNode *device_node = NULL;
     50    cl_context_properties cps[3];
     51    int i;
     52    int nb_devices;
     53    int arg = 0;
     54    // Header based loading (opencl_image.h)
     55    //kernelbinary = hevc_xclbin;
     56    //kernel_len = hevc_xclbin_len;
     57
     58    //
     59    // Setup NGCodec HEVC core defaults
     60    //
     61    unsigned int CSR1_FRAME_WIDTH_V = avctx->width;
     62    unsigned int CSR2_FRAME_HEIGHT_V = avctx->height;
     63    unsigned int CSR9_BITRATE_V = 0;
     64    unsigned int CSR10_FIXED_QP_V = 0;
     65    unsigned int CSR11_INTRA_PERIOD_V = avctx->gop_size;
     66    unsigned int CSR15_RESET_ENCODER_V = 0;
     67
     68    av_log(NULL, AV_LOG_INFO, " * Xilinx HEVC HW accelerator init ***\n");
     69    if (avctx->bit_rate > 0)
     70    {
     71         // Constant bitrate mode
     72         CSR9_BITRATE_V = avctx->bit_rate;
     73         av_log(NULL, AV_LOG_INFO, " * Encoding in constant bitrate mode***\n");
     74    }
     75    else
     76    {
     77         // Fixed QP mode
     78         CSR10_FIXED_QP_V = avctx->global_quality;
     79         av_log(NULL, AV_LOG_INFO, " * Encoding in fixed QP mode***\n");
     80    }
     81
     82    //
     83    // Setup OpenCL context
     84    //
     85    cl_env = av_opencl_alloc_external_env();
     86    cl_platform_id platforms[16] = { 0 };
     87        cl_device_id devices[16];
     88        char platformName[256];
     89        char deviceName[256];
     90        cl_uint platformCount = 0;
     91        cl_int err = clGetPlatformIDs(0, 0, &platformCount);
     92        err = clGetPlatformIDs(16, platforms, &platformCount);
     93        if (err != CL_SUCCESS) {
     94                //printf("%s\n", oclErrorCode(err));
     95                return;// hardware;
     96    }
     97        cl_env->device_type = CL_DEVICE_TYPE_ACCELERATOR;
     98    for (cl_uint i = 0; i < platformCount; i++) {
     99                err = clGetPlatformInfo(platforms[i], CL_PLATFORM_NAME, 256, platformName, 0);
     100                if (err != CL_SUCCESS) {
     101                        //printf("%s\n", oclErrorCode(err));
     102                        return;// hardware;
     103                }
     104                cl_uint deviceCount = 0;
     105                err = clGetDeviceIDs(platforms[i], cl_env->device_type, 16, devices, &deviceCount);
     106                if ((err != CL_SUCCESS) || (deviceCount == 0)) {
     107                        continue;
     108                }
     109
     110                err = clGetDeviceInfo(devices[0], CL_DEVICE_NAME, 256, deviceName, 0);
     111                if (err != CL_SUCCESS) {
     112                        //printf("%s\n", oclErrorCode(err));
     113                        return;// hardware;
     114                }
     115
     116                cl_context_properties contextData[3] = {CL_CONTEXT_PLATFORM, (cl_context_properties)platforms[i], 0};
     117                cl_context context = clCreateContextFromType(contextData, cl_env->device_type, 0, 0, &err);
     118                if (err != CL_SUCCESS) {
     119                        continue;
     120                }
     121                cl_command_queue queue = clCreateCommandQueue(context, devices[0], 0, &err);
     122                if (err != CL_SUCCESS) {
     123                        //printf("%s\n", oclErrorCode(err));
     124                        return; //hardware;
     125                }
     126                cl_env->platform_id = platforms[i];
     127                cl_env->context = context;
     128                cl_env->command_queue = queue;
     129                cl_env->device_type = CL_DEVICE_TYPE_ACCELERATOR;
     130        cl_env->device_id = devices[0];
     131        break;
     132        }
     133
     134    //
     135    // Create the program
     136    //
     137        unsigned char* xcl_path = getenv("XLNX_XCLBIN_PATH");
     138        if (NULL == xcl_path)
     139        {
     140       av_log(NULL, AV_LOG_INFO, " * XLNX_XCLBIN_PATH not found\n");
     141       return;
     142        }
     143   
     144        char xcl_fullpath[PATH_MAX];
     145        snprintf(xcl_fullpath, sizeof(xcl_fullpath), "%s/hevc_1k1c.xclbin", xcl_path);
     146    av_log(NULL, AV_LOG_INFO, " * loading kernel from file %s\n", xcl_fullpath);
     147        load_file_to_memory_hevc(xcl_fullpath, &kernelbinary);
     148    program = clCreateProgramWithBinary(cl_env->context, 1, &(cl_env->device_id),
     149                   &kernel_len, (const unsigned char**)&kernelbinary, &status, NULL);
     150    if( status != CL_SUCCESS || !program )
     151    {
     152        av_log(NULL, AV_LOG_ERROR, "OpenCL unable to create fpga accelerator program\n");
     153        return;
     154    }
     155
     156    //
     157    // Build the program
     158    //
     159    av_log(NULL, AV_LOG_INFO," * Building the program\n");
     160    status = clBuildProgram(program, 1, &(cl_env->device_id), NULL, NULL, NULL);
     161    if( status != CL_SUCCESS )
     162    {
     163        av_log(NULL, AV_LOG_ERROR, "OpenCL unable to build program\n");
     164        return;
     165    }
     166
     167    //
     168    // Create the kernel
     169    //
     170    av_log(NULL, AV_LOG_INFO," * Creating the HEVC kernel\n");
     171    kernel = clCreateKernel(program, "krnl_ngcodec_hevc_0", &status);   //"HEVC_kernel"
     172    if( status != CL_SUCCESS )
     173    {
     174        av_log(NULL, AV_LOG_ERROR, "OpenCL unable to create kernel\n");
     175        return;
     176    }
     177
     178    //
     179    // Setup Source and EncodedFrame Buffers
     180    //
     181    CurSourceImageSize[Y] = (avctx->width * avctx->height);
     182    CurSourceImageSize[U] = (avctx->width * avctx->height) >> 2;
     183    CurSourceImageSize[V] = (avctx->width * avctx->height) >> 2;
     184       
     185    // Encoded Frame data size - hard code to allocate host memory as this varies!
     186    EncodedFrameSize = (avctx->width * avctx->height * 3) >> 1;
     187    EncodedFrameLengthSize = 1;
     188    // av_log(NULL, AV_LOG_INFO," * Image Sizes: Source[YUV]=[%d,%d,%d] EncodedFrame=%d\n",
     189    //          CurSourceImageSize[Y], CurSourceImageSize[U], CurSourceImageSize[V], EncodedFrameSize);
     190
     191    //
     192    // Setup OpenCL Buffers and Kernel Parameters
     193    //
     194    // av_log(NULL, AV_LOG_INFO," * Creating the kernel buffers\n");
     195    CREATEBUF(CSR3_INPUT_FP_Y_V, CL_MEM_READ_ONLY,  CurSourceImageSize[Y] * sizeof(unsigned char));
     196    CREATEBUF(CSR4_INPUT_FP_U_V, CL_MEM_READ_ONLY,  CurSourceImageSize[U] * sizeof(unsigned char));
     197    CREATEBUF(CSR5_INPUT_FP_V_V, CL_MEM_READ_ONLY,  CurSourceImageSize[V] * sizeof(unsigned char));
     198    CREATEBUF(CSR6_NEXT_FP_Y_V, CL_MEM_READ_ONLY,  CurSourceImageSize[Y] * sizeof(unsigned char));
     199    CREATEBUF(CSR7_NEXT_FP_U_V, CL_MEM_READ_ONLY,  CurSourceImageSize[U] * sizeof(unsigned char));
     200    // Padding to make reference base pointer of reconstructed picture 128KB aligned
     201    CREATEBUF(CSR8_NEXT_FP_V_V, CL_MEM_READ_ONLY,  (CurSourceImageSize[V]+ 48*128*1024-1920*1080*3) * sizeof(unsigned char));
     202    // Reference frame requires at least 16MB space in DDR
     203    CREATEBUF(CSR12_RECON_BASE_V, CL_MEM_READ_WRITE,  16*1024*1024);
     204    CREATEBUF(CSR13_BITSTREAM_BASE_V, CL_MEM_WRITE_ONLY, EncodedFrameSize * sizeof(unsigned char));
     205    CREATEBUF(CSR14_BITSTREAM_LEN_V, CL_MEM_WRITE_ONLY, EncodedFrameLengthSize * sizeof(unsigned long long));
     206   
     207    //
     208    // Send Kernel Parameters
     209    //
     210    // av_log(NULL, AV_LOG_INFO," * Sending parameters to HEVC kernel\n");
     211    // av_log(NULL, AV_LOG_INFO," * CSR1_FRAME_WIDTH_V:  0x%08x\n", CSR1_FRAME_WIDTH_V);
     212    // av_log(NULL, AV_LOG_INFO," * CSR2_FRAME_HEIGHT_V: 0x%08x\n", CSR2_FRAME_HEIGHT_V);
     213    // av_log(NULL, AV_LOG_INFO," * CSR3_INPUT_FP_Y_V addr %p\n", &CSR3_INPUT_FP_Y_V);
     214    // av_log(NULL, AV_LOG_INFO," * CSR4_INPUT_FP_U_V addr %p\n", &CSR4_INPUT_FP_U_V);
     215    // av_log(NULL, AV_LOG_INFO," * CSR5_INPUT_FP_V_V addr %p\n", &CSR5_INPUT_FP_V_V);
     216    // av_log(NULL, AV_LOG_INFO," * CSR6_NEXT_FP_Y_V addr %p\n", &CSR6_NEXT_FP_Y_V);
     217    // av_log(NULL, AV_LOG_INFO," * CSR7_NEXT_FP_U_V addr %p\n", &CSR7_NEXT_FP_U_V);
     218    // av_log(NULL, AV_LOG_INFO," * CSR8_NEXT_FP_V_V addr %p\n", &CSR8_NEXT_FP_V_V);
     219    // av_log(NULL, AV_LOG_INFO," * CSR9_BITRATE_V:  0x%08x\n", CSR9_BITRATE_V);
     220    // av_log(NULL, AV_LOG_INFO," * CSR10_FIXED_QP_V:  0x%08x\n", CSR10_FIXED_QP_V);
     221    // av_log(NULL, AV_LOG_INFO," * CSR11_INTRA_PERIOD_V:  0x%08x\n", CSR11_INTRA_PERIOD_V);
     222    // av_log(NULL, AV_LOG_INFO," * CSR12_RECON_BASE_V addr %p\n", &CSR12_RECON_BASE_V);
     223    // av_log(NULL, AV_LOG_INFO," * CSR13_BITSTREAM_BASE_V addr %p\n", &CSR13_BITSTREAM_BASE_V);
     224    // av_log(NULL, AV_LOG_INFO," * CSR14_BITSTREAM_LEN_V addr %p\n", &CSR14_BITSTREAM_LEN_V);
     225    // av_log(NULL, AV_LOG_INFO," * CSR15_RESET_ENCODER_V:  0x%08x\n", CSR15_RESET_ENCODER_V);
     226       
     227    OCLCHECK(clSetKernelArg, kernel, arg++, sizeof(unsigned int), &CSR1_FRAME_WIDTH_V);
     228    OCLCHECK(clSetKernelArg, kernel, arg++, sizeof(unsigned int), &CSR2_FRAME_HEIGHT_V);
     229    OCLCHECK(clSetKernelArg, kernel, arg++, sizeof(cl_mem),       &CSR3_INPUT_FP_Y_V);
     230    OCLCHECK(clSetKernelArg, kernel, arg++, sizeof(cl_mem),       &CSR4_INPUT_FP_U_V);
     231    OCLCHECK(clSetKernelArg, kernel, arg++, sizeof(cl_mem),       &CSR5_INPUT_FP_V_V);
     232    OCLCHECK(clSetKernelArg, kernel, arg++, sizeof(cl_mem),       &CSR6_NEXT_FP_Y_V);
     233    OCLCHECK(clSetKernelArg, kernel, arg++, sizeof(cl_mem),       &CSR7_NEXT_FP_U_V);
     234    OCLCHECK(clSetKernelArg, kernel, arg++, sizeof(cl_mem),       &CSR8_NEXT_FP_V_V);
     235    OCLCHECK(clSetKernelArg, kernel, arg++, sizeof(unsigned int), &CSR9_BITRATE_V);
     236    OCLCHECK(clSetKernelArg, kernel, arg++, sizeof(unsigned int), &CSR10_FIXED_QP_V);
     237    OCLCHECK(clSetKernelArg, kernel, arg++, sizeof(unsigned int), &CSR11_INTRA_PERIOD_V);
     238    OCLCHECK(clSetKernelArg, kernel, arg++, sizeof(cl_mem),       &CSR12_RECON_BASE_V);
     239    OCLCHECK(clSetKernelArg, kernel, arg++, sizeof(cl_mem),       &CSR13_BITSTREAM_BASE_V);
     240    OCLCHECK(clSetKernelArg, kernel, arg++, sizeof(cl_mem),       &CSR14_BITSTREAM_LEN_V);
     241    OCLCHECK(clSetKernelArg, kernel, arg++, sizeof(unsigned int), &CSR15_RESET_ENCODER_V);
     242    return;
     243}
     244
     245//
     246// HEVC opencl run function
     247//
     248int ff_hevc_xlnx_hw(AVCodecContext *avctx, AVFrame *pic, uint8_t *dst, uint32_t *dstSize)
     249{
     250    size_t global_work_size_1d[1] = {1};
     251    size_t local_work_size_1d[1] = {1};
     252         
     253    if (frameNumber == 0)
     254    {
     255        OCLCHECK1(clEnqueueWriteBuffer, cl_env->command_queue, CSR3_INPUT_FP_Y_V, CL_TRUE, 0, CurSourceImageSize[Y] * sizeof(unsigned char), pic->data[Y], 0, NULL, NULL);
     256        OCLCHECK1(clEnqueueWriteBuffer, cl_env->command_queue, CSR4_INPUT_FP_U_V, CL_TRUE, 0, CurSourceImageSize[U] * sizeof(unsigned char), pic->data[U], 0, NULL, NULL);
     257        OCLCHECK1(clEnqueueWriteBuffer, cl_env->command_queue, CSR5_INPUT_FP_V_V, CL_TRUE, 0, CurSourceImageSize[V] * sizeof(unsigned char), pic->data[V], 0, NULL, NULL); 
     258        // av_log(NULL, AV_LOG_INFO," * Loading frame %d\n", frameNumber);       
     259        frameNumber++;
     260        return 0;
     261    }
     262    else if (frameNumber == 1)
     263    {
     264        OCLCHECK1(clEnqueueWriteBuffer, cl_env->command_queue, CSR6_NEXT_FP_Y_V, CL_TRUE, 0, CurSourceImageSize[Y] * sizeof(unsigned char), pic->data[Y], 0, NULL, NULL);
     265        OCLCHECK1(clEnqueueWriteBuffer, cl_env->command_queue, CSR7_NEXT_FP_U_V, CL_TRUE, 0, CurSourceImageSize[U] * sizeof(unsigned char), pic->data[U], 0, NULL, NULL);
     266        OCLCHECK1(clEnqueueWriteBuffer, cl_env->command_queue, CSR8_NEXT_FP_V_V, CL_TRUE, 0, CurSourceImageSize[V] * sizeof(unsigned char), pic->data[V], 0, NULL, NULL);
     267        // av_log(NULL, AV_LOG_INFO," * Loading frame %d\n", frameNumber);       
     268        frameNumber++;
     269    }
     270    else
     271    {
     272        // Ping-pong buffers used; switch cur and nxt buffer pointer for kernel
     273        if (frameNumber%2 == 0)
     274                {
     275                        OCLCHECK1(clSetKernelArg, kernel, 2, sizeof(cl_mem), &CSR6_NEXT_FP_Y_V);
     276                        OCLCHECK1(clSetKernelArg, kernel, 3, sizeof(cl_mem), &CSR7_NEXT_FP_U_V);
     277                        OCLCHECK1(clSetKernelArg, kernel, 4, sizeof(cl_mem), &CSR8_NEXT_FP_V_V);
     278                        OCLCHECK1(clSetKernelArg, kernel, 5, sizeof(cl_mem), &CSR3_INPUT_FP_Y_V);
     279                        OCLCHECK1(clSetKernelArg, kernel, 6, sizeof(cl_mem), &CSR4_INPUT_FP_U_V);
     280                        OCLCHECK1(clSetKernelArg, kernel, 7, sizeof(cl_mem), &CSR5_INPUT_FP_V_V);
     281                        OCLCHECK1(clEnqueueWriteBuffer, cl_env->command_queue, CSR3_INPUT_FP_Y_V, CL_TRUE, 0, CurSourceImageSize[Y] * sizeof(unsigned char), pic->data[Y], 0, NULL, NULL);
     282                        OCLCHECK1(clEnqueueWriteBuffer, cl_env->command_queue, CSR4_INPUT_FP_U_V, CL_TRUE, 0, CurSourceImageSize[U] * sizeof(unsigned char), pic->data[U], 0, NULL, NULL);
     283                        OCLCHECK1(clEnqueueWriteBuffer, cl_env->command_queue, CSR5_INPUT_FP_V_V, CL_TRUE, 0, CurSourceImageSize[V] * sizeof(unsigned char), pic->data[V], 0, NULL, NULL);
     284                        // av_log(NULL, AV_LOG_INFO," * Loading frame %d\n", frameNumber);
     285                }
     286                else
     287                {
     288                        OCLCHECK1(clSetKernelArg, kernel, 2, sizeof(cl_mem), &CSR3_INPUT_FP_Y_V);
     289                        OCLCHECK1(clSetKernelArg, kernel, 3, sizeof(cl_mem), &CSR4_INPUT_FP_U_V);
     290                        OCLCHECK1(clSetKernelArg, kernel, 4, sizeof(cl_mem), &CSR5_INPUT_FP_V_V);
     291                        OCLCHECK1(clSetKernelArg, kernel, 5, sizeof(cl_mem), &CSR6_NEXT_FP_Y_V);
     292                        OCLCHECK1(clSetKernelArg, kernel, 6, sizeof(cl_mem), &CSR7_NEXT_FP_U_V);
     293                        OCLCHECK1(clSetKernelArg, kernel, 7, sizeof(cl_mem), &CSR8_NEXT_FP_V_V);
     294                        OCLCHECK1(clEnqueueWriteBuffer, cl_env->command_queue, CSR6_NEXT_FP_Y_V, CL_TRUE, 0, CurSourceImageSize[Y] * sizeof(unsigned char), pic->data[Y], 0, NULL, NULL);
     295                        OCLCHECK1(clEnqueueWriteBuffer, cl_env->command_queue, CSR7_NEXT_FP_U_V, CL_TRUE, 0, CurSourceImageSize[U] * sizeof(unsigned char), pic->data[U], 0, NULL, NULL);
     296                        OCLCHECK1(clEnqueueWriteBuffer, cl_env->command_queue, CSR8_NEXT_FP_V_V, CL_TRUE, 0, CurSourceImageSize[V] * sizeof(unsigned char), pic->data[V], 0, NULL, NULL);
     297                        // av_log(NULL, AV_LOG_INFO," * Loading frame %d\n", frameNumber); 
     298                }
     299                frameNumber++;
     300    }
     301    OCLCHECK1(clEnqueueNDRangeKernel, cl_env->command_queue, kernel, 1, NULL, global_work_size_1d, local_work_size_1d, 0, NULL, NULL);
     302
     303    //
     304    // Wait for the hw accelerator to complete
     305    //
     306    clFinish(cl_env->command_queue);
     307    //av_log(NULL, AV_LOG_INFO," * Finished the xlnx hw accelerator kernel\n");
     308
     309    //
     310    // Read the result
     311    // Get the length of the Encoded Frame first as this varies!
     312    //
     313    // av_log(NULL, AV_LOG_INFO," * Enqueuing Read Buffer - CSR14_BITSTREAM_LEN_V\n");
     314    OCLCHECK1(clEnqueueReadBuffer, cl_env->command_queue, CSR14_BITSTREAM_LEN_V, CL_TRUE, 0, EncodedFrameLengthSize * sizeof(unsigned int), dstSize, 0, NULL, NULL);
     315    // av_log(NULL, AV_LOG_INFO," * Encoded Frame Length = %d\n", *dstSize);
     316    //*dstSize = *dstSize * 4;
     317
     318    // av_log(NULL, AV_LOG_INFO," * Enqueuing Read Buffer - CSR13_BITSTREAM_BASE_V\n");
     319    OCLCHECK1(clEnqueueReadBuffer, cl_env->command_queue, CSR13_BITSTREAM_BASE_V, CL_TRUE, 0, (*dstSize) * sizeof(unsigned char), dst, 0, NULL, NULL);
     320
     321    return 0;
     322}
     323
     324//
     325// HEVC exit function
     326//
     327void ff_uninit_hevc_xlnx_hw(AVCodecContext *avctx)
     328{
     329    // av_log(NULL, AV_LOG_INFO," * Tidying up ... releasing OpenCL Objects\n");
     330    clReleaseKernel(kernel);
     331    clReleaseProgram(program);
     332    clReleaseMemObject(CSR3_INPUT_FP_Y_V);
     333    clReleaseMemObject(CSR4_INPUT_FP_U_V);
     334    clReleaseMemObject(CSR5_INPUT_FP_V_V);
     335    clReleaseMemObject(CSR6_NEXT_FP_Y_V);
     336    clReleaseMemObject(CSR7_NEXT_FP_U_V);
     337    clReleaseMemObject(CSR8_NEXT_FP_V_V);
     338    clReleaseMemObject(CSR13_BITSTREAM_BASE_V);
     339    clReleaseMemObject(CSR14_BITSTREAM_LEN_V); 
     340}
     341
     342int load_file_to_memory_hevc(const char *filename, unsigned char **result)
     343{
     344   int size = 0;
     345   FILE *f = fopen(filename, "rb");
     346   if(f == NULL)
     347   {
     348       *result = NULL;
     349        return -1; // -1 means file opening fail
     350   }
     351   fseek(f, 0, SEEK_END);
     352   size = ftell(f);
     353   fseek(f, 0, SEEK_SET);
     354   *result = malloc(size);
     355   if(size != fread(*result, sizeof(char), size, f))
     356   {
     357      free(*result);
     358      return -2; // -2 means file reading fail
     359   }
     360   fclose(f);
     361   return size;
     362 }
     363
  • new file libavcodec/xlnx_hevc/xlnx_hevc_config.h

    diff --git a/libavcodec/xlnx_hevc/xlnx_hevc_config.h b/libavcodec/xlnx_hevc/xlnx_hevc_config.h
    new file mode 100644
    index 0000000..18dd33e
    - +  
     1#ifndef _XLNX_HEVC_CONFIG_H_
     2#define _XLNX_HEVC_CONFIG_H_
     3
     4#include "libavcodec/avcodec.h"
     5
     6//Macros
     7#define OCLCHECK(method, ... )                                                 \
     8do {                                                                           \
     9    status = method(__VA_ARGS__);                                              \
     10    if (status != CL_SUCCESS) {                                                \
     11        av_log(NULL, AV_LOG_ERROR, # method " error '%s'\n",                   \
     12               av_opencl_errstr(status));                                      \
     13        return;                                                                \
     14    }                                                                          \
     15} while (0)
     16
     17#define OCLCHECK1(method, ... )                                                \
     18do {                                                                           \
     19    status = method(__VA_ARGS__);                                              \
     20    if (status != CL_SUCCESS) {                                                \
     21        av_log(NULL, AV_LOG_ERROR, # method " error '%s'\n",                   \
     22               av_opencl_errstr(status));                                      \
     23        return AVERROR_EXTERNAL;                                               \
     24    }                                                                          \
     25} while (0)
     26
     27#define CREATEBUF(out, flags, size)                                            \
     28do {                                                                           \
     29    out = clCreateBuffer(cl_env->context, flags, size, NULL, &status);         \
     30    if (status != CL_SUCCESS) {                                                \
     31        av_log(NULL, AV_LOG_ERROR, "Could not create OpenCL buffer\n");        \
     32        return;                                                                \
     33    }                                                                          \
     34} while (0)
     35
     36//Typedefs
     37typedef enum
     38{
     39        Y = 0,
     40        U = 1,
     41        V = 2
     42}col_fmt_t;
     43
     44//Function Prototypes
     45void ff_init_hevc_xlnx_hw(AVCodecContext *c);
     46void ff_uninit_hevc_xlnx_hw(AVCodecContext *c);
     47int ff_hevc_xlnx_hw(AVCodecContext *avctx, AVFrame *pic, uint8_t *dst, uint32_t *dstSize);
     48
     49#endif //_XLNX_HEVC_CONFIG_H_
     50
  • new file libavcodec/xlnx_hevc_enc.c

    diff --git a/libavcodec/xlnx_hevc_enc.c b/libavcodec/xlnx_hevc_enc.c
    new file mode 100644
    index 0000000..93c5d5b
    - +  
     1/*
     2 * Xilinx HEVC NGCodec encoder
     3 *
     4 * Copyright (C) 2015 Xilinx Inc.
     5 *
     6 * This file is part of FFmpeg.
     7 *
     8 * FFmpeg is free software; you can redistribute it and/or
     9 * modify it under the terms of the GNU Lesser General Public
     10 * License as published by the Free Software Foundation; either
     11 * version 2.1 of the License, or (at your option) any later version.
     12 *
     13 * FFmpeg is distributed in the hope that it will be useful,
     14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     16 * Lesser General Public License for more details.
     17 *
     18 * You should have received a copy of the GNU Lesser General Public
     19 * License along with FFmpeg; if not, write to the Free Software
     20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     21 */
     22#include <stdio.h>
     23#include "avcodec.h"
     24#include "internal.h"
     25#include "xlnx_hw/xlnx_hw.h"
     26#include "pthread.h"
     27#include <sys/types.h>
     28#include <sys/syscall.h>
     29#include "xlnx_hw/common/inc/xlnx_queue.h"
     30#include "xlnx_hw/common/inc/xlnx_hw_defines.h"
     31
     32typedef struct EncodeRequest {
     33    xlnx_cmp_buf iBuf;
     34    xlnx_hw_buf iBufHdr;
     35    xlnx_data_buf out;
     36    xlnx_hw_buf oBufHdr;
     37    AVFrame* pic;
     38}
     39EncodeRequest;
     40
     41typedef struct XlnxHevcContext {
     42    xlnx_hw hw;
     43    HevcEncParam params;
     44    xlnx_queue* rQ;
     45    int frame;
     46}
     47XlnxHevcContext;
     48
     49static EncodeRequest* createEncReq(const AVFrame* pic, size_t aEncodeSize) {
     50    EncodeRequest* req;
     51    xlnx_data_buf* tmp;
     52    req = av_mallocz(sizeof(EncodeRequest));
     53    if (NULL == req) {
     54        av_log(NULL, AV_LOG_ERROR,"Error: Cannot allocate memory %s at %d\n", __FILE__, __LINE__);
     55        return NULL;
     56    }
     57    //input
     58    req->iBufHdr.type = ERAW;
     59    req->oBufHdr.type = EDATA;
     60    if (pic != NULL) {
     61        req->pic = av_frame_clone(pic);
     62        if (NULL == req->pic) {
     63            av_log(NULL, AV_LOG_ERROR,"Error: Cannot allocate memory %s at %d\n", __FILE__, __LINE__);
     64            av_free(req);
     65            return NULL;
     66        }
     67        tmp = (xlnx_data_buf*)&req->iBuf;
     68        for (int i = 0; i < 3; i++) {
     69            tmp[i].pDATA = req->pic->data[i];
     70            tmp[i].offset = 0;
     71            tmp[i].size = req->pic->linesize[i] * req->pic->height;
     72        }
     73        req->iBufHdr.ptr = &req->iBuf;
     74        // output
     75        req->out.pDATA = av_malloc(aEncodeSize);
     76        if (NULL == req->out.pDATA) {
     77            av_log(NULL, AV_LOG_ERROR,"Error: Cannot allocate memory %s at %d\n", __FILE__, __LINE__);
     78            av_frame_unref(req->pic);
     79            return NULL;
     80        }
     81        req->out.size = aEncodeSize;
     82        req->oBufHdr.ptr = &req->out;
     83    } else {
     84        req->iBufHdr.ptr = NULL;
     85        req->oBufHdr.ptr = NULL;
     86    }
     87
     88    return req;
     89}
     90
     91static void destroyEncInput(EncodeRequest* aReq) {
     92    if (aReq->pic) {
     93        av_frame_unref(aReq->pic);
     94        av_frame_free(&aReq->pic);
     95    }
     96}
     97
     98static void destroyEncOut(EncodeRequest* aReq) {
     99    if(aReq->out.pDATA) av_free(aReq->out.pDATA);
     100}
     101
     102static int destroyEncReq(EncodeRequest* aReq) {
     103    destroyEncInput(aReq);
     104    destroyEncOut(aReq);
     105    av_free(aReq);
     106    return 0;
     107}
     108
     109static void hevc_init_params(AVCodecContext *avctx, HevcEncParam* params) {
     110    params->width = avctx->width;
     111    params->height = avctx->height;
     112    params->ip = avctx->gop_size;
     113    params->bitrate = avctx->bit_rate;
     114    params->qp = avctx->global_quality;
     115    if (params->qp > 51) {
     116        // Constant bitrate mode
     117        av_log(NULL, AV_LOG_INFO, " * Encoding in constant bitrate mode***\n");
     118    } else {
     119        // Fixed QP mode
     120        av_log(NULL, AV_LOG_INFO, " * Encoding in fixed QP mode***\n");
     121    }
     122    params->reset = 0;
     123    return;
     124}
     125static int isSupported(AVCodecContext *avctx) {
     126    //Supported 1080p60, 8bits
     127    // height and width should be a multiple of 4
     128    // minimum resolution is 352x288
     129    int width, height;
     130    width = avctx->width;
     131    height = avctx->height;
     132    if (((width & 3) != 0) || ((height & 3) != 0)) {
     133        av_log(NULL, AV_LOG_ERROR,"ERROR:height and width should be a multiple of 4\n");
     134        return -1;
     135    }
     136    if ((width < 352 || height < 288) &&
     137        (width < 288 || height < 352)) {
     138        av_log(NULL, AV_LOG_ERROR,"ERROR: min resolution supported is 352x288\n");
     139        return -1;
     140    }
     141    switch(avctx->pix_fmt) {
     142    case AV_PIX_FMT_YUV420P:
     143        avctx->bits_per_raw_sample = 8;
     144        break;
     145    default:
     146        av_log(NULL, AV_LOG_ERROR,"ERROR: Pixel format not supported...\n");
     147        return -1;
     148        break;
     149    }
     150    return 0;
     151}
     152
     153static int xlnx_hevc_encode_init(AVCodecContext *avctx) {
     154    XlnxHevcContext* hevc;
     155    HevcEncParam* params;
     156    if (isSupported(avctx) < 0) {
     157        return AVERROR(ENOSYS);
     158    }
     159    hevc = (XlnxHevcContext*)avctx->priv_data;
     160    params = &hevc->params;
     161    hevc_init_params(avctx, params);
     162    hevc->rQ = createQueue(HEVC_ENC_OUT_Q_CAPACITY);
     163    if (NULL == hevc->rQ) return -1;
     164    hevc->hw = xlnx_hw_get(EHevcEnc, params);
     165    if (NULL == hevc->hw) {
     166        av_log(NULL, AV_LOG_ERROR,"ERROR: Failed to get EHevcEnc handle\n");
     167        return AVERROR(EINVAL);
     168    }
     169    return 0;
     170}
     171
     172static int xlnx_hevc_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pic, int *got_packet) {
     173    XlnxHevcContext* hevc = (XlnxHevcContext*)avctx->priv_data;
     174    int EntrySize = avctx->bits_per_raw_sample == 8 ? 1 : 2;
     175    int ret;
     176    int EntryCount = 0;
     177    uint64_t EncodeBuffSize = 0;
     178    int width, height, format;
     179    EncodeRequest* req;
     180    xlnx_hw_buf* outBuf;
     181    void* nullptr;
     182    HevcEncParam* params = &hevc->params;
     183    if (NULL == pic) {
     184        av_log(NULL, AV_LOG_DEBUG, "xlnx_hevc_encode_frame EOS Received\n");
     185        if (params->reset == 0) {
     186            params->reset = 1;
     187        } else if (params->reset == 2) {
     188            *got_packet = 0;
     189            return 0;
     190        }
     191        width = avctx->width;
     192        height = avctx->height;
     193        format = avctx->pix_fmt;
     194    } else {
     195        width = pic->width;
     196        height = pic->height;
     197        format = pic->format;
     198    }
     199
     200    switch(format) {
     201    case AV_PIX_FMT_YUV420P:
     202        EntryCount = 2;
     203        break;
     204    default:
     205        av_log(NULL, AV_LOG_ERROR,"Error. Encoding unknown pixel format.\n");
     206        return AVERROR_INVALIDDATA;
     207        break;
     208    }
     209
     210    EncodeBuffSize = EntryCount * width * height * EntrySize;
     211
     212    req = createEncReq(pic, EncodeBuffSize);
     213    if (req == NULL) {
     214        return -1;
     215    }
     216    outBuf = &req->oBufHdr;
     217    nullptr = NULL;
     218    ret = xlnx_hw_process_async(hevc->hw, &hevc->params, &req->iBufHdr, &outBuf, &nullptr);
     219    if (ret < 0) {
     220        *got_packet = 0;
     221        destroyEncReq(req);
     222        return AVERROR(EINVAL);
     223    } else if (ret == 0) {
     224        *got_packet = 0;
     225        enqueue(hevc->rQ, (XItem)req);
     226        return 0;
     227    } else if (ret == 1) {
     228        EncodeRequest* tmpReq = (EncodeRequest*)dequeue(hevc->rQ);
     229        xlnx_data_buf* ptr = outBuf->ptr;
     230        assert(tmpReq->out.pDATA == ptr->pDATA);
     231        av_packet_from_data(pkt, ptr->pDATA, ptr->size);
     232        pkt->pts = pkt->dts = (int64_t)tmpReq->pic->pts;
     233        destroyEncInput(tmpReq);
     234        av_free(tmpReq);
     235        enqueue(hevc->rQ, (XItem)req);
     236        *got_packet = 1;
     237    } else if (ret == 2) {
     238        *got_packet = 0;
     239        params->reset = 2;
     240    }
     241    return 0;
     242}
     243
     244static int xlnx_hevc_encode_close(AVCodecContext *avctx) {
     245    XlnxHevcContext* hevc = (XlnxHevcContext*)avctx->priv_data;
     246    xlnx_hw_release(hevc->hw);
     247    if (hevc->rQ) {
     248        while(!isEmpty(hevc->rQ)) {
     249            EncodeRequest* req = (EncodeRequest*)dequeue(hevc->rQ);
     250            destroyEncReq(req);
     251        }
     252        destroyQueue(hevc->rQ);
     253    }
     254    return 0;
     255}
     256
     257AVCodec ff_xlnx_hevc_encoder = {
     258    .name           = "xlnx_hevc_enc",
     259    .long_name      = NULL_IF_CONFIG_SMALL("Xilinx High Efficiency Video Codec (H.265) Encoder"),
     260    .type           = AVMEDIA_TYPE_VIDEO,
     261    .id             = AV_CODEC_ID_HEVC,
     262    .priv_data_size = sizeof(XlnxHevcContext),
     263    .init           = xlnx_hevc_encode_init,
     264    .encode2        = xlnx_hevc_encode_frame,
     265    .close          = xlnx_hevc_encode_close,
     266    .capabilities   = CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
     267    .pix_fmts       = (const enum AVPixelFormat[]) {
     268                          AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE
     269                      },
     270};
     271
  • new file libavcodec/xlnx_hw/Makefile

    diff --git a/libavcodec/xlnx_hw/Makefile b/libavcodec/xlnx_hw/Makefile
    new file mode 100644
    index 0000000..dddd044
    - +  
     1OBJS                            += xlnx_hw/xlnx_hw.o
     2OBJS                            += xlnx_hw/xlnx_hrm.o
     3OBJS                            += xlnx_hw/xcl.o
  • new file libavcodec/xlnx_hw/common/inc/xcl.h

    diff --git a/libavcodec/xlnx_hw/common/inc/xcl.h b/libavcodec/xlnx_hw/common/inc/xcl.h
    new file mode 100755
    index 0000000..327837c
    - +  
     1#ifndef XCL_H
     2#define XCL_H
     3
     4#include <CL/opencl.h>
     5#include "xlnx_types_internal.h"
     6
     7int xcl_GetPlatform(const char* platform, cl_platform_id* id);
     8int xcl_CreateContextFromType(const cl_platform_id* id, cl_device_type aType,
     9    cl_context* aContext);
     10int xcl_ReleaseContext(cl_context* aContext);
     11int xcl_GetDeviceList(const cl_platform_id* id, cl_device_type aType,
     12    xlnx_device** aDeviceList, cl_uint* aNumDevices);
     13int xcl_FreeDeviceList(xlnx_device* aDeviceList, cl_uint aNumDevices);
     14int xcl_IsDeviceAvailable(cl_device_id aDevice);
     15int xcl_ImportBinaryHeader(cl_context* aContext, cl_device_id* aDevice,
     16    const char *xclbin, size_t aBinaryLength, cl_program* aProgram);
     17int xcl_ImportBinary(cl_context* aContext, cl_device_id* aDevice,
     18    const char *xclbin_file_name, cl_program* aProgram);
     19int xcl_ReleaseProgram(cl_program* aProgram);
     20int xcl_CreateKernels(cl_context* aContext, cl_device_id* aDevice,
     21    cl_program* aProgram, const char** aKernelNames, uint32_t aNumKernels,
     22        xlnx_kernel** aKernelList);
     23int xcl_CreateKernels2(cl_context* aContext, cl_device_id* aDevice,
     24    cl_program* aProgram, const KRNL_CONFIG* aKernelConfig, uint32_t aNumKernels,
     25        xlnx_kernel** aKernelList);
     26int xcl_FreeKernels(xlnx_kernel* aKernelList, uint32_t aNumKernels);
     27
     28#endif //XCL_H
     29 No newline at end of file
  • new file libavcodec/xlnx_hw/common/inc/xlnx_hrm.h

    diff --git a/libavcodec/xlnx_hw/common/inc/xlnx_hrm.h b/libavcodec/xlnx_hw/common/inc/xlnx_hrm.h
    new file mode 100644
    index 0000000..1f38d58
    - +  
     1#ifndef XLNX_HRM_H
     2#define XLNX_HRM_H
     3
     4#include "../../xlnx_hw_types.h"
     5#include "../inc/xlnx_types_internal.h"
     6
     7int xlnx_hrm_init(const char* aCfgFileName, xlnx_hw_id aHWID);
     8int xlnx_hrm_deinit(void);
     9xlnx_host* xlnx_hrm_get_host(xlnx_hw_id aHWID, xlnx_hw_params aParams);
     10int xlnx_hrm_release_host(xlnx_host* aHost);
     11
     12#endif //XLNX_HRM_H
  • new file libavcodec/xlnx_hw/common/inc/xlnx_hw_defines.h

    diff --git a/libavcodec/xlnx_hw/common/inc/xlnx_hw_defines.h b/libavcodec/xlnx_hw/common/inc/xlnx_hw_defines.h
    new file mode 100644
    index 0000000..deb7913
    - +  
     1#ifndef XLNX_HW_DEFINES_H
     2#define XLNX_HW_DEFINES_H
     3
     4#define RESET_UPPER_16 0x0000FFFF
     5#define RESET_LOWER_16 0xFFFF0000
     6
     7#define FILE_PATH_LENGTH 1024
     8#define LOAD_BINARY_FROM_HEADER 0
     9#define VU9P_HEVC_ENC_2_K 1
     10#define VU9P_HEVC_ENC_NUM_CH 2
     11
     12#define HEVC_KRNL_CH_Q_CAPACITY 3
     13#define HEVC_ENC_IN_Q_CAPACITY 2
     14#define HEVC_ENC_OUT_Q_CAPACITY (HEVC_ENC_IN_Q_CAPACITY + HEVC_KRNL_CH_Q_CAPACITY + 1)
     15
     16#define OCLCHECK(method, ... )                                                 \
     17do {                                                                           \
     18    status = method(__VA_ARGS__);                                              \
     19    if (status != CL_SUCCESS) {                                                \
     20        printf( # method " error '%d'\n", status);                             \
     21        return -1;                                                             \
     22    }                                                                          \
     23} while (0)
     24
     25#define ENQUEUEBUF(method, dst)                                                \
     26do {                                                                           \
     27    status = method(cmdQ, dst, CL_TRUE, 0, size, iHBuf[i].pDATA, 0, NULL, NULL);\
     28    if (CL_SUCCESS != status) {                                                \
     29        printf(# method " failed, error %d\n", status);                        \
     30        return -1;                                                             \
     31    }                                                                          \
     32} while (0)
     33
     34#endif //XLNX_HW_DEFINES_H
     35 No newline at end of file
  • new file libavcodec/xlnx_hw/common/inc/xlnx_queue.h

    diff --git a/libavcodec/xlnx_hw/common/inc/xlnx_queue.h b/libavcodec/xlnx_hw/common/inc/xlnx_queue.h
    new file mode 100644
    index 0000000..a995c45
    - +  
     1#ifndef XLNX_QUEUE_H
     2#define XLNX_QUEUE_H
     3
     4typedef void* XItem;
     5typedef struct xlnx_queue xlnx_queue;
     6
     7xlnx_queue* createQueue(size_t capacity);
     8void destroyQueue(xlnx_queue* queue);
     9int isFull(xlnx_queue* queue);
     10int isEmpty(xlnx_queue* queue);
     11size_t getSize(xlnx_queue* queue);
     12int enqueue(xlnx_queue* queue, XItem item);
     13XItem dequeue(xlnx_queue* queue);
     14XItem front(xlnx_queue* queue);
     15XItem rear(xlnx_queue* queue);
     16
     17#endif // XLNX_QUEUE_H
     18 No newline at end of file
  • new file libavcodec/xlnx_hw/common/inc/xlnx_ts_queue.h

    diff --git a/libavcodec/xlnx_hw/common/inc/xlnx_ts_queue.h b/libavcodec/xlnx_hw/common/inc/xlnx_ts_queue.h
    new file mode 100644
    index 0000000..ff66fc7
    - +  
     1#ifndef XLNX_TS_QUEUE_H
     2#define XLNX_TS_QUEUE_H
     3
     4#include "xlnx_queue.h"
     5
     6typedef struct xlnx_ts_queue xlnx_ts_queue;
     7
     8xlnx_ts_queue* createTSQ(size_t capacity);
     9void destroyTSQ(xlnx_ts_queue* queue);
     10int isFullTSQ(xlnx_ts_queue* queue);
     11int isEmptyTSQ(xlnx_ts_queue* queue);
     12size_t getSizeTSQ(xlnx_ts_queue* queue);
     13int enqueueTSQ(xlnx_ts_queue* queue, XItem item);
     14XItem dequeueTSQ(xlnx_ts_queue* queue);
     15XItem frontTSQ(xlnx_ts_queue* queue);
     16XItem rearTSQ(xlnx_ts_queue* queue);
     17
     18#endif // XLNX_TS_QUEUE_H
     19 No newline at end of file
  • new file libavcodec/xlnx_hw/common/inc/xlnx_types_internal.h

    diff --git a/libavcodec/xlnx_hw/common/inc/xlnx_types_internal.h b/libavcodec/xlnx_hw/common/inc/xlnx_types_internal.h
    new file mode 100644
    index 0000000..174a793
    - +  
     1#ifndef XLNX_TYPES_INTERNAL_H
     2#define XLNX_TYPES_INTERNAL_H
     3
     4#include <CL/opencl.h>
     5#include "../../xlnx_hw_types.h"
     6
     7typedef struct {
     8    char* devName;
     9    cl_device_id device;
     10    uint32_t majorV;
     11    uint32_t minorV;
     12    void* privData;
     13} xlnx_device;
     14
     15typedef struct xlnx_kernel {
     16    cl_context* context;
     17    cl_command_queue cmdQ;
     18    cl_kernel kernel;
     19    U32 prfBank;
     20    void* appData;
     21    void* privData;
     22} xlnx_kernel;
     23
     24typedef struct xlnx_host xlnx_host;
     25typedef int (*Run)(xlnx_host* aHost, xlnx_hw_params aParams, xlnx_hw_buf* aInput, xlnx_hw_buf* aOutput);
     26typedef int (*RunAsync)(xlnx_host* aHost, xlnx_hw_params aParams, xlnx_hw_buf* aInput, xlnx_hw_buf** aOutput, XContext* aContext);
     27
     28struct xlnx_host {
     29    int ch;
     30    Run process;
     31    RunAsync processAsync;
     32    int eosRcv;
     33    void* appData;
     34    void* privData;
     35};
     36
     37typedef enum {
     38    Y = 0,
     39    U = 1,
     40    V = 2
     41} xlnx_col_fmt;
     42
     43typedef struct {
     44    const char* krnl_name;
     45    U32 prfBank;
     46} KRNL_CONFIG;
     47
     48
     49#endif //XLNX_TYPES_INTERNAL_H
     50 No newline at end of file
  • new file libavcodec/xlnx_hw/common/src/xcl.c

    diff --git a/libavcodec/xlnx_hw/common/src/xcl.c b/libavcodec/xlnx_hw/common/src/xcl.c
    new file mode 100755
    index 0000000..9e2eaf1
    - +  
     1#include <stdio.h>
     2#include <stdlib.h>
     3#include <unistd.h>
     4#include <limits.h>
     5#include <string.h>
     6
     7#include "../inc/xcl.h"
     8#include "CL/cl_ext.h"
     9
     10// Wrap any OpenCL API calls that return error code(cl_int)
     11// with the below macro to quickly check for an error
     12#define OCL_CHECK(call)                                              \
     13    do {                                                             \
     14        cl_int err = call;                                           \
     15        if (err != CL_SUCCESS) {                                     \
     16            printf("Error from " #call ", error code is %d\n", err); \
     17            return err;                                              \
     18        }                                                            \
     19    } while (0);
     20
     21static void* smalloc(size_t size) {
     22    void* ptr;
     23    ptr = malloc(size);
     24    if (ptr == NULL) {
     25        printf("Error: Cannot allocate memory %s at %d\n", __FILE__, __LINE__);
     26        return NULL;
     27    }
     28    return ptr;
     29}
     30
     31static int load_file_to_memory(const char *filename, char **result) {
     32    unsigned int size;
     33    FILE* f;
     34
     35    f = fopen(filename, "rb");
     36    if (f == NULL) {
     37        *result = NULL;
     38        printf("Error: Could not read file %s\n", filename);
     39        return -1;
     40    }
     41
     42    fseek(f, 0, SEEK_END);
     43    size = ftell(f);
     44    fseek(f, 0, SEEK_SET);
     45
     46    *result = (char *) smalloc(sizeof(char)*(size+1));
     47
     48    if (size != fread(*result, sizeof(char), size, f)) {
     49        free(*result);
     50        fclose(f);
     51        printf("Error: read of kernel failed\n");
     52        return -1;
     53    }
     54
     55    fclose(f);
     56    (*result)[size] = 0;
     57
     58    return size;
     59}
     60//
     61// Get device version
     62//
     63static int getDeviceVersion(cl_device_id* aDevice, uint32_t* aMajor, uint32_t* aMinor)
     64{
     65    char versionString[512];
     66    size_t size = 0;
     67    uint32_t major = 0;
     68    uint32_t minor = 0;
     69    uint32_t state = 0;
     70    cl_int err;
     71    err = clGetDeviceInfo(*aDevice, CL_DEVICE_VERSION, 511, versionString, &size);
     72    if ( err != CL_SUCCESS) {
     73        printf("clGetDeviceInfo(CL_DEVICE_VERSION) Failed\n");
     74        return -1;
     75    }
     76    size = strlen(versionString);
     77    for (size_t i = 0; i < size; i++) {
     78        if (versionString[i] == ' ') {
     79            if (0 == state)
     80                state++;
     81            else
     82                break;
     83            continue;
     84        }
     85        if (versionString[i] == '.') {
     86            state++;
     87            continue;
     88        }
     89        if (state == 0) {
     90            continue;
     91        }
     92        if (state == 1) {
     93            major *= 10;
     94            major += (versionString[i] - '0');
     95            continue;
     96        }
     97        if (state == 2) {
     98            minor *= 10;
     99            minor += (versionString[i] - '0');
     100            continue;
     101        }
     102        break;
     103    }
     104    *aMajor = major;
     105    *aMinor = minor;
     106    return -1;
     107}
     108
     109int xcl_GetPlatform(const char* platform, cl_platform_id* id) {
     110    int err = -1;
     111    cl_uint num_platforms = 0;
     112    cl_platform_id* platform_ids;
     113    size_t i;
     114    char* platform_name;
     115
     116    if ((platform == NULL) || (id == NULL)) return -1;
     117
     118    err = clGetPlatformIDs(0, NULL, &num_platforms);
     119    if (err != CL_SUCCESS) {
     120        printf("Error: no platforms available or OpenCL install broken\n");
     121        return err;
     122    }
     123
     124    platform_ids = (cl_platform_id *) malloc(num_platforms * sizeof(cl_platform_id));
     125    if (platform_ids == NULL) {
     126        printf("Error: Out of Memory %s at %d\n", __FILE__, __LINE__);
     127        return -1;
     128    }
     129
     130    err = clGetPlatformIDs(num_platforms, platform_ids, NULL);
     131    if (err != CL_SUCCESS) {
     132        printf("Error: Failed to find an OpenCL platform!\n");
     133        free(platform_ids);
     134        return err;
     135    }
     136
     137    for(i = 0; i < num_platforms; i++) {
     138        size_t platform_name_size;
     139        err = clGetPlatformInfo(platform_ids[i], CL_PLATFORM_NAME,
     140                                0, NULL, &platform_name_size);
     141        if( err != CL_SUCCESS) {
     142            printf("Error: Could not determine platform name!\n");
     143            return err;
     144        }
     145
     146        platform_name = (char*) malloc(sizeof(char)*platform_name_size);
     147        if(platform_name == NULL) {
     148            printf("Error: out of memory! %s at %d\n", __FILE__, __LINE__);
     149            free(platform_ids);
     150            return -1;
     151        }
     152
     153        err = clGetPlatformInfo(platform_ids[i], CL_PLATFORM_NAME,
     154                                platform_name_size, platform_name, NULL);
     155        if(err != CL_SUCCESS) {
     156            free(platform_ids);
     157            free(platform_name);
     158            printf("Error: could not determine platform name!\n");
     159            return err;
     160        }
     161
     162        if (!strcmp(platform_name, platform)) {
     163            free(platform_name);
     164            *id = platform_ids[i];
     165            break;
     166        }
     167
     168        free(platform_name);
     169    }
     170
     171    free(platform_ids);
     172
     173    if (i == num_platforms) {
     174        printf("Error: Failed to find Xilinx platform\n");
     175        return -1;
     176    }
     177    return 0;
     178}
     179
     180int xcl_CreateContextFromType(const cl_platform_id* id, cl_device_type aType, cl_context* aContext) {
     181    int err;
     182    cl_context_properties contextData[3];
     183
     184    if ((id == NULL) || (aContext == NULL)) return -1;
     185    err = -1;
     186    contextData[0] = CL_CONTEXT_PLATFORM;
     187    contextData[1] = (cl_context_properties)*id;
     188    contextData[2] = 0;
     189    *aContext = clCreateContextFromType(contextData, aType, 0, 0, &err);
     190    if (err != CL_SUCCESS) {
     191        return -1;
     192    }
     193    return 0;
     194}
     195
     196int xcl_ReleaseContext(cl_context* aContext) {
     197    if (aContext == NULL) return -1;
     198    OCL_CHECK(clReleaseContext(*aContext));
     199    return 0;
     200}
     201
     202int xcl_GetDeviceList(const cl_platform_id* id, cl_device_type aType, xlnx_device** aDeviceList, cl_uint* aNumDevices) {
     203    int err;
     204    int i;
     205    cl_uint num_devices;
     206    xlnx_device* devices;
     207    cl_device_id* deviceIDs;
     208    size_t device_name_size;
     209
     210    if ((id) == NULL || (aDeviceList == NULL) || (aNumDevices == NULL)) return -1;
     211    err = -1;
     212    num_devices = 0;
     213
     214    err = clGetDeviceIDs(*id, aType, 0, NULL, &num_devices);
     215    if (err != CL_SUCCESS) {
     216        printf("Error: no ACCELERATOR devices available\n");
     217        return err;
     218    }
     219
     220    deviceIDs = (cl_device_id *) malloc(sizeof(cl_device_id) * num_devices);
     221    if (deviceIDs == NULL) {
     222        printf("Error: Out of Memory %s at %d\n", __FILE__, __LINE__);
     223        return -1;
     224    }
     225
     226    err = clGetDeviceIDs(*id, aType, num_devices, deviceIDs, NULL);
     227    if (err != CL_SUCCESS) {
     228        free(deviceIDs);
     229        printf("Error: could not get device ids\n");
     230        return err;
     231    }
     232
     233
     234    devices = (xlnx_device *) calloc(num_devices, sizeof(xlnx_device));
     235    if (devices == NULL) {
     236        free(deviceIDs);
     237        printf("Error: Out of Memory %s at %d\n", __FILE__, __LINE__);
     238        return -1;
     239    }
     240
     241    for (i = 0; i < num_devices; i++) {
     242        err = clGetDeviceInfo(deviceIDs[i], CL_DEVICE_NAME,
     243                              0, NULL, &device_name_size);
     244        if(err != CL_SUCCESS) {
     245            free(deviceIDs);
     246            if (i>0) {
     247                xcl_FreeDeviceList(devices, i);
     248            }
     249            printf("Error: could not determine device name\n");
     250            return err;
     251        }
     252
     253        devices[i].devName = (char*) malloc(sizeof(char)*device_name_size);
     254        if(devices[i].devName == NULL) {
     255            free(deviceIDs);
     256            xcl_FreeDeviceList(devices, i+1);
     257            printf("Error: Out of Memory! %s at %d\n", __FILE__, __LINE__);
     258            return -1;
     259        }
     260
     261        err = clGetDeviceInfo(deviceIDs[i], CL_DEVICE_NAME,
     262                              device_name_size, devices[i].devName, NULL);
     263        if(err != CL_SUCCESS) {
     264            free(deviceIDs);
     265            xcl_FreeDeviceList(devices, i+1);
     266            printf("Error: could not determine device name\n");
     267            return err;
     268        }
     269        getDeviceVersion(&deviceIDs[i], &devices[i].majorV, &devices[i].minorV);
     270        printf("Found %s : version %d.%d\n", devices[i].devName, devices[i].majorV, devices[i].minorV);
     271        devices[i].device = deviceIDs[i];
     272    }
     273    free(deviceIDs);
     274    *aNumDevices = num_devices;
     275    *aDeviceList = devices;
     276    return 0;
     277}
     278
     279int xcl_FreeDeviceList(xlnx_device* aDeviceList, cl_uint aNumDevices) {
     280    if (aDeviceList == NULL) return -1;
     281    for (int i=0; i<aNumDevices; i++) {
     282        if (aDeviceList[i].devName)
     283            free(aDeviceList[i].devName);
     284    }
     285    free(aDeviceList);
     286    return 0;
     287}
     288
     289int xcl_IsDeviceAvailable(cl_device_id aDevice) {
     290    cl_bool avail = CL_TRUE;
     291    OCL_CHECK(clGetDeviceInfo(aDevice, CL_DEVICE_AVAILABLE,
     292                              sizeof(cl_bool), &avail, NULL));
     293    if (avail == CL_FALSE) {
     294        printf("Error: device busy!!\n");
     295        return 0;
     296    }
     297    return 1;
     298}
     299
     300int xcl_ImportBinaryHeader(cl_context* aContext, cl_device_id* aDevice,
     301                        const char *xclbin, size_t aBinaryLength, cl_program* aProgram) {
     302    int err;
     303    cl_program program;
     304    size_t len;
     305    char buffer[2048];
     306    if ((aContext == NULL) || (aDevice == NULL) || (xclbin == NULL ) ||
     307        (aBinaryLength == 0) || (aProgram == NULL))
     308        return -1;
     309
     310    err = -1;
     311    program = clCreateProgramWithBinary(*aContext, 1,
     312                                            aDevice, &aBinaryLength,
     313                                            (const unsigned char **) &xclbin,
     314                                            NULL, &err);
     315    if ((!program) || (err!=CL_SUCCESS)) {
     316        printf("Error: Failed to create compute program from binary %d!\n", err);
     317        return -1;
     318    }
     319
     320    err = clBuildProgram(program, 0, NULL, NULL, NULL, NULL);
     321    if (err != CL_SUCCESS) {
     322        xcl_ReleaseProgram(&program);
     323
     324        clGetProgramBuildInfo(program, *aDevice, CL_PROGRAM_BUILD_LOG,
     325                              sizeof(buffer), buffer, &len);
     326        printf("%s\n", buffer);
     327        printf("Error: Failed to build program executable!\n");
     328        return -1;
     329    }
     330    *aProgram = program;
     331    return 0;
     332}
     333
     334int xcl_ImportBinary(cl_context* aContext, cl_device_id* aDevice,
     335                            const char *xclbin_file_name, cl_program* aProgram) {
     336    int err;
     337    char* krnl_bin;
     338    size_t krnl_size;
     339    cl_program program;
     340    size_t len;
     341    char buffer[2048];
     342
     343    if ((aContext == NULL) || (aDevice == NULL) ||
     344          (xclbin_file_name == NULL ) || (aProgram == NULL))
     345        return -1;
     346
     347    if(access(xclbin_file_name, R_OK) != 0) {
     348        printf("ERROR: %s xclbin not available please build\n", xclbin_file_name);
     349        return -1;
     350    }
     351
     352    krnl_size = load_file_to_memory(xclbin_file_name, &krnl_bin);
     353    program = clCreateProgramWithBinary(*aContext, 1,
     354                                        aDevice, &krnl_size,
     355                                        (const unsigned char**) &krnl_bin,
     356                                        NULL, &err);
     357    if ((!program) || (err!=CL_SUCCESS)) {
     358        free(krnl_bin);
     359        printf("Error: Failed to create compute program from binary %d!\n",
     360               err);
     361        return -1;
     362    }
     363
     364    err = clBuildProgram(program, 0, NULL, NULL, NULL, NULL);
     365    if (err != CL_SUCCESS) {
     366        xcl_ReleaseProgram(&program);
     367        free(krnl_bin);
     368
     369        clGetProgramBuildInfo(program, *aDevice, CL_PROGRAM_BUILD_LOG,
     370                              sizeof(buffer), buffer, &len);
     371        printf("%s\n", buffer);
     372        printf("Error: Failed to build program executable!\n");
     373        return -1;
     374    }
     375    *aProgram = program;
     376    free(krnl_bin);
     377
     378    return 0;
     379}
     380
     381int xcl_ReleaseProgram(cl_program* aProgram) {
     382    if (aProgram == NULL) { return -1;}
     383    OCL_CHECK(clReleaseProgram(*aProgram));
     384    return 0;
     385}
     386
     387int xcl_CreateKernels(cl_context* aContext, cl_device_id* aDevice,
     388                      cl_program* aProgram, const char** aKernelNames, uint32_t aNumKernels,
     389                      xlnx_kernel** aKernelList) {
     390    int err = -1;
     391    xlnx_kernel* kList;
     392    int i;
     393
     394    if ((aContext == NULL) || (aDevice == NULL) ||
     395          (aProgram == NULL ) || (aKernelNames == NULL) || (aNumKernels == 0)) {
     396        return -1;
     397    }
     398    err = -1;
     399    kList = (xlnx_kernel*)calloc(aNumKernels, sizeof(xlnx_kernel));
     400    if (kList == NULL) {
     401        printf("Error: Out of Memory! %s at %d\n", __FILE__, __LINE__);
     402        return -1;
     403    }
     404    for (i = 0; i < aNumKernels; i++) {
     405        kList[i].kernel = clCreateKernel(*aProgram, aKernelNames[i], &err);
     406        if (err != CL_SUCCESS) {
     407            xcl_FreeKernels(kList, i);
     408            printf("Error: OpenCL unable to create kernel %s\n", aKernelNames[i]);
     409            return -1;
     410        }
     411
     412        if (!strcmp(aKernelNames[i], "krnl_ngcodec_hevc_0")) {
     413            printf("%s bank %d\n", aKernelNames[i], XCL_MEM_DDR_BANK0);
     414            kList[i].prfBank = XCL_MEM_DDR_BANK0;
     415        } else if (!strcmp(aKernelNames[i], "krnl_ngcodec_hevc_1")) {
     416            printf("%s bank %d\n", aKernelNames[i], XCL_MEM_DDR_BANK3);
     417            kList[i].prfBank = XCL_MEM_DDR_BANK3;
     418        }
     419
     420        kList[i].cmdQ = clCreateCommandQueue(*aContext, *aDevice, 0, &err);
     421        if (err != CL_SUCCESS) {
     422            xcl_FreeKernels(kList, i+1);
     423            printf("Error: OpenCL unable to create CommandQueue\n");
     424            return -1;
     425        }
     426        kList[i].context = aContext;
     427    }
     428    *aKernelList = kList;
     429    return 0;
     430}
     431
     432int xcl_CreateKernels2(cl_context* aContext, cl_device_id* aDevice,
     433                      cl_program* aProgram, const KRNL_CONFIG* aKernelConfig, uint32_t aNumKernels,
     434                      xlnx_kernel** aKernelList) {
     435    int err;
     436    xlnx_kernel* kList;
     437    if ((aContext == NULL) || (aDevice == NULL) ||
     438          (aProgram == NULL ) || (aKernelConfig == NULL) || (aNumKernels == 0)) {
     439        return -1;
     440    }
     441    err = -1;
     442    kList = (xlnx_kernel*)calloc(aNumKernels, sizeof(xlnx_kernel));
     443    if (kList == NULL) {
     444        printf("Error: Out of Memory! %s at %d\n", __FILE__, __LINE__);
     445        return -1;
     446    }
     447    for (int i = 0; i < aNumKernels; i++) {
     448        kList[i].kernel = clCreateKernel(*aProgram, aKernelConfig[i].krnl_name, &err);
     449        if (err != CL_SUCCESS) {
     450            xcl_FreeKernels(kList, i);
     451            printf("Error: OpenCL unable to create kernel %s\n", aKernelConfig[i].krnl_name);
     452            return -1;
     453        }
     454        kList[i].prfBank = aKernelConfig[i].prfBank;
     455        kList[i].cmdQ = clCreateCommandQueue(*aContext, *aDevice, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE, &err);
     456        //kList[i].cmdQ = clCreateCommandQueue(*aContext, *aDevice, 0, &err);
     457        if (err != CL_SUCCESS) {
     458            xcl_FreeKernels(kList, i+1);
     459            printf("Error: OpenCL unable to create CommandQueue\n");
     460            return -1;
     461        }
     462        kList[i].context = aContext;
     463    }
     464    *aKernelList = kList;
     465    return 0;
     466}
     467
     468int xcl_FreeKernels(xlnx_kernel* aKernelList, uint32_t aNumKernels) {
     469    if (aKernelList == NULL) return -1;
     470    for (int i = 0; i < aNumKernels; i++) {
     471        if (aKernelList[i].kernel)
     472            clReleaseKernel(aKernelList[i].kernel);
     473        if (aKernelList[i].cmdQ)
     474            clReleaseCommandQueue(aKernelList[i].cmdQ);
     475    }
     476    free(aKernelList);
     477    return 0;
     478}
  • new file libavcodec/xlnx_hw/common/src/xlnx_hrm.c

    diff --git a/libavcodec/xlnx_hw/common/src/xlnx_hrm.c b/libavcodec/xlnx_hw/common/src/xlnx_hrm.c
    new file mode 100644
    index 0000000..90671f6
    - +  
     1#include <string.h>
     2#include <stdio.h>
     3#include <pthread.h>
     4#include <assert.h>
     5#include "../inc/xcl.h"
     6#include "../inc/xlnx_hrm.h"
     7#include "../inc/xlnx_hw_defines.h"
     8#include "../../xlnx_hw_types.h"
     9#include "../..//hevc/ku115_hevc_enc_config.h"
     10#include "../../hevc/vu9p_hevc_enc_config.h"
     11
     12#include "../../hevc/enc_vu9p.h"
     13#include "../../hevc/enc_vu9p_2c.h"
     14
     15// Wrap any OpenCL API calls that return error code(cl_int)
     16// with the below macro to quickly check for an error
     17#define XCL_CHECK(call)                                              \
     18do {                                                                 \
     19    int err = call;                                                  \
     20    if (err != 0) {                                                  \
     21        printf("Error from " #call ", error code is %d\n", err);     \
     22        destroy_hrm();                                               \
     23        return err;                                                  \
     24    }                                                                \
     25} while (0);
     26
     27static pthread_mutex_t * volatile atomic_hrm_lock = NULL;
     28#define LOCK_HRM pthread_mutex_lock(atomic_hrm_lock)
     29#define UNLOCK_HRM pthread_mutex_unlock(atomic_hrm_lock)
     30
     31static uint32_t xlnx_init_count = 0;
     32
     33typedef struct xlnx_krnl_info {
     34    const char* kName;
     35    xlnx_hw_id hwID;
     36    uint32_t numCh;
     37    // Can hold status for Max 32 channels
     38    uint32_t chStatus;
     39    uint32_t refCount;
     40} xlnx_krnl_info;
     41
     42typedef struct xlnx_dev_info {
     43    cl_program program;
     44    uint32_t nKernels;
     45    xlnx_kernel* kernelList;
     46    xlnx_krnl_info* krnlInfo;
     47} xlnx_dev_info;
     48
     49typedef enum xlnx_dev_type {
     50    ENONE,
     51    EKU115,
     52    EVU9P
     53} xlnx_dev_type;
     54
     55typedef struct xlnx_hrm {
     56    cl_platform_id platform_id;
     57    cl_context context;
     58    cl_uint nDevices;
     59    xlnx_device* deviceList;
     60} xlnx_hrm;
     61
     62static xlnx_hrm* gHRM = NULL;
     63
     64static int clear_device_info(xlnx_dev_info* aDevInfo) {
     65    if (aDevInfo == NULL) return -1;
     66    if (aDevInfo->krnlInfo) free(aDevInfo->krnlInfo);
     67    if (aDevInfo->kernelList) xcl_FreeKernels(aDevInfo->kernelList, aDevInfo->nKernels);
     68    if (aDevInfo->program) xcl_ReleaseProgram(&aDevInfo->program);
     69    free(aDevInfo);
     70    return 0;
     71}
     72
     73static int clear_device_list(void) {
     74    int i;
     75    xlnx_dev_info* temp;
     76    if (gHRM->deviceList == NULL) return 0;
     77    for (i = 0; i < gHRM->nDevices; i++) {
     78        if (gHRM->deviceList[i].privData != NULL) {
     79            temp = (xlnx_dev_info*)gHRM->deviceList[i].privData;
     80            clear_device_info(temp);
     81            gHRM->deviceList[i].privData = NULL;
     82        }
     83    }
     84    xcl_FreeDeviceList(gHRM->deviceList, gHRM->nDevices);
     85    return 0;
     86}
     87
     88static int setup_KU115(xlnx_device* aDevice, xlnx_hw_id aHWID) {
     89    //@ToDo parsing of config and loading of appropriate binary
     90    //Assume the profile 1K1C/KU115 = kernel binary
     91    int ret = -1;
     92    xlnx_dev_info* devInfo;
     93    int nK;
     94    xlnx_krnl_info* info;
     95    printf("setup_KU115\n");
     96    devInfo = (xlnx_dev_info*) calloc(1, sizeof(xlnx_dev_info));
     97    if (devInfo == NULL) {
     98        printf("Error: OOM %s at %d\n", __FILE__, __LINE__);
     99        return -1;
     100    }
     101    if (aHWID == EHevcEnc) {
     102    // Header based loading
     103#if LOAD_BINARY_FROM_HEADER
     104        ret = xcl_ImportBinaryHeader(&gHRM->context, &aDevice->device, hevc_xclbin, hevc_xclbin_len, &devInfo->program);
     105#else
     106        ret = xcl_ImportBinary(&gHRM->context, &aDevice->device, KU115_HEVC_ENC_BINARY, &devInfo->program);
     107#endif //LOAD_BINARY_FROM_HEADER
     108        if (ret < 0) {
     109            free(devInfo);
     110            return -1;
     111        }
     112        nK =  sizeof(KU115_HEVC_KRNL_NAME)/sizeof(char*);
     113        ret = xcl_CreateKernels(&gHRM->context, &aDevice->device, &devInfo->program, KU115_HEVC_KRNL_NAME, nK,
     114                          &devInfo->kernelList);
     115        if (ret < 0) {
     116            clear_device_info(devInfo);
     117            return -1;
     118        }
     119        devInfo->nKernels = nK;
     120        devInfo->krnlInfo = (xlnx_krnl_info*) calloc(nK, sizeof(xlnx_krnl_info));
     121        if (NULL == devInfo->krnlInfo) {
     122            clear_device_info(devInfo);
     123            return -1;
     124        }
     125        info = devInfo->krnlInfo;
     126        for (int i = 0; i < nK; i++) {
     127            info[i].kName = KU115_HEVC_KRNL_NAME[i];
     128            info[i].hwID = EHevcEnc;
     129            info[i].refCount = 0;
     130        }
     131    }
     132    aDevice->privData = (void*)devInfo;
     133    return 0;
     134}
     135
     136static int setup_VU9P(xlnx_device* aDevice, xlnx_hw_id aHWID) {
     137    int ret = -1;
     138    xlnx_dev_info* devInfo;
     139    char* xcl_fullpath;
     140    unsigned char* xcl_path;
     141    int nK;
     142    int i;
     143    xlnx_krnl_info* info;
     144    uint32_t numCh = VU9P_HEVC_ENC_NUM_CH;
     145    unsigned char* numch;
     146
     147    printf("Setup VU9P\n");
     148    devInfo = (xlnx_dev_info*) calloc(1, sizeof(xlnx_dev_info));
     149    if (devInfo == NULL) {
     150        printf("Error: OOM %s at %d\n", __FILE__, __LINE__);
     151        return -1;
     152    }
     153    if (aHWID == EHevcEnc) {
     154    // Header based loading
     155#if LOAD_BINARY_FROM_HEADER
     156        ret = xcl_ImportBinaryHeader(&gHRM->context, &aDevice->device, hevc_enc_vu9p_2k2c_xclbin, hevc_enc_vu9p_2k2c_xclbin_len, &devInfo->program);
     157#else
     158        xcl_fullpath = malloc(FILE_PATH_LENGTH);
     159        xcl_path = getenv("XLNX_XCLBIN_PATH");
     160        if (NULL != xcl_path) {
     161            snprintf(xcl_fullpath, FILE_PATH_LENGTH, "%s/%s", xcl_path, VU9P_HEVC_ENC_BINARY);
     162        } else {
     163            printf(" * XLNX_XCLBIN_PATH not found\n");
     164            snprintf(xcl_fullpath, FILE_PATH_LENGTH, "%s", VU9P_HEVC_ENC_BINARY);
     165        }
     166        ret = xcl_ImportBinary(&gHRM->context, &aDevice->device, xcl_fullpath, &devInfo->program);
     167        free(xcl_fullpath);
     168#endif //LOAD_BINARY_FROM_HEADER
     169        if (ret < 0) {
     170            free(devInfo);
     171            return -1;
     172        }
     173        nK =  sizeof(VU9P_HEVC_CONFIG)/sizeof(KRNL_CONFIG);
     174        ret = xcl_CreateKernels2(&gHRM->context, &aDevice->device, &devInfo->program, VU9P_HEVC_CONFIG, nK,
     175                          &devInfo->kernelList);
     176        if (ret < 0) {
     177            clear_device_info(devInfo);
     178            return -1;
     179        }
     180        devInfo->nKernels = nK;
     181        devInfo->krnlInfo = (xlnx_krnl_info*) calloc(nK, sizeof(xlnx_krnl_info));
     182        if (NULL == devInfo->krnlInfo) {
     183            clear_device_info(devInfo);
     184            return -1;
     185        }
     186        info = devInfo->krnlInfo;
     187        for (i = 0; i < nK; i++) {
     188            // @Todo load info from some source
     189            // for now, hardcore infor for hevc 2k2c
     190            info[i].kName = VU9P_HEVC_CONFIG[i].krnl_name;
     191            info[i].hwID = EHevcEnc;
     192            numCh = VU9P_HEVC_ENC_NUM_CH;
     193            numch = getenv("VU9P_HEVC_ENC_NUM_CH");
     194            if (NULL != numch) {
     195                numCh = atoi(numch);
     196                printf(" * VU9P_HEVC_ENC_NUM_CH set to = %d\n", VU9P_HEVC_ENC_NUM_CH);
     197            } else {
     198                printf(" * VU9P_HEVC_ENC_NUM_CH not set. Default = %d\n", VU9P_HEVC_ENC_NUM_CH);
     199            }
     200            info[i].numCh = numCh;
     201            info[i].chStatus = 0;
     202            info[i].refCount = 0;
     203            devInfo->kernelList[i].privData = (void*)&info[i];
     204        }
     205    }
     206    aDevice->privData = (void*)devInfo;
     207    return 0;
     208}
     209
     210static xlnx_dev_type get_device_type(const xlnx_device* device) {
     211    assert(device != NULL);
     212    if (!strncmp(device->devName, KU115_BOARD, strlen(KU115_BOARD))) {
     213        return EKU115;
     214    } else if (!strncmp(device->devName, VU9P_BOARD, strlen(VU9P_BOARD))) {
     215        return EVU9P;
     216    }
     217    return ENONE;
     218}
     219
     220static int setup_devices(const char* aCfgFileName, xlnx_hw_id aHWID) {
     221    //@Todo depending upon the config file or environment variable settings,
     222    //create context and load binaries here or at a later stage
     223    // for now just assume HEVC encoder config only.
     224    int ret = -1;
     225    xlnx_device* device = NULL;
     226    /* seems CL_DEVICE_AVAILABLE not implemented in runtime
     227    for (int i = 0; i < gHRM->nDevices; i++) {
     228        if (xcl_IsDeviceAvailable(gHRM->deviceList[i].device)) {
     229            device = &gHRM->deviceList[i];
     230            break;
     231        }
     232    }*/
     233    //So choose the first available device
     234    // @TODO setup for all the available devices
     235
     236    device = &gHRM->deviceList[0];
     237    if (NULL == device) {
     238        return -1;
     239    }
     240    switch (get_device_type(device)) {
     241      case EKU115:
     242          ret = setup_KU115(device, aHWID);
     243          break;
     244      case EVU9P:
     245          ret = setup_VU9P(device, aHWID);
     246          break;
     247      case ENONE:
     248      default:
     249          return -1;
     250    }
     251    return ret;
     252}
     253
     254static void destroy_hrm(void) {
     255    printf("destroy_hrm\n");
     256    assert(gHRM != NULL);
     257    if (gHRM->deviceList)
     258        clear_device_list();
     259    gHRM->deviceList = NULL;
     260    if (gHRM->context)
     261        xcl_ReleaseContext(&gHRM->context);
     262    gHRM->context = 0;
     263    free(gHRM);
     264    gHRM = NULL;
     265    printf("destroyed hrm\n");
     266}
     267
     268static int create_hrm(const char* aCfgFileName, xlnx_hw_id aHWID) {
     269    //@Todo parse aCfgFileName
     270    // For now aCfgFileName is the URI of the Kernal binary file
     271    printf("create_hrm\n");
     272    assert(gHRM == NULL);
     273    gHRM = calloc(1, sizeof(xlnx_hrm));
     274    if (!gHRM) {
     275        printf("Error: OOM %s at %d\n", __FILE__, __LINE__);
     276        return -1;
     277    }
     278    XCL_CHECK(xcl_GetPlatform("Xilinx", &gHRM->platform_id));
     279    XCL_CHECK(xcl_CreateContextFromType(&gHRM->platform_id, CL_DEVICE_TYPE_ACCELERATOR, &gHRM->context));
     280    XCL_CHECK(xcl_GetDeviceList(&gHRM->platform_id, CL_DEVICE_TYPE_ACCELERATOR, &gHRM->deviceList, &gHRM->nDevices));
     281    //If aHWID is known, then setup the devices here
     282    if (ENone != aHWID) {
     283        XCL_CHECK(setup_devices(aCfgFileName, aHWID));
     284    }
     285    printf("created hrm\n");
     286    return 0;
     287}
     288
     289static inline int init_hrm_mtx(void) {
     290    if (!atomic_hrm_lock) {
     291        int err;
     292        pthread_mutex_t *tmp = malloc(sizeof(pthread_mutex_t));
     293        if (!tmp)
     294            return -1;
     295        if ((err = pthread_mutex_init(tmp, NULL))) {
     296            free(tmp);
     297            return err;
     298        }
     299        if (__sync_val_compare_and_swap((void * volatile *)&atomic_hrm_lock, NULL, tmp)) {
     300            pthread_mutex_destroy(tmp);
     301            free(tmp);
     302        }
     303    }
     304    return 0;
     305}
     306
     307static inline int deinit_hrm_mtx(void) {
     308    if (atomic_hrm_lock) {
     309        pthread_mutex_t *tmp = atomic_hrm_lock;
     310        UNLOCK_HRM;
     311        pthread_mutex_destroy(atomic_hrm_lock);
     312        atomic_hrm_lock = NULL;
     313        free(tmp);
     314    }
     315    return 0;
     316}
     317
     318int xlnx_hrm_init(const char* aCfgFileName, xlnx_hw_id aHWID) {
     319    int ret = init_hrm_mtx();
     320    if (ret < 0)
     321        return ret;
     322
     323    LOCK_HRM;
     324
     325    if (xlnx_init_count == 0) {
     326        ret = create_hrm(aCfgFileName, aHWID);
     327        if (ret < 0) {
     328            deinit_hrm_mtx();
     329            return -1;
     330        }
     331    }
     332    xlnx_init_count++;
     333
     334    UNLOCK_HRM;
     335    return xlnx_init_count;
     336}
     337
     338int xlnx_hrm_deinit() {
     339    LOCK_HRM;
     340    xlnx_init_count--;
     341    if (xlnx_init_count == 0) {
     342        destroy_hrm();
     343    } else {
     344      uint32_t count = xlnx_init_count;
     345        UNLOCK_HRM;
     346        return count;
     347    }
     348    deinit_hrm_mtx();
     349    return 0;
     350}
     351
     352static int allocChannel(int aNumCh, int* aChStatus) {
     353    for(int i = 0; i < aNumCh; i++) {
     354        if ((*aChStatus & (1 << i)) == 0) {
     355            *aChStatus = *aChStatus | (1<<i);
     356            return i;
     357        }
     358    }
     359    return -1;
     360}
     361
     362static int alloc_xKernel(xlnx_dev_info* devInfo, xlnx_hw_id aHWID, int* aIndex, int* aChannel) {
     363    for (int i = 0; i < devInfo->nKernels; i++) {
     364        xlnx_krnl_info* kInfo = &devInfo->krnlInfo[i];
     365        if ((kInfo->hwID == aHWID) && (kInfo->refCount < kInfo->numCh)) {
     366            int ch = allocChannel(kInfo->numCh, &kInfo->chStatus);
     367            if (ch < 0) return ch;
     368            kInfo->refCount++;
     369            *aChannel = ch;
     370            *aIndex = i;
     371            return 0;
     372        }
     373    }
     374    return -1;
     375}
     376
     377static int free_xKernel(xlnx_krnl_info* aKrnlInfo, int aChannel) {
     378    if (aKrnlInfo) {
     379        aKrnlInfo->refCount--;
     380        assert(aKrnlInfo->chStatus & (1 << aChannel));
     381        aKrnlInfo->chStatus &= ~(1 << aChannel);
     382    }
     383    else
     384        return -1;
     385    return 0;
     386}
     387
     388xlnx_host* xlnx_hrm_get_host(xlnx_hw_id aHWID, xlnx_hw_params aParams) {
     389    // @TODO
     390    // Device setup can be delayed to this point as well
     391    // It will either be done as part of hrm init(if aHWID is known) or delayed till this point.
     392    // hrm is being initialized from here in the current case, so it does not make a difference
     393    xlnx_host* host = NULL;
     394    xlnx_dev_info* devInfo;
     395    int kIndex, ch, ret;
     396
     397    if (aHWID == ENONE) return host;
     398    if (xlnx_hrm_init(NULL, aHWID) < 0) {
     399        return host;
     400    }
     401    LOCK_HRM;
     402    //@TODO check the whole devicelist
     403    devInfo = (xlnx_dev_info*)gHRM->deviceList[0].privData;
     404    if (devInfo == NULL) {
     405        // Should not happen as hrm init i sdone with xlnx_hw_id
     406        // Other wise setup_devices() should be done here
     407        UNLOCK_HRM;
     408        return host;
     409    }
     410
     411    ret = alloc_xKernel(devInfo, aHWID, &kIndex, &ch);
     412    if (ret < 0) {
     413        UNLOCK_HRM;
     414        return host;
     415    }
     416    // ONLY HEVC ENc host available right now!!
     417    //@Todo update when other hosts are available
     418    if (aHWID == EHevcEnc) {
     419        host = createHevcEnc2C(&devInfo->kernelList[kIndex], ch, aParams);
     420        if (host == NULL) {
     421            free_xKernel(&devInfo->krnlInfo[kIndex], ch);
     422            UNLOCK_HRM;
     423            printf("Error: Cannot allocate memory for xlnx_host %s at %d\n", __FILE__, __LINE__);
     424            return host;
     425        }
     426    } else {
     427        UNLOCK_HRM;
     428        return host;
     429    }
     430
     431    host->appData = (void*) &devInfo->krnlInfo[kIndex];
     432    UNLOCK_HRM;
     433    return host;
     434}
     435
     436int xlnx_hrm_release_host(xlnx_host* aHost) {
     437    xlnx_krnl_info* krnlInfo;
     438    if (NULL == aHost) return -1;
     439    krnlInfo = (xlnx_krnl_info*)aHost->appData;
     440    if (free_xKernel(krnlInfo, aHost->ch) < 0) return -1;
     441    destroyHevcEnc2C(aHost);
     442    xlnx_hrm_deinit();
     443    return 0;
     444}
  • new file libavcodec/xlnx_hw/common/src/xlnx_queue.c

    diff --git a/libavcodec/xlnx_hw/common/src/xlnx_queue.c b/libavcodec/xlnx_hw/common/src/xlnx_queue.c
    new file mode 100644
    index 0000000..3233cf3
    - +  
     1#include <stdio.h>
     2#include <stdlib.h>
     3#include <assert.h>
     4#include "../inc/xlnx_queue.h"
     5
     6struct xlnx_queue {
     7    int front, rear;
     8    size_t size, capacity;
     9    XItem* pItem;
     10};
     11
     12xlnx_queue* createQueue(size_t capacity) {
     13    xlnx_queue* queue = (xlnx_queue*) malloc(sizeof(xlnx_queue));
     14    if (NULL == queue) {
     15        printf("Error: Out of Memory! %s at %d\n", __FILE__, __LINE__);
     16        return queue;
     17    }
     18    queue->capacity = capacity;
     19    queue->front = queue->size = 0;
     20    queue->rear = -1;
     21    queue->pItem = (XItem*)malloc(queue->capacity * sizeof(XItem));
     22    if (NULL == queue->pItem) {
     23        printf("Error: Out of Memory! %s at %d\n", __FILE__, __LINE__);
     24        free(queue);
     25        return NULL;
     26    }
     27    return queue;
     28}
     29
     30void destroyQueue(xlnx_queue* queue) {
     31    if (NULL == queue) return;
     32    free(queue->pItem);
     33    free(queue);
     34    return;
     35}
     36
     37int isFull(xlnx_queue* queue) {
     38    assert(queue != NULL);
     39    return (queue->size == queue->capacity);
     40}
     41
     42int isEmpty(xlnx_queue* queue) {
     43    assert(queue != NULL);
     44    return (queue->size == 0);
     45}
     46
     47size_t getSize(xlnx_queue* queue) {
     48    assert(queue != NULL);
     49    return queue->size;
     50}
     51
     52int enqueue(xlnx_queue* queue, XItem item) {
     53    assert(queue != NULL);
     54    if (isFull(queue))
     55        return -1;
     56    queue->rear = (queue->rear + 1)%queue->capacity;
     57    queue->pItem[queue->rear] = item;
     58    queue->size++;
     59    return 0;
     60}
     61
     62XItem dequeue(xlnx_queue* queue) {
     63    XItem item;
     64    assert(queue != NULL);
     65    if (isEmpty(queue))
     66        return NULL;
     67    item = queue->pItem[queue->front];
     68    queue->pItem[queue->front] = 0;
     69    queue->front = (queue->front + 1)%queue->capacity;
     70    queue->size = queue->size - 1;
     71    return item;
     72}
     73
     74XItem front(xlnx_queue* queue) {
     75    assert(queue != NULL);
     76    if (isEmpty(queue))
     77        return NULL;
     78    return queue->pItem[queue->front];
     79}
     80
     81XItem rear(xlnx_queue* queue) {
     82    assert(queue != NULL);
     83    if (isEmpty(queue))
     84        return NULL;
     85    return queue->pItem[queue->rear];
     86}
     87 No newline at end of file
  • new file libavcodec/xlnx_hw/common/src/xlnx_ts_queue.c

    diff --git a/libavcodec/xlnx_hw/common/src/xlnx_ts_queue.c b/libavcodec/xlnx_hw/common/src/xlnx_ts_queue.c
    new file mode 100644
    index 0000000..507040a
    - +  
     1#include <stdio.h>
     2#include <stdlib.h>
     3#include <assert.h>
     4#include <pthread.h>
     5
     6#include "../inc/xlnx_ts_queue.h"
     7
     8#define LOCK_Q pthread_mutex_lock(&queue->lock)
     9#define UNLOCK_Q pthread_mutex_unlock(&queue->lock)
     10
     11struct xlnx_ts_queue {
     12    pthread_mutex_t lock;
     13    xlnx_queue* q;
     14};
     15
     16xlnx_ts_queue* createTSQ(size_t capacity) {
     17    xlnx_queue* queue;
     18    xlnx_ts_queue* q = calloc(1, sizeof(xlnx_ts_queue));
     19    if (NULL == q) {
     20        printf("Error: Out of Memory! %s at %d\n", __FILE__, __LINE__);
     21        return q;
     22    }
     23    queue = createQueue(capacity);
     24    if (NULL == queue) {
     25        printf("Error: Out of Memory! %s at %d\n", __FILE__, __LINE__);
     26        free(q);
     27        return NULL;
     28    }
     29    q->q = queue;
     30    if (pthread_mutex_init(&q->lock, NULL) < 0) {
     31        destroyQueue(queue);
     32        free(q);
     33        return NULL;
     34    }
     35    return q;
     36}
     37
     38void destroyTSQ(xlnx_ts_queue* queue) {
     39    if (NULL == queue) return;
     40    pthread_mutex_destroy(&queue->lock);
     41    destroyQueue(queue->q);
     42    free(queue);
     43    return;
     44}
     45
     46int isFullTSQ(xlnx_ts_queue* queue) {
     47    int ret;
     48    assert(queue != NULL);
     49    LOCK_Q;
     50    ret = isFull(queue->q);
     51    UNLOCK_Q;
     52    return ret;
     53}
     54
     55int isEmptyTSQ(xlnx_ts_queue* queue) {
     56    int ret;
     57    assert(queue != NULL);
     58    LOCK_Q;
     59    ret = isEmpty(queue->q);
     60    UNLOCK_Q;
     61    return ret;
     62}
     63
     64size_t getSizeTSQ(xlnx_ts_queue* queue) {
     65    size_t size;
     66    assert(queue != NULL);
     67    LOCK_Q;
     68    size = getSize(queue->q);
     69    UNLOCK_Q;
     70    return size;
     71}
     72
     73int enqueueTSQ(xlnx_ts_queue* queue, XItem item) {
     74    int ret;
     75    assert(queue != NULL);
     76    LOCK_Q;
     77    ret = enqueue(queue->q, item);
     78    UNLOCK_Q;
     79    return ret;
     80}
     81
     82XItem dequeueTSQ(xlnx_ts_queue* queue) {
     83    XItem item;
     84    assert(queue != NULL);
     85    LOCK_Q;
     86    item = dequeue(queue->q);
     87    UNLOCK_Q;
     88    return item;
     89}
     90
     91XItem frontTSQ(xlnx_ts_queue* queue) {
     92    XItem item;
     93    assert(queue != NULL);
     94    LOCK_Q;
     95    item = front(queue->q);
     96    UNLOCK_Q;
     97    return item;
     98}
     99
     100XItem rearTSQ(xlnx_ts_queue* queue) {
     101    XItem item;
     102    assert(queue != NULL);
     103    LOCK_Q;
     104    item = rear(queue->q);
     105    UNLOCK_Q;
     106    return item;
     107}
     108 No newline at end of file
  • new file libavcodec/xlnx_hw/hevc/Makefile

    diff --git a/libavcodec/xlnx_hw/hevc/Makefile b/libavcodec/xlnx_hw/hevc/Makefile
    new file mode 100644
    index 0000000..2c49c2b
    - +  
     1OBJS                            += xlnx_hw/hevc/enc_vu9p.o
  • new file libavcodec/xlnx_hw/hevc/enc_vu9p.c

    diff --git a/libavcodec/xlnx_hw/hevc/enc_vu9p.c b/libavcodec/xlnx_hw/hevc/enc_vu9p.c
    new file mode 100644
    index 0000000..19c41d1
    - +  
     1#include <stdio.h>
     2#include <stdlib.h>
     3#include <unistd.h>
     4#include <limits.h>
     5#include <string.h>
     6#include <assert.h>
     7#include <CL/opencl.h>
     8#include "enc_vu9p.h"
     9#include "../common/inc/xlnx_hw_defines.h"
     10
     11//Macros
     12
     13#define OCLCHECKI(method, ... )                                                \
     14do {                                                                           \
     15    status = method(__VA_ARGS__);                                              \
     16    if (status != CL_SUCCESS) {                                                \
     17        printf( # method " error '%d'\n", status);                             \
     18        KDD_deinit(aKDD);                                                      \
     19        return -1;                                                             \
     20    }                                                                          \
     21} while (0)
     22
     23#define CREATEBUF(out, flags, size)                                            \
     24do {                                                                           \
     25    out = clCreateBuffer(*context, flags, size, NULL, &status);                \
     26    if (status != CL_SUCCESS) {                                                \
     27        printf("Could not create OpenCL buffer\n");                            \
     28        KDD_deinit(aKDD);                                                      \
     29        return -1;                                                             \
     30    }                                                                          \
     31} while (0)
     32
     33typedef struct KernelDeviceData {
     34    // CSR3/CSR4/CSR5
     35    cl_mem  InCur[3];
     36    // CSR6/CSR7/CSR8
     37    cl_mem  inNxt[3];
     38    cl_mem  CSR12_RECON_BASE_V;
     39    cl_mem  CSR13_BITSTREAM_BASE_V;
     40    cl_mem  CSR14_BITSTREAM_LEN_V;
     41    U32 CurImgSize[3];
     42    U32 EncodedFrameSize;
     43    U32 EncodedFrameLengthSize;
     44    HevcEncParam* params;
     45} KernelDeviceData;
     46typedef KernelDeviceData KDD;
     47
     48typedef struct HevcEnc {
     49    //KHD khd;
     50    KDD kdd;
     51    HevcEncParam params;
     52    xlnx_kernel* xKernel;
     53    U32 frameNumber;
     54} HevcEnc;
     55
     56static int KDD_deinit(KDD* aKDD) {
     57    if (aKDD->InCur[Y]) clReleaseMemObject(aKDD->InCur[Y]);
     58    if (aKDD->InCur[U]) clReleaseMemObject(aKDD->InCur[U]);
     59    if (aKDD->InCur[V]) clReleaseMemObject(aKDD->InCur[V]);
     60    if (aKDD->inNxt[Y]) clReleaseMemObject(aKDD->inNxt[Y]);
     61    if (aKDD->inNxt[U]) clReleaseMemObject(aKDD->inNxt[U]);
     62    if (aKDD->inNxt[V]) clReleaseMemObject(aKDD->inNxt[V]);
     63    if (aKDD->CSR12_RECON_BASE_V) clReleaseMemObject(aKDD->CSR12_RECON_BASE_V);
     64    if (aKDD->CSR13_BITSTREAM_BASE_V) clReleaseMemObject(aKDD->CSR13_BITSTREAM_BASE_V);
     65    if (aKDD->CSR14_BITSTREAM_LEN_V) clReleaseMemObject(aKDD->CSR14_BITSTREAM_LEN_V);
     66    memset(aKDD, 0, sizeof(KDD));
     67    return 0;
     68}
     69
     70static int KDD_init(KDD* aKDD, HevcEnc* aEnc) {
     71    cl_int status;
     72    U32 width, height;
     73    cl_kernel kernel;
     74    cl_context* context;
     75    int arg = 0;
     76    if ((aKDD == NULL) || (aEnc == NULL)) return -1;
     77    status = -1;
     78    aKDD->params = &aEnc->params;
     79    width = aKDD->params->width;
     80    height = aKDD->params->height;
     81    aKDD->CurImgSize[Y] = width * height;
     82    aKDD->CurImgSize[U] = (width * height) >> 2;
     83    aKDD->CurImgSize[V] = (width * height) >> 2;
     84
     85    // Encoded Frame data size - hard code to allocate host memory as this varies!
     86    aKDD->EncodedFrameSize = (width * height * 3) >> 1;
     87    aKDD->EncodedFrameLengthSize = 1;
     88
     89    // Setup the CSR registers
     90    kernel = aEnc->xKernel->kernel;
     91    context = aEnc->xKernel->context;
     92    CREATEBUF(aKDD->InCur[Y], CL_MEM_READ_ONLY,  aKDD->CurImgSize[Y] * sizeof(U8));
     93    CREATEBUF(aKDD->InCur[U], CL_MEM_READ_ONLY,  aKDD->CurImgSize[U] * sizeof(U8));
     94    CREATEBUF(aKDD->InCur[V], CL_MEM_READ_ONLY,  aKDD->CurImgSize[V] * sizeof(U8));
     95    CREATEBUF(aKDD->inNxt[Y], CL_MEM_READ_ONLY,  aKDD->CurImgSize[Y] * sizeof(U8));
     96    CREATEBUF(aKDD->inNxt[U], CL_MEM_READ_ONLY,  aKDD->CurImgSize[U] * sizeof(U8));
     97    // Padding to make reference base pointer of reconstructed picture 128KB aligned
     98    CREATEBUF(aKDD->inNxt[V], CL_MEM_READ_ONLY,  (aKDD->CurImgSize[V]+ 48*128*1024-1920*1080*3) * sizeof(U8));
     99    // Reference frame requires at least 16MB space in DDR
     100    CREATEBUF(aKDD->CSR12_RECON_BASE_V, CL_MEM_READ_WRITE,  16*1024*1024);
     101    CREATEBUF(aKDD->CSR13_BITSTREAM_BASE_V, CL_MEM_WRITE_ONLY, aKDD->EncodedFrameSize * sizeof(U8));
     102    CREATEBUF(aKDD->CSR14_BITSTREAM_LEN_V, CL_MEM_WRITE_ONLY, aKDD->EncodedFrameLengthSize * sizeof(U64));
     103
     104    OCLCHECKI(clSetKernelArg, kernel, arg++, sizeof(U32), &aKDD->params->width);
     105    OCLCHECKI(clSetKernelArg, kernel, arg++, sizeof(U32), &aKDD->params->height);
     106    OCLCHECKI(clSetKernelArg, kernel, arg++, sizeof(cl_mem),       &aKDD->InCur[Y]);
     107    OCLCHECKI(clSetKernelArg, kernel, arg++, sizeof(cl_mem),       &aKDD->InCur[U]);
     108    OCLCHECKI(clSetKernelArg, kernel, arg++, sizeof(cl_mem),       &aKDD->InCur[V]);
     109    OCLCHECKI(clSetKernelArg, kernel, arg++, sizeof(cl_mem),       &aKDD->inNxt[Y]);
     110    OCLCHECKI(clSetKernelArg, kernel, arg++, sizeof(cl_mem),       &aKDD->inNxt[U]);
     111    OCLCHECKI(clSetKernelArg, kernel, arg++, sizeof(cl_mem),       &aKDD->inNxt[V]);
     112    OCLCHECKI(clSetKernelArg, kernel, arg++, sizeof(U32), &aKDD->params->bitrate);
     113    OCLCHECKI(clSetKernelArg, kernel, arg++, sizeof(U32), &aKDD->params->qp);
     114    OCLCHECKI(clSetKernelArg, kernel, arg++, sizeof(U32), &aKDD->params->ip);
     115    OCLCHECKI(clSetKernelArg, kernel, arg++, sizeof(cl_mem),       &aKDD->CSR12_RECON_BASE_V);
     116    OCLCHECKI(clSetKernelArg, kernel, arg++, sizeof(cl_mem),       &aKDD->CSR13_BITSTREAM_BASE_V);
     117    OCLCHECKI(clSetKernelArg, kernel, arg++, sizeof(cl_mem),       &aKDD->CSR14_BITSTREAM_LEN_V);
     118    OCLCHECKI(clSetKernelArg, kernel, arg++, sizeof(U32), &aKDD->params->reset);
     119    return 0;
     120}
     121
     122static int hevc_encode(xlnx_host* aHost, xlnx_hw_params aParams, xlnx_hw_buf* aInput, xlnx_hw_buf* aOutput) {
     123    cl_command_queue cmdQ;
     124    cl_kernel kernel;
     125    xlnx_data_buf* iHBuf;
     126    xlnx_data_buf* oBuf;
     127    size_t global_work_size_1d[1];
     128    size_t local_work_size_1d[1];
     129    int size;
     130    cl_int status = -1;
     131    HevcEnc* enc = (HevcEnc*)aHost->privData;
     132    KDD kdd = enc->kdd;
     133    HevcEncParam* params = (HevcEncParam*) aParams;
     134    xlnx_kernel* xKernel = enc->xKernel;
     135    U32 frameNumber = enc->frameNumber;
     136
     137    if ((frameNumber == 0) && (aInput->ptr == NULL)) { return -1;}
     138
     139    cmdQ = xKernel->cmdQ;
     140    kernel = xKernel->kernel;
     141
     142    assert(aInput->type == ERAW);
     143    assert(aOutput->type == EDATA);
     144    iHBuf = aInput->ptr;
     145    oBuf = aOutput->ptr;
     146
     147    global_work_size_1d[0] = 1;
     148    local_work_size_1d[0] = 1;
     149    size = 0;
     150
     151    if (frameNumber == 0) {
     152        for (int i = 0; i < 3; i++) {
     153            size = kdd.CurImgSize[i] * sizeof(U8);
     154            ENQUEUEBUF(clEnqueueWriteBuffer, kdd.InCur[i]);
     155        }
     156        enc->frameNumber++;
     157        oBuf->size = 0;
     158        return 0;
     159    } else if (frameNumber == 1) {
     160        if (aInput->ptr != NULL) {
     161            for (int i = 0; i < 3; i++) {
     162                size = kdd.CurImgSize[i] * sizeof(U8);
     163                ENQUEUEBUF(clEnqueueWriteBuffer, kdd.inNxt[i]);
     164            }
     165        } else {
     166            OCLCHECK(clSetKernelArg, kernel, 14, sizeof(U32), &params->reset);
     167        }
     168        // av_log(NULL, AV_LOG_INFO," * Loading frame %d\n", frameNumber);
     169        enc->frameNumber++;
     170    } else {
     171        // Ping-pong buffers used; switch cur and nxt buffer pointer for kernel
     172        if (frameNumber%2 == 0) {
     173            OCLCHECK(clSetKernelArg, kernel, 2, sizeof(cl_mem), &kdd.inNxt[Y]);
     174            OCLCHECK(clSetKernelArg, kernel, 3, sizeof(cl_mem), &kdd.inNxt[U]);
     175            OCLCHECK(clSetKernelArg, kernel, 4, sizeof(cl_mem), &kdd.inNxt[V]);
     176            OCLCHECK(clSetKernelArg, kernel, 5, sizeof(cl_mem), &kdd.InCur[Y]);
     177            OCLCHECK(clSetKernelArg, kernel, 6, sizeof(cl_mem), &kdd.InCur[U]);
     178            OCLCHECK(clSetKernelArg, kernel, 7, sizeof(cl_mem), &kdd.InCur[V]);
     179            if (aInput->ptr != NULL) {
     180                for (int i = 0; i < 3; i++) {
     181                    size = kdd.CurImgSize[i] * sizeof(U8);
     182                    ENQUEUEBUF(clEnqueueWriteBuffer, kdd.InCur[i]);
     183                }
     184            } else {
     185                OCLCHECK(clSetKernelArg, kernel, 14, sizeof(U32), &params->reset);
     186            }
     187        } else {
     188            OCLCHECK(clSetKernelArg, kernel, 2, sizeof(cl_mem), &kdd.InCur[Y]);
     189            OCLCHECK(clSetKernelArg, kernel, 3, sizeof(cl_mem), &kdd.InCur[U]);
     190            OCLCHECK(clSetKernelArg, kernel, 4, sizeof(cl_mem), &kdd.InCur[V]);
     191            OCLCHECK(clSetKernelArg, kernel, 5, sizeof(cl_mem), &kdd.inNxt[Y]);
     192            OCLCHECK(clSetKernelArg, kernel, 6, sizeof(cl_mem), &kdd.inNxt[U]);
     193            OCLCHECK(clSetKernelArg, kernel, 7, sizeof(cl_mem), &kdd.inNxt[V]);
     194            if (aInput->ptr != NULL) {
     195                for (int i = 0; i < 3; i++) {
     196                    size = kdd.CurImgSize[i] * sizeof(U8);
     197                    ENQUEUEBUF(clEnqueueWriteBuffer, kdd.inNxt[i]);
     198                }
     199            } else {
     200                OCLCHECK(clSetKernelArg, kernel, 14, sizeof(U32), &params->reset);
     201            }
     202        }
     203        enc->frameNumber++;
     204    }
     205    OCLCHECK(clEnqueueNDRangeKernel, cmdQ, kernel, 1, NULL, global_work_size_1d, local_work_size_1d, 0, NULL, NULL);
     206
     207    //
     208    // Wait for the hw accelerator to complete
     209    //
     210    clFinish(cmdQ);
     211    //av_log(NULL, AV_LOG_INFO," * Finished the xlnx hw accelerator kernel\n");
     212
     213    //
     214    // Read the result
     215    // Get the length of the Encoded Frame first as this varies!
     216    //
     217    // av_log(NULL, AV_LOG_INFO," * Enqueuing Read Buffer - CSR14_BITSTREAM_LEN_V\n");
     218    OCLCHECK(clEnqueueReadBuffer, cmdQ, kdd.CSR14_BITSTREAM_LEN_V, CL_TRUE, 0, kdd.EncodedFrameLengthSize * sizeof(U64), &oBuf->size, 0, NULL, NULL);
     219    // av_log(NULL, AV_LOG_INFO," * Encoded Frame Length = %d\n", *dstSize);
     220    //*dstSize = *dstSize * 4;
     221    printf(" * Encoded Frame Length = %llu enc->frameNumber=%u\n", oBuf->size, enc->frameNumber);
     222
     223    // av_log(NULL, AV_LOG_INFO," * Enqueuing Read Buffer - CSR13_BITSTREAM_BASE_V\n");
     224    OCLCHECK(clEnqueueReadBuffer, cmdQ, kdd.CSR13_BITSTREAM_BASE_V, CL_TRUE, 0, oBuf->size * sizeof(U8), oBuf->pDATA, 0, NULL, NULL);
     225    return 0;
     226}
     227
     228xlnx_host* createHevcEnc(xlnx_kernel* aKernel, xlnx_hw_params aParams) {
     229    HevcEnc* enc;
     230    xlnx_host* host;
     231    int err;
     232    if (aKernel == NULL) return NULL;
     233    enc = (HevcEnc*)calloc(1, sizeof(HevcEnc));
     234    if (enc == NULL) {
     235        printf("Error: Cannot allocate memory %s at %d\n", __FILE__, __LINE__);
     236        return NULL;
     237    }
     238    memcpy(&enc->params, aParams, sizeof(HevcEncParam));
     239    enc->xKernel = aKernel;
     240    err = KDD_init(&enc->kdd, enc);
     241    if (err < 0) {
     242        printf("Error: createHevcEnc Failed\n");
     243        free(enc);
     244        return NULL;
     245    }
     246    enc->frameNumber = 0;
     247    host = (xlnx_host*) calloc(1, sizeof(xlnx_host));
     248    if (host == NULL) {
     249        printf("Error: Cannot allocate memory %s at %d\n", __FILE__, __LINE__);
     250        return NULL;
     251    }
     252    host->privData = (void*) enc;
     253    host->process = &hevc_encode;
     254    return host;
     255}
     256
     257int destroyHevcEnc(xlnx_host* aHost) {
     258    HevcEnc* enc;
     259    if (aHost == NULL) return -1;
     260    enc = (HevcEnc*)aHost->privData;
     261    if (enc == NULL) return -1;
     262    KDD_deinit(&enc->kdd);
     263    free(enc);
     264    free(aHost);
     265    return 0;
     266}
  • new file libavcodec/xlnx_hw/hevc/enc_vu9p.h

    diff --git a/libavcodec/xlnx_hw/hevc/enc_vu9p.h b/libavcodec/xlnx_hw/hevc/enc_vu9p.h
    new file mode 100644
    index 0000000..4423f53
    - +  
     1#ifndef HEVC_ENC_VU9P_H
     2#define HEVC_ENC_VU9P_H
     3
     4#include "../common/inc/xlnx_types_internal.h"
     5
     6xlnx_host* createHevcEnc(xlnx_kernel* aKernel, xlnx_hw_params aParams);
     7int destroyHevcEnc(xlnx_host* aHost);
     8
     9#endif //HEVC_ENC_VU9P_H
     10 No newline at end of file
  • new file libavcodec/xlnx_hw/hevc/enc_vu9p_2c.c

    diff --git a/libavcodec/xlnx_hw/hevc/enc_vu9p_2c.c b/libavcodec/xlnx_hw/hevc/enc_vu9p_2c.c
    new file mode 100644
    index 0000000..e441aec
    - +  
     1#include <stdio.h>
     2#include <stdlib.h>
     3#include <unistd.h>
     4#include <limits.h>
     5#include <string.h>
     6#include <assert.h>
     7#include <CL/opencl.h>
     8#include "pthread.h"
     9
     10//@TODO implement own msg queue and remove libavutil dependency
     11#include "libavutil/atomic.h"
     12#include "libavutil/threadmessage.h"
     13#include "libavutil/error.h"
     14
     15#include "../common/inc/xlnx_hw_defines.h"
     16#include "../common/inc/xlnx_ts_queue.h"
     17#include "enc_vu9p_2c.h"
     18
     19#define OCLCHECKI(method, ... )                                                \
     20do {                                                                           \
     21    status = method(__VA_ARGS__);                                              \
     22    if (status != CL_SUCCESS) {                                                \
     23        printf( # method " error '%d'\n", status);                             \
     24        return -1;                                                             \
     25    }                                                                          \
     26} while (0)
     27
     28#define OCLCHECKI2(method, ... )                                               \
     29do {                                                                           \
     30    status = method(__VA_ARGS__);                                              \
     31    if (status != CL_SUCCESS) {                                                \
     32        printf( # method " error '%d'\n", status);                             \
     33        KDD2_deinit(kdd, ch, refcount);                                        \
     34        return -1;                                                             \
     35    }                                                                          \
     36} while (0)
     37
     38#define CREATEBUF2(out, flags, size)                                               \
     39do {                                                                               \
     40    out = clCreateBuffer(*context, flags, size, &ext, &status);                    \
     41    if (status != CL_SUCCESS) {                                                    \
     42        printf("Could not create OpenCL buffer\n");                                \
     43        KDD2_deinit(aKDD, ch, aRefcount);                                          \
     44        return -1;                                                                 \
     45    }                                                                              \
     46    OCLCHECKI2(clEnqueueMigrateMemObjects, cmdQ, 1, &out, migflags, 0, NULL, NULL);\
     47} while (0)
     48
     49#define OCLCHECKCB(method, ... )                                               \
     50do {                                                                           \
     51    status = method(__VA_ARGS__);                                              \
     52    if (status != CL_SUCCESS) {                                                \
     53        printf( # method " error '%d'\n", status);                             \
     54        break;                                                                 \
     55    }                                                                          \
     56} while (0)
     57
     58#define WAIT_IF_EMPTY(Q) while (isEmptyTSQ(Q)) usleep(1000)
     59
     60
     61typedef struct HevcEnc2 HevcEnc2;
     62
     63typedef enum HevcEncState {
     64    EInit,
     65    ESendIp,
     66    EEncode,
     67    EReadOpSize,
     68    ECopyOp
     69} HevcEncState;
     70
     71typedef struct HevcKDCtx {
     72    cl_mem* inD;
     73    cl_mem* outD;
     74    xlnx_hw_buf* outH;
     75    void* appCtx;
     76} HevcKDCtx;
     77
     78typedef struct HevcEncCtx {
     79    HevcEnc2* enc;
     80    HevcKDCtx kdCtx[VU9P_HEVC_ENC_NUM_CH];
     81    HevcEncState state;
     82    cl_event lEncode;
     83} HevcEncCtx;
     84
     85typedef struct HevcEncParam2 {
     86    U32 wh[2];
     87    U32 br;
     88    U32 qp;
     89    U32 ip;
     90    U32 reset;
     91} HevcEncParam2;
     92
     93typedef struct KernelDeviceData2 {
     94    // CSR3/CSR4/CSR5
     95    // CSR6/CSR7/CSR8
     96    cl_mem  InCur[VU9P_HEVC_ENC_NUM_CH][3];
     97    // CSR9/CSR10/CSR11
     98    cl_mem  inNxt[3];
     99    xlnx_ts_queue* inQ[VU9P_HEVC_ENC_NUM_CH];
     100    cl_mem  CSR15_RECON_BASE_V;
     101    // CSR 16 & 18 + CSR 17 & 19
     102    xlnx_ts_queue* outQ[VU9P_HEVC_ENC_NUM_CH];
     103    U32 CurImgSize[VU9P_HEVC_ENC_NUM_CH][3];
     104    U32 EncodedFrameSize[VU9P_HEVC_ENC_NUM_CH];
     105    //CSR20
     106    U32 isDualCh;
     107    HevcEncParam2* params;
     108} KernelDeviceData2;
     109
     110typedef KernelDeviceData2 KDD2;
     111
     112struct HevcEnc2 {
     113    KDD2 kdd;
     114    HevcEncParam2 params;
     115    xlnx_kernel* xKernel;
     116    U32 frameNumber[VU9P_HEVC_ENC_NUM_CH];
     117    int refCount;
     118    pthread_t encThread;
     119    AVThreadMessageQueue* reqQ[VU9P_HEVC_ENC_NUM_CH];
     120    AVThreadMessageQueue* rspQ[VU9P_HEVC_ENC_NUM_CH];
     121    xlnx_ts_queue* ctxQ;
     122    HevcEncCtx* curCtx;
     123};
     124
     125typedef enum {
     126    EProcess,
     127    EEOS
     128} HevcMsgType;
     129
     130typedef struct HevcEncReq {
     131    HevcMsgType type;
     132    xlnx_host* host;
     133    xlnx_hw_params params;
     134    xlnx_hw_buf* in;
     135    xlnx_hw_buf* out;
     136    void* appCtx;
     137} HevcEncReq;
     138
     139typedef struct HevcEncRsp {
     140    HevcMsgType type;
     141    xlnx_hw_buf* out;
     142    void* appCtx;
     143} HevcEncRsp;
     144
     145static int KDD2_deinit(KDD2* aKDD, uint32_t aChannel,  int aRefcount);
     146
     147static int hevc_prepare(HevcEnc2* aEnc, HevcEncReq* aReq) {
     148    cl_int status = -1;
     149    int ch;
     150    HevcEnc2* enc = aEnc;
     151    KDD2* kdd = &enc->kdd;
     152    int refcount = enc->refCount;
     153    xlnx_kernel* xKernel = enc->xKernel;
     154    cl_command_queue cmdQ;
     155    cl_kernel kernel;
     156    int size;
     157    xlnx_data_buf* iHBuf;
     158    xlnx_host* host = aReq->host;
     159    xlnx_hw_buf* inHost = aReq->in;
     160    HevcEncCtx* ctx;
     161    HevcKDCtx* kdCtx;
     162    int arg;
     163    U32 frameNumber;
     164    cl_mem* inFBuf = NULL;
     165
     166    iHBuf = inHost->ptr;
     167    ch = host->ch;
     168    frameNumber = enc->frameNumber[ch];
     169    if ((frameNumber == 0) && (iHBuf == NULL)) { return -1;}
     170    assert(inHost->type == ERAW);
     171
     172    cmdQ = xKernel->cmdQ;
     173    kernel = xKernel->kernel;
     174
     175    size = 0;
     176    if (ch == 0) {
     177        if (frameNumber == 0) {
     178            arg = 2;
     179            inFBuf = (cl_mem*)dequeueTSQ(kdd->inQ[ch]);
     180            for (int i = 0; i < 3; i++) {
     181                size = kdd->CurImgSize[ch][i] * sizeof(U8);
     182                ENQUEUEBUF(clEnqueueWriteBuffer, inFBuf[i]);
     183                OCLCHECKI2(clSetKernelArg, kernel, arg, sizeof(cl_mem),&inFBuf[i]);
     184                arg++;
     185            }
     186            enc->frameNumber[ch]++;
     187            ctx = enc->curCtx = dequeueTSQ(enc->ctxQ);
     188            ctx->state = ESendIp;
     189            kdCtx = &ctx->kdCtx[ch];
     190            kdCtx->inD = inFBuf;
     191            kdCtx->outH = aReq->out;
     192            kdCtx->appCtx = aReq->appCtx;
     193            return 0;
     194        } else if (frameNumber == 1) {
     195            if (iHBuf != NULL) {
     196                inFBuf = (cl_mem*)dequeueTSQ(kdd->inQ[ch]);
     197                arg = 8;
     198                for (int i = 0; i < 3; i++) {
     199                    size = kdd->CurImgSize[ch][i] * sizeof(U8);
     200                    ENQUEUEBUF(clEnqueueWriteBuffer, inFBuf[i]);
     201                    OCLCHECKI2(clSetKernelArg, kernel, arg, sizeof(cl_mem), &inFBuf[i]);
     202                    arg++;
     203                }
     204            }
     205            enc->frameNumber[ch]++;
     206            ctx = frontTSQ(enc->ctxQ);
     207            kdCtx = &ctx->kdCtx[ch];
     208            kdCtx->inD = inFBuf;
     209            kdCtx->outH = aReq->out;
     210            kdCtx->appCtx = aReq->appCtx;
     211        } else {
     212            WAIT_IF_EMPTY(enc->ctxQ);
     213            ctx = enc->curCtx = dequeueTSQ(enc->ctxQ);
     214            ctx->state = ESendIp;
     215            kdCtx = &ctx->kdCtx[ch];
     216            inFBuf = kdCtx->inD;
     217            arg = 2;
     218            for (int i = 0; i < 3; i++) {
     219                OCLCHECKI2(clSetKernelArg, kernel, arg, sizeof(cl_mem),&inFBuf[i]);
     220                arg++;
     221            }
     222            if (iHBuf != NULL) {
     223                WAIT_IF_EMPTY(kdd->inQ[ch]);
     224                inFBuf = (cl_mem*)dequeueTSQ(kdd->inQ[ch]);
     225                arg = 8;
     226                for (int i = 0; i < 3; i++) {
     227                    size = kdd->CurImgSize[ch][i] * sizeof(U8);
     228                    ENQUEUEBUF(clEnqueueWriteBuffer, inFBuf[i]);
     229                    OCLCHECKI2(clSetKernelArg, kernel, arg, sizeof(cl_mem), &inFBuf[i]);
     230                    arg++;
     231                }
     232            }
     233            enc->frameNumber[ch]++;
     234            WAIT_IF_EMPTY(enc->ctxQ);
     235            ctx = frontTSQ(enc->ctxQ);
     236            kdCtx = &ctx->kdCtx[ch];
     237            kdCtx->inD = inFBuf;
     238            kdCtx->outH = aReq->out;
     239            kdCtx->appCtx = aReq->appCtx;
     240        }
     241    } else if (ch == 1) {
     242        if (iHBuf != NULL) {
     243            ctx = enc->curCtx;
     244            assert(ctx->state == ESendIp);
     245            kdCtx = &ctx->kdCtx[ch];
     246            WAIT_IF_EMPTY(kdd->inQ[ch]);
     247            inFBuf = (cl_mem*)dequeueTSQ(kdd->inQ[ch]);
     248            arg = 5;
     249            for (int i = 0; i < 3; i++) {
     250                size = kdd->CurImgSize[ch][i] * sizeof(U8);
     251                ENQUEUEBUF(clEnqueueWriteBuffer, inFBuf[i]);
     252                OCLCHECKI2(clSetKernelArg, kernel, arg, sizeof(cl_mem), &inFBuf[i]);
     253                arg++;
     254            }
     255            kdCtx = &ctx->kdCtx[ch];
     256            kdCtx->inD = inFBuf;
     257            kdCtx->outH = aReq->out;
     258            kdCtx->appCtx = aReq->appCtx;
     259        } else {
     260            U32 wh = 0;
     261            OCLCHECKI2(clSetKernelArg, kernel, 1, sizeof(U32),          &wh);
     262            OCLCHECKI2(clSetKernelArg, kernel, 5, sizeof(cl_mem),       NULL);
     263            OCLCHECKI2(clSetKernelArg, kernel, 6, sizeof(cl_mem),       NULL);
     264            OCLCHECKI2(clSetKernelArg, kernel, 7, sizeof(cl_mem),       NULL);
     265            OCLCHECKI2(clSetKernelArg, kernel, 17, sizeof(cl_mem),      NULL);
     266            OCLCHECKI2(clSetKernelArg, kernel, 18, sizeof(cl_mem),      NULL);
     267        }
     268        enc->frameNumber[ch]++;
     269    }
     270    return 0;
     271}
     272
     273static void CL_CALLBACK notify_callback(cl_event event, cl_int event_command_exec_status, void* user_data) {
     274    cl_int status = -1;
     275    HevcEncCtx* ctx;
     276    HevcKDCtx* kdCtx;
     277    HevcEnc2* enc;
     278    KDD2* kdd;
     279    int isDualCh;
     280    cl_command_queue cmdQ;
     281    cl_event eventRead;
     282    xlnx_hw_buf* outH;
     283    xlnx_data_buf* oHBuf;
     284    cl_mem* oFBuf;
     285    HevcEncRsp rspMsg;
     286
     287    ctx = (HevcEncCtx*)user_data;
     288    kdCtx = &ctx->kdCtx[0];
     289    outH = kdCtx->outH;
     290    oHBuf = outH->ptr;
     291    oFBuf = kdCtx->outD;
     292    enc = ctx->enc;
     293    cmdQ = enc->xKernel->cmdQ;
     294    kdd = &enc->kdd;
     295    isDualCh = kdd->isDualCh;
     296
     297    switch (ctx->state) {
     298        case EEncode:
     299            oHBuf->size = 0;
     300            OCLCHECKCB(clEnqueueReadBuffer, cmdQ, oFBuf[1], CL_FALSE, 0, sizeof(U64), &oHBuf->size, 0, NULL, &eventRead);
     301            enqueueTSQ(kdd->inQ[0], kdCtx->inD);
     302            kdCtx->inD = NULL;
     303            ctx->state = EReadOpSize;
     304            if (isDualCh) {
     305                kdCtx = &ctx->kdCtx[1];
     306                oFBuf = kdCtx->outD;
     307                outH = kdCtx->outH;
     308                oHBuf = outH->ptr;
     309                OCLCHECKCB(clEnqueueReadBuffer, cmdQ, oFBuf[1], CL_FALSE, 0, sizeof(U64), &oHBuf->size, 1, &eventRead, &ctx->lEncode);
     310                enqueueTSQ(kdd->inQ[1], kdCtx->inD);
     311                kdCtx->inD = NULL;
     312                OCLCHECKCB(clSetEventCallback, ctx->lEncode, CL_COMPLETE, &notify_callback, ctx);
     313            } else {
     314                OCLCHECKCB(clSetEventCallback, eventRead, CL_COMPLETE, &notify_callback, ctx);
     315            }
     316            break;
     317        case EReadOpSize:
     318            OCLCHECKCB(clEnqueueReadBuffer, cmdQ, oFBuf[0], CL_FALSE, 0, oHBuf->size * sizeof(U8), oHBuf->pDATA, 0, NULL, &eventRead);
     319            ctx->state = ECopyOp;
     320            if (isDualCh) {
     321                kdCtx = &ctx->kdCtx[1];
     322                oFBuf = kdCtx->outD;
     323                outH = kdCtx->outH;
     324                oHBuf = outH->ptr;
     325                OCLCHECKCB(clEnqueueReadBuffer, cmdQ, oFBuf[0], CL_FALSE, 0, oHBuf->size * sizeof(U8), oHBuf->pDATA, 1, &eventRead, &ctx->lEncode);
     326                OCLCHECKCB(clSetEventCallback, ctx->lEncode, CL_COMPLETE, &notify_callback, ctx);
     327            } else {
     328                OCLCHECKCB(clSetEventCallback, eventRead, CL_COMPLETE, &notify_callback, ctx);
     329            }
     330            break;
     331        case ECopyOp:
     332            rspMsg.type = EProcess;
     333            rspMsg.out = kdCtx->outH;
     334            rspMsg.appCtx = kdCtx->appCtx;
     335            av_thread_message_queue_send(enc->rspQ[0], &rspMsg, 0);
     336            kdd = &enc->kdd;
     337            enqueueTSQ(kdd->outQ[0], oFBuf);
     338            kdCtx->outD = NULL;
     339            kdCtx->outH = NULL;
     340            if (isDualCh) {
     341                kdCtx = &ctx->kdCtx[1];
     342                rspMsg.out = kdCtx->outH;
     343                rspMsg.appCtx = kdCtx->appCtx;
     344                oFBuf = kdCtx->outD;
     345                av_thread_message_queue_send(enc->rspQ[1], &rspMsg, 0);
     346                enqueueTSQ(kdd->outQ[1], oFBuf);
     347                kdCtx->outD = NULL;
     348                kdCtx->outH = NULL;
     349            }
     350            ctx->state = EInit;
     351            enqueueTSQ(enc->ctxQ, ctx);
     352            break;
     353        default:
     354            printf("Error: Unknown STATE!!\n");
     355            break;
     356    }
     357}
     358
     359static int hevc_encode(HevcEnc2* aEnc) {
     360    cl_int status = -1;
     361    HevcEnc2* enc;
     362    HevcEncCtx* ctx;
     363    xlnx_hw_buf* outH0;
     364    xlnx_data_buf* oHBuf0;
     365    //xlnx_data_buf* oHBuf1;
     366    KDD2* kdd;
     367    int isDualCh;
     368    xlnx_kernel* xKernel;
     369    cl_command_queue cmdQ;
     370    cl_kernel kernel;
     371    size_t global_work_size_1d[1];
     372    size_t local_work_size_1d[1];
     373    cl_event event;
     374    HevcKDCtx* kdCtx;
     375    cl_mem* oFBuf;
     376    enc = aEnc;
     377    ctx = enc->curCtx;
     378    assert(ctx != NULL);
     379    kdCtx = &ctx->kdCtx[0];
     380    outH0 = kdCtx->outH;
     381    assert(outH0->type == EDATA);
     382    oHBuf0 = outH0->ptr;
     383    kdd = &enc->kdd;
     384    xKernel = enc->xKernel;
     385    cmdQ = xKernel->cmdQ;
     386    kernel = xKernel->kernel;
     387    isDualCh = kdd->isDualCh;
     388
     389    WAIT_IF_EMPTY(kdd->outQ[0]);
     390    oFBuf = dequeueTSQ(kdd->outQ[0]);
     391    OCLCHECKI(clSetKernelArg, kernel, 15, sizeof(cl_mem), &oFBuf[0]);
     392    OCLCHECKI(clSetKernelArg, kernel, 16, sizeof(cl_mem), &oFBuf[1]);
     393    kdCtx->outD = oFBuf;
     394    if(isDualCh) {
     395        kdCtx = &ctx->kdCtx[1];
     396        WAIT_IF_EMPTY(kdd->outQ[1]);
     397        oFBuf = dequeueTSQ(kdd->outQ[1]);
     398        OCLCHECKI(clSetKernelArg, kernel, 17, sizeof(cl_mem), &oFBuf[0]);
     399        OCLCHECKI(clSetKernelArg, kernel, 18, sizeof(cl_mem), &oFBuf[1]);
     400        kdCtx->outD = oFBuf;
     401    }
     402    global_work_size_1d[0] = 1;
     403    local_work_size_1d[0] = 1;
     404    if (ctx->lEncode != 0) {
     405        OCLCHECK(clEnqueueNDRangeKernel, cmdQ, kernel, 1, NULL, global_work_size_1d, local_work_size_1d, 1, &ctx->lEncode, &event);
     406    } else {
     407        OCLCHECK(clEnqueueNDRangeKernel, cmdQ, kernel, 1, NULL, global_work_size_1d, local_work_size_1d, 0, NULL, &event);
     408    }
     409    ctx->state = EEncode;
     410    OCLCHECK(clSetEventCallback, event, CL_COMPLETE, &notify_callback, ctx);
     411    enc->curCtx = NULL;
     412    WAIT_IF_EMPTY(enc->ctxQ);
     413    ctx = frontTSQ(enc->ctxQ);
     414    ctx->lEncode = event;
     415    if (kdd->params->reset == 1) {
     416        kdd->params->reset = 0;
     417        OCLCHECKI(clSetKernelArg, kernel, 20, sizeof(U32), &kdd->params->reset);
     418    }
     419    return 0;
     420}
     421
     422
     423static void* process(void* aEnc) {
     424    HevcEnc2* enc;
     425    AVThreadMessageQueue* reqQ;
     426    AVThreadMessageQueue* rspQ;
     427    AVThreadMessageQueue* reqQ1;
     428    AVThreadMessageQueue* rspQ1;
     429    HevcEncReq reqMsg;
     430    HevcEncRsp rspMsg;
     431    HevcEncReq reqMsg1;
     432    HevcEncRsp rspMsg1;
     433    int ret, isDualCh;
     434
     435    printf("Thread started\n");
     436    enc = (HevcEnc2*)aEnc;
     437    reqQ = enc->reqQ[0];
     438    rspQ = enc->rspQ[0];
     439    rspMsg.type = EProcess;
     440
     441    reqQ1 = NULL;
     442    rspQ1 = NULL;
     443    rspMsg1.out = NULL;
     444    rspMsg1.appCtx = NULL;
     445    isDualCh = 0;
     446
     447    av_thread_message_queue_recv(reqQ, &reqMsg, 0);
     448    ret = hevc_prepare(enc, &reqMsg);
     449    if (ret < 0) {
     450        printf("Error: Prepare failed, Exit Thread aEnc=%p\n", aEnc);
     451        pthread_exit(NULL);
     452    }
     453    while(1) {
     454        av_thread_message_queue_recv(reqQ, &reqMsg, 0);
     455        ret = hevc_prepare(enc, &reqMsg);
     456        if (ret < 0) break;
     457
     458        isDualCh = enc->kdd.isDualCh;
     459        if (isDualCh) {
     460            reqQ1 = enc->reqQ[1];
     461            rspQ1 = enc->rspQ[1];
     462            av_thread_message_queue_recv(reqQ1, &reqMsg1, 0);
     463            if (reqMsg1.type == EEOS) {
     464                while (!isFullTSQ(enc->ctxQ)) usleep(1000);
     465                break;
     466            }
     467            ret = hevc_prepare(enc, &reqMsg1);
     468            if (ret < 0) break;
     469        }
     470        ret = hevc_encode(aEnc);
     471        if (ret < 0) break;
     472        if (reqMsg.type == EEOS) {
     473            while (!isFullTSQ(enc->ctxQ)) usleep(1000);
     474            break;
     475        }
     476    }
     477    rspMsg.type = EEOS;
     478    av_thread_message_queue_send(rspQ, &rspMsg, 0);
     479    av_thread_message_queue_recv(reqQ, &reqMsg, AV_THREAD_MESSAGE_NONBLOCK);
     480    if (isDualCh) {
     481        av_thread_message_queue_recv(reqQ1, &reqMsg1, 0);
     482        assert(reqMsg1.type == EEOS);
     483        rspMsg1.type = EEOS;
     484        av_thread_message_queue_send(rspQ1, &rspMsg1, 0);
     485    }
     486    printf("Exit Thread aEnc=%p\n", aEnc);
     487    pthread_exit(NULL);
     488}
     489
     490int KDD2_deinit(KDD2* aKDD, uint32_t aChannel,  int aRefcount) {
     491    int ch = aChannel;
     492    cl_mem* mem;
     493    xlnx_ts_queue* inQ = aKDD->inQ[ch];
     494    xlnx_ts_queue* outQ = aKDD->outQ[ch];
     495    if (inQ) {
     496        while(!isEmptyTSQ(inQ)) {
     497            mem = (cl_mem*)dequeueTSQ(inQ);
     498            if (mem) {
     499                for (int i = 0; i < 3; i++) {
     500                    clReleaseMemObject(mem[i]);
     501                }
     502                free(mem);
     503            }
     504        }
     505        destroyTSQ(inQ);
     506        aKDD->inQ[ch] = NULL;
     507    }
     508    if (outQ) {
     509        while(!isEmptyTSQ(outQ)) {
     510            mem = (cl_mem*)dequeueTSQ(outQ);
     511            if (mem) {
     512                for (int i = 0; i < 2; i++) {
     513                    clReleaseMemObject(mem[i]);
     514                }
     515                free(mem);
     516            }
     517        }
     518        destroyTSQ(outQ);
     519        aKDD->outQ[ch] = NULL;
     520    }
     521    for (int i = 0; i < 3; i++) {
     522        if (aKDD->InCur[ch][i]) clReleaseMemObject(aKDD->InCur[ch][i]);
     523        if ((ch == 0) && (aKDD->inNxt[i])) clReleaseMemObject(aKDD->inNxt[i]);
     524        aKDD->CurImgSize[ch][i] = 0;
     525    }
     526    if ((aRefcount == 0) && aKDD->CSR15_RECON_BASE_V) clReleaseMemObject(aKDD->CSR15_RECON_BASE_V);
     527    aKDD->EncodedFrameSize[ch] = 0;
     528    aKDD->isDualCh = 0;
     529    return 0;
     530}
     531
     532static int KDD2_init(KDD2* aKDD, HevcEnc2* aEnc, uint32_t aChannel, int aRefcount) {
     533    cl_int status = -1;
     534    KDD2* kdd = aKDD;
     535    int refcount = aRefcount;
     536    int ch = aChannel;
     537    U32 width, height;
     538    cl_kernel kernel;
     539    cl_context* context;
     540    U32 ddrBank;
     541    cl_mem_ext_ptr_t ext;
     542    cl_mem* mem;
     543    xlnx_ts_queue* inQ;
     544    xlnx_ts_queue* outQ;
     545    cl_command_queue cmdQ;
     546    cl_mem_migration_flags  migflags;
     547
     548    if ((aKDD == NULL) || (aEnc == NULL)) return -1;
     549
     550    aKDD->params = &aEnc->params;
     551    width = aKDD->params->wh[ch] >> 16;
     552    height = aKDD->params->wh[ch] & RESET_UPPER_16;
     553    aKDD->CurImgSize[ch][Y] = width * height;
     554    aKDD->CurImgSize[ch][U] = (width * height) >> 2;
     555    aKDD->CurImgSize[ch][V] = (width * height) >> 2;
     556
     557    // Encoded Frame data size - hard code to allocate host memory as this varies!
     558    aKDD->EncodedFrameSize[ch] = (width * height * 3) >> 1;
     559
     560    // Setup the CSR registers
     561    kernel = aEnc->xKernel->kernel;
     562    context = aEnc->xKernel->context;
     563    ddrBank = aEnc->xKernel->prfBank;
     564    cmdQ = aEnc->xKernel->cmdQ;
     565    ext.obj = NULL;
     566    ext.param = 0;
     567    ext.flags = ddrBank;
     568    migflags = 0;
     569
     570    if (aRefcount == 1) {
     571        CREATEBUF2(aKDD->CSR15_RECON_BASE_V, CL_MEM_READ_WRITE  | CL_MEM_EXT_PTR_XILINX | CL_MEM_HOST_NO_ACCESS,  32*1024*1024 * sizeof(U8));
     572    } else {
     573        aKDD->isDualCh = 1;
     574    }
     575    inQ = createTSQ(HEVC_KRNL_CH_Q_CAPACITY);
     576    outQ = createTSQ(HEVC_KRNL_CH_Q_CAPACITY);
     577    if ((NULL == aKDD->outQ) || (NULL == aKDD->inQ)) {
     578        if (aKDD->inQ) free(aKDD->inQ);
     579        return -1;
     580    }
     581    aKDD->inQ[ch] = inQ;
     582    aKDD->outQ[ch] = outQ;
     583    for (int j = 0; j < HEVC_KRNL_CH_Q_CAPACITY; j++) {
     584        mem = calloc(3, sizeof(cl_mem));
     585        if (NULL == mem) return -1;
     586        CREATEBUF2(mem[Y], CL_MEM_READ_ONLY | CL_MEM_EXT_PTR_XILINX,  aKDD->CurImgSize[ch][Y] * sizeof(U8));
     587        CREATEBUF2(mem[U], CL_MEM_READ_ONLY | CL_MEM_EXT_PTR_XILINX,  aKDD->CurImgSize[ch][U] * sizeof(U8));
     588        CREATEBUF2(mem[V], CL_MEM_READ_ONLY | CL_MEM_EXT_PTR_XILINX,  aKDD->CurImgSize[ch][V] * sizeof(U8));
     589        enqueueTSQ(inQ, mem);
     590        mem = calloc(2, sizeof(cl_mem));
     591        if (NULL == mem) return -1;
     592        CREATEBUF2(mem[0], CL_MEM_WRITE_ONLY  | CL_MEM_EXT_PTR_XILINX, aKDD->EncodedFrameSize[ch] * sizeof(U8));
     593        CREATEBUF2(mem[1], CL_MEM_WRITE_ONLY  | CL_MEM_EXT_PTR_XILINX, sizeof(U64));
     594        enqueueTSQ(outQ, mem);
     595    }
     596
     597    if (ch == 0) {
     598        OCLCHECKI2(clSetKernelArg, kernel, 0, sizeof(U32),          &aKDD->params->wh[0]);
     599        OCLCHECKI2(clSetKernelArg, kernel, 14, sizeof(cl_mem),       &aKDD->CSR15_RECON_BASE_V);
     600        if (aRefcount == 1) {
     601            U32 wh = 0;
     602            OCLCHECKI2(clSetKernelArg, kernel, 1, sizeof(U32),          &wh);
     603            OCLCHECKI2(clSetKernelArg, kernel, 5, sizeof(cl_mem),       NULL);
     604            OCLCHECKI2(clSetKernelArg, kernel, 6, sizeof(cl_mem),       NULL);
     605            OCLCHECKI2(clSetKernelArg, kernel, 7, sizeof(cl_mem),       NULL);
     606            OCLCHECKI2(clSetKernelArg, kernel, 17, sizeof(cl_mem),      NULL);
     607            OCLCHECKI2(clSetKernelArg, kernel, 18, sizeof(cl_mem),      NULL);
     608        }
     609    } else if (ch == 1) {
     610        OCLCHECKI2(clSetKernelArg, kernel, 1, sizeof(U32),          &aKDD->params->wh[1]);
     611    }
     612
     613    OCLCHECKI2(clSetKernelArg, kernel, 11, sizeof(U32),          &aKDD->params->br);
     614    OCLCHECKI2(clSetKernelArg, kernel, 12, sizeof(U32),          &aKDD->params->qp);
     615    OCLCHECKI2(clSetKernelArg, kernel, 13, sizeof(U32),          &aKDD->params->ip);
     616    OCLCHECKI2(clSetKernelArg, kernel, 19, sizeof(U32), &aKDD->isDualCh);
     617    OCLCHECKI2(clSetKernelArg, kernel, 20, sizeof(U32), &aKDD->params->reset);
     618    return 0;
     619}
     620
     621static int hevc_process(xlnx_host* aHost, xlnx_hw_params aParams, xlnx_hw_buf* aInput, xlnx_hw_buf** aOutput, XContext* aContext) {
     622    HevcEncReq reqMsg;
     623    HevcEncRsp rspMsg;
     624    int ret;
     625    HevcEnc2* enc;
     626    int ch = aHost->ch;
     627
     628    reqMsg.host = aHost;
     629    reqMsg.params = aParams;
     630    reqMsg.in = aInput;
     631    reqMsg.out = *aOutput;
     632    reqMsg.appCtx = *aContext;
     633    reqMsg.type = EProcess;
     634    if ((aInput->ptr == NULL) && (aHost->eosRcv == 0)) {
     635        reqMsg.type = EEOS;
     636    }
     637
     638    enc = (HevcEnc2*)aHost->privData;
     639
     640    // Send a request to encode the frame
     641    if (aHost->eosRcv == 0) {
     642        av_thread_message_queue_send(enc->reqQ[ch], &reqMsg, 0);
     643    }
     644
     645    // Check if there is a response to return from a previous invocation
     646    if (aInput->ptr == NULL) {
     647        aHost->eosRcv = 1;
     648        ret = av_thread_message_queue_recv(enc->rspQ[ch], &rspMsg, 0);
     649    } else {
     650        ret = av_thread_message_queue_recv(enc->rspQ[ch], &rspMsg, AV_THREAD_MESSAGE_NONBLOCK);
     651    }
     652    if (ret == AVERROR(EAGAIN)) {
     653        *aOutput = NULL;
     654        return 0;
     655    }
     656    if (rspMsg.type == EEOS) {
     657        *aOutput = NULL;
     658        return 2;
     659    }
     660    *aOutput = rspMsg.out;
     661    *aContext = rspMsg.appCtx;
     662    return 1;
     663}
     664
     665static int setEnc2CParams(HevcEncParam2* dParames, uint32_t aChannel, HevcEncParam* sParams) {
     666    int ch = aChannel;
     667    dParames->wh[ch] = (sParams->width << 16) + sParams->height;
     668    if (ch == 0) {
     669        dParames->qp = (dParames->qp & RESET_LOWER_16) + sParams->qp;
     670        dParames->ip = (dParames->ip & RESET_LOWER_16) + sParams->ip;
     671        dParames->br = (dParames->br & RESET_LOWER_16) + sParams->bitrate;
     672    } else {
     673        dParames->qp = (dParames->qp & RESET_UPPER_16) + (sParams->qp << 16);
     674        dParames->ip = (dParames->ip & RESET_UPPER_16) + (sParams->ip << 16);
     675        dParames->br = (dParames->br & RESET_UPPER_16) + (sParams->bitrate << 16);
     676    }
     677    dParames->reset = 1;
     678    return 0;
     679}
     680
     681xlnx_host* createHevcEnc2C(xlnx_kernel* aKernel, uint32_t aChannel, xlnx_hw_params aParams) {
     682    HevcEnc2* enc;
     683    int err;
     684    xlnx_host* host;
     685    xlnx_ts_queue* ctxQ;
     686    HevcEncCtx* ctx;
     687
     688    if (aKernel == NULL) return NULL;
     689    assert((aChannel == 0) || ((aChannel == 1) && (aKernel->appData != NULL)));
     690
     691    if (aChannel == 0) {
     692        enc = (HevcEnc2*)calloc(1, sizeof(HevcEnc2));
     693        ctxQ = createTSQ(HEVC_KRNL_CH_Q_CAPACITY);
     694        if ((enc == NULL) || (ctxQ == NULL)) {
     695            if (enc) free(enc);
     696            printf("Error: Cannot allocate memory %s at %d\n", __FILE__, __LINE__);
     697            return NULL;
     698        }
     699        enc->refCount = 0;
     700        for (int i = 0; i < HEVC_KRNL_CH_Q_CAPACITY; i++) {
     701            ctx = calloc(1, sizeof(HevcEncCtx));
     702            if (ctx == NULL) {
     703                free(enc);
     704                while(!isEmptyTSQ(enc->ctxQ)) {
     705                    free(dequeueTSQ(enc->ctxQ));
     706                }
     707                destroyTSQ(ctxQ);
     708                printf("Error: Cannot allocate memory %s at %d\n", __FILE__, __LINE__);
     709                return NULL;
     710            }
     711            ctx->enc = enc;
     712            ctx->state = EInit;
     713            ctx->lEncode = 0;
     714            enqueueTSQ(ctxQ, ctx);
     715        }
     716        enc->ctxQ = ctxQ;
     717    } else if (aChannel == 1) {
     718        enc = (HevcEnc2*)aKernel->appData;
     719    }
     720
     721    setEnc2CParams(&enc->params, aChannel, aParams);
     722    enc->xKernel = aKernel;
     723    enc->refCount++;
     724    err = KDD2_init(&enc->kdd, enc, aChannel, enc->refCount);
     725    if (err < 0) {
     726        printf("Error: createHevcEnc Failed\n");
     727        free(enc);
     728        return NULL;
     729    }
     730    enc->frameNumber[aChannel] = 0;
     731    host = (xlnx_host*) calloc(1, sizeof(xlnx_host));
     732    if (host == NULL) {
     733        printf("Error: Cannot allocate memory %s at %d\n", __FILE__, __LINE__);
     734        return NULL;
     735    }
     736    host->privData = (void*) enc;
     737    host->ch = aChannel;
     738    host->processAsync = &hevc_process;
     739    host->eosRcv = 0;
     740    // Create the message queues
     741    printf("Creating request message queue ch[%d]\n", aChannel);
     742    err = av_thread_message_queue_alloc(&enc->reqQ[aChannel],
     743                                       HEVC_ENC_IN_Q_CAPACITY, sizeof(HevcEncReq));
     744    printf("Creating response message queue ch[%d]\n", aChannel);
     745    err |= av_thread_message_queue_alloc(&enc->rspQ[aChannel],
     746                                       HEVC_ENC_OUT_Q_CAPACITY, sizeof(HevcEncRsp));
     747
     748    if (err < 0)
     749    {
     750        printf("Error: Cannot allocate memory %s at %d\n", __FILE__, __LINE__);
     751        destroyHevcEnc2C(host);
     752        return NULL;
     753    }
     754
     755    if (aChannel == 0) {
     756        printf("create Thread for enc=%p host=%p\n", enc, host);
     757        aKernel->appData = (void*) enc;
     758        if (pthread_create(&enc->encThread, NULL, process, enc) < 0) {
     759            printf("Error: Thread Creation Failed!!\n");
     760            destroyHevcEnc2C(host);
     761            return NULL;
     762        }
     763    }
     764    return host;
     765}
     766
     767int destroyHevcEnc2C(xlnx_host* aHost) {
     768    HevcEnc2* enc;
     769    if (aHost == NULL) return -1;
     770    enc = (HevcEnc2*)aHost->privData;
     771    if (enc == NULL) return -1;
     772    enc->refCount--;
     773    KDD2_deinit(&enc->kdd, aHost->ch, enc->refCount);
     774    if (enc->refCount == 0) {
     775        // @Todo Terminate the thread for sure
     776        pthread_join(enc->encThread, NULL);
     777
     778        // Free the message queues
     779        for (int i = 0; i < VU9P_HEVC_ENC_NUM_CH; i++) {
     780            av_thread_message_queue_free(&enc->reqQ[i]);
     781            av_thread_message_queue_free(&enc->rspQ[i]);
     782        }
     783        if (enc->ctxQ) {
     784            while(!isEmptyTSQ(enc->ctxQ)) {
     785                free(dequeueTSQ(enc->ctxQ));
     786            }
     787            destroyTSQ(enc->ctxQ);
     788        }
     789        free(enc);
     790    }
     791    free(aHost);
     792    return 0;
     793}
  • new file libavcodec/xlnx_hw/hevc/enc_vu9p_2c.h

    diff --git a/libavcodec/xlnx_hw/hevc/enc_vu9p_2c.h b/libavcodec/xlnx_hw/hevc/enc_vu9p_2c.h
    new file mode 100644
    index 0000000..2fabc5c
    - +  
     1#ifndef HEVC_ENC_VU9P_2C_H
     2#define HEVC_ENC_VU9P_2C_H
     3
     4#include "../common/inc/xlnx_types_internal.h"
     5
     6/*
     7Restrictions for dual channel mode:
     8 1. Both the channels must have same framerate
     9 2. Parameters like height/width do not change once encoder is initialized
     10 3. Both the channels need to be setup (createHevcEnc2C), before the second process
     11    request arrives for the first channel(0)
     12*/
     13xlnx_host* createHevcEnc2C(xlnx_kernel* aKernel, uint32_t aChannel, xlnx_hw_params aParams);
     14int destroyHevcEnc2C(xlnx_host* aHost);
     15
     16#endif //HEVC_ENC_VU9P_2C_H
     17 No newline at end of file
  • new file libavcodec/xlnx_hw/hevc/ku115_hevc_enc_config.h

    diff --git a/libavcodec/xlnx_hw/hevc/ku115_hevc_enc_config.h b/libavcodec/xlnx_hw/hevc/ku115_hevc_enc_config.h
    new file mode 100644
    index 0000000..68897ee
    - +  
     1#ifndef KU115_HEVC_ENC_CONFIG
     2#define KU115_HEVC_ENC_CONFIG
     3
     4#if LOAD_BINARY_FROM_HEADER
     5#include "hevc_enc_ku115_bin.h"
     6#else
     7static const char* KU115_HEVC_ENC_BINARY = "sdxl_hevc.xclbin";
     8#endif //LOAD_BINARY_FROM_HEADER
     9// KU115
     10static const char* KU115_BOARD = "xilinx:xil-accel-rd-ku115:4ddr-xpr";
     11static const char* KU115_HEVC_KRNL_NAME[] = {"sdxl_hevc"};
     12
     13#endif //KU115_HEVC_ENC_CONFIG
     14 No newline at end of file
  • new file libavcodec/xlnx_hw/hevc/vu9p_hevc_enc_config.h

    diff --git a/libavcodec/xlnx_hw/hevc/vu9p_hevc_enc_config.h b/libavcodec/xlnx_hw/hevc/vu9p_hevc_enc_config.h
    new file mode 100644
    index 0000000..7ab4e5b
    - +  
     1#ifndef VU9P_HEVC_ENC_CONFIG
     2#define VU9P_HEVC_ENC_CONFIG
     3
     4#include "../common/inc/xlnx_types_internal.h"
     5
     6#if LOAD_BINARY_FROM_HEADER
     7#include "hevc_enc_vu9p_bin.h"
     8#include "hevc_enc_vu9p_2k2c_bin.h"
     9#else
     10static const char* VU9P_HEVC_ENC_BINARY = "hevc_enc_vu9p_2k2c.aws.awsxclbin";
     11#endif //LOAD_BINARY_FROM_HEADER
     12
     13// VU9P
     14static const char* VU9P_BOARD = "xilinx:aws-vu9p-f1:4ddr-xpr-2pr";
     15
     16static KRNL_CONFIG VU9P_HEVC_CONFIG[] = {
     17                                            {"krnl_ngcodec_hevc_f1_0", XCL_MEM_DDR_BANK3},
     18#if 0
     19                                            {"krnl_ngcodec_hevc_1", XCL_MEM_DDR_BANK3}
     20#endif //VU9P_HEVC_ENC_2_K
     21};
     22
     23
     24#endif //VU9P_HEVC_ENC_CONFIG
  • new file libavcodec/xlnx_hw/xlnx_hw.c

    diff --git a/libavcodec/xlnx_hw/xlnx_hw.c b/libavcodec/xlnx_hw/xlnx_hw.c
    new file mode 100644
    index 0000000..712400d
    - +  
     1#include "stdio.h"
     2#include "stddef.h"
     3#include "xlnx_hw.h"
     4#include "common/inc/xlnx_hrm.h"
     5#include "common/inc/xlnx_types_internal.h"
     6
     7int xlnx_hw_init(const char* aConfigFile, xlnx_hw_id aHWID) {
     8    return xlnx_hrm_init(aConfigFile, aHWID);
     9}
     10
     11int xlnx_hw_deinit(void) {
     12    return xlnx_hrm_deinit();
     13}
     14
     15xlnx_hw xlnx_hw_get(xlnx_hw_id aHW, xlnx_hw_params aParams) {
     16    return (xlnx_hw)xlnx_hrm_get_host(aHW, aParams);
     17}
     18
     19int xlnx_hw_process(xlnx_hw aHW, xlnx_hw_params aParams, xlnx_hw_buf* aInput, xlnx_hw_buf* aOutput) {
     20    int err;
     21    xlnx_host* host;
     22    err = -1;
     23    host = (xlnx_host*)aHW;
     24    if (host->process) {
     25        err = host->process(host, aParams, aInput, aOutput);
     26    } else {
     27        printf("Error: Not Implemented");
     28    }
     29    return err;
     30}
     31
     32int xlnx_hw_process_async(xlnx_hw aHW, xlnx_hw_params aParams, xlnx_hw_buf* aInput, xlnx_hw_buf** aOutput, XContext* aContext) {
     33    int err;
     34    xlnx_host* host;
     35    err = -1;
     36    host = (xlnx_host*)aHW;
     37    if (host->processAsync) {
     38        err = host->processAsync(host, aParams, aInput, aOutput, aContext);
     39    } else {
     40        printf("Error: Not Implemented");
     41    }
     42    return err;
     43}
     44
     45int xlnx_hw_release(xlnx_hw aHW) {
     46    return xlnx_hrm_release_host((xlnx_host*) aHW);
     47}
     48
     49
  • new file libavcodec/xlnx_hw/xlnx_hw.h

    diff --git a/libavcodec/xlnx_hw/xlnx_hw.h b/libavcodec/xlnx_hw/xlnx_hw.h
    new file mode 100755
    index 0000000..ea5fc41
    - +  
     1#ifndef XLNX_HW_H
     2#define XLNX_HW_H
     3#include "xlnx_hw_types.h"
     4
     5int xlnx_hw_init(const char* aConfigFile, xlnx_hw_id aHWID);
     6int xlnx_hw_deinit(void);
     7
     8xlnx_hw xlnx_hw_get(xlnx_hw_id aHWID, xlnx_hw_params aParams);
     9int xlnx_hw_process(xlnx_hw aHW, xlnx_hw_params aParams, xlnx_hw_buf* aInput, xlnx_hw_buf* aOutput);
     10//@TODO Async API added for POC. Aync API with callback to be added later
     11int xlnx_hw_process_async(xlnx_hw aHW, xlnx_hw_params aParams, xlnx_hw_buf* aInput, xlnx_hw_buf** aOutput, XContext* aContext);
     12int xlnx_hw_release(xlnx_hw aHW);
     13
     14#endif // XLNX_HW_H
  • new file libavcodec/xlnx_hw/xlnx_hw_types.h

    diff --git a/libavcodec/xlnx_hw/xlnx_hw_types.h b/libavcodec/xlnx_hw/xlnx_hw_types.h
    new file mode 100644
    index 0000000..14da602
    - +  
     1#ifndef XLNX_HW_TYPES_H
     2#define XLNX_HW_TYPES_H
     3
     4//@TODO define informative error codes
     5#define XLNX_MAX_COMPONENTS 3
     6typedef unsigned char       U8;
     7typedef unsigned int       U32;
     8typedef unsigned long long U64;
     9
     10
     11typedef void* xlnx_hw;
     12typedef void* xlnx_hw_params;
     13typedef void* XBUF;
     14typedef void* XDATA;
     15typedef void* XContext;
     16
     17typedef enum {
     18    EDATA,
     19    ERAW
     20} xlnx_buf_type;
     21
     22typedef struct xlnx_hw_buf {
     23    xlnx_buf_type type;
     24    XBUF ptr;
     25    void* user_priv;
     26    void* priv;
     27} xlnx_hw_buf;
     28
     29//EDATA
     30typedef struct xlnx_data {
     31    XDATA pDATA;
     32    U64 offset;
     33    U64 size;
     34} xlnx_data_buf;
     35
     36//ERAW (YUV, RGB etc)
     37typedef struct {
     38    xlnx_data_buf data[XLNX_MAX_COMPONENTS];
     39} xlnx_cmp_buf;
     40
     41typedef enum xlnx_hw_id {
     42    ENone,
     43    EHevcEnc
     44} xlnx_hw_id;
     45
     46typedef struct HevcEncParam {
     47    U32 width;
     48    U32 height;
     49    U32 bitrate;
     50    U32 qp; // quantization parameter
     51    U32 ip; // intra period
     52    U32 reset;
     53} HevcEncParam;
     54
     55#endif //XLNX_HW_TYPES_H
     56 No newline at end of file
  • libavutil/opencl.c

    diff --git a/libavutil/opencl.c b/libavutil/opencl.c
    index af35770..00992b4 100644
    a b static const AVClass openclutils_class = {  
    8888
    8989static OpenclContext opencl_ctx = {&openclutils_class};
    9090
    91 static const cl_device_type device_type[] = {CL_DEVICE_TYPE_GPU, CL_DEVICE_TYPE_CPU};
     91static const cl_device_type device_type[] = {CL_DEVICE_TYPE_GPU, CL_DEVICE_TYPE_CPU, CL_DEVICE_TYPE_ACCELERATOR};
    9292
    9393typedef struct {
    9494    int err_code;