H.264 HP encoder problem

Hello,

I am using H.264 HP encoder for C66x DSP version DEV.100.V.H264HP.E.C66X.01.00.00.00.

For some reason H.264 HP encoder produces wrong H.264 elementary stream that is not playable (we use ffmpeg to play it):

ffplay -f h264 output.264
avplay version 0.8.4-6:0.8.4-0ubuntu0.12.10.1, Copyright (c) 2003-2012 the Libav developers
  built on Nov  6 2012 16:51:11 with gcc 4.7.2
[h264 @ 0x7fee54000e00] non-existing PPS referenced
[h264 @ 0x7fee54000e00] non-existing PPS 0 referenced
[h264 @ 0x7fee54000e00] decode_slice_header error
[h264 @ 0x7fee54000e00] no frame!
[h264 @ 0x7fee54000e00] sps_id out of range
[h264 @ 0x7fee54000e00] non-existing PPS referenced
[h264 @ 0x7fee54000e00] sps_id out of range
[h264 @ 0x7fee54000e00] non-existing PPS 0 referenced
[h264 @ 0x7fee54000e00] decode_slice_header error
[h264 @ 0x7fee54000e00] no frame!
[h264 @ 0x7fee54000e00] non-existing PPS referenced
[h264 @ 0x7fee54000e00] non-existing PPS 0 referenced
[h264 @ 0x7fee54000e00] decode_slice_header error
[h264 @ 0x7fee54000e00] no frame!

As we see most likely IDR frame is missing.

At the same time demo that goes with H.264 encoder produces correct streams.

I created test that shows how we use H.264 encoder. I did totally the same call order to the encoder API (including all not mandatory calls) in my test as in original demo that goes with the encoder. Input parameters are also the same - you can compare demo_params.txt and test_params.txt files that contains copy of the param and dynamic params of test and original demo.

Some details about test:

- By default test encodes YUV that consists of all zeros - a green image. This is to speed-up testing because reading input YUV files is slow.
- Also you can use "input.yuv" file as an input. Just uncomment "fopen" code in test_task.c
- For simplicity test does not use caching
- For simplicity test does not have a buffer manager. We just never free allocated input/output buffers. So with time it ends with out of memory error.
- For simplicity no IPC. Only one core is used.
- Shared Memory Manager implemented using SYS/BIOS Heap
- Test outputs encoded stream to "output.264" file

Call order:

algNumAlloc
algAlloc
algInit

algActivate
control XDM_GETVERSION
algDeactivate

algActivate
control XDM_GETBUFINFO
algDeactivate

algActivate
RMAN_assignResources
RMAN_activateAllResources
algDeactivate

loop {
  algActivate
  control XDM_SETPARAMS
  algDeactivate
 
  algActivate
  process
 
  algActivate
  control XDM_GETSTATUS
  algDeactivate
}

Results are interesting - frame type changes correctly, starting from IDR frame, but encoder doesn't generate any data:

[C66xx_0] main() on CORE=0
Initialize RMAN
Start SYS/BIOS
test_task
Create encoder
Version: DEV.100.V.H264HP.E.C66X.01.00.00.00
Configure encoder2 buffers
minNumInBufs 3
minNumOutBufs 1
minInBufSize[0] 101376 0
minInBufSize[1] 25344 0
minInBufSize[2] 25344 0
minOutBufSize[0] 3145728 0
Input buffers size (bytes in YUV frame) = 152064
Output buffers size = 3145728
Configure encoder resources
Encoder created and configured
Allocating input and output buffers
Encoding frame
Frame type: -1 Bytes generated 0
Allocating input and output buffers
Encoding frame
Frame type: -1 Bytes generated 0
Allocating input and output buffers
Encoding frame
Frame type: 3 Bytes generated 0
Allocating input and output buffers
Encoding frame
Frame type: 1 Bytes generated 0
Allocating input and output buffers
Encoding frame
Frame type: 2 Bytes generated 0
Allocating input and output buffers
Encoding frame
Frame type: 2 Bytes generated 0
Allocating input and output buffers
Encoding frame
Frame type: 1 Bytes generated 0
Allocating input and output buffers
Encoding frame
Frame type: 2 Bytes generated 0
Allocating input and output buffers
Encoding frame
Frame type: 2 Bytes generated 0
Allocating input and output buffers
Encoding frame
Frame type: 1 Bytes generated 0
Allocating input and output buffers
Encoding frame
Frame type: 2 Bytes generated 0
Allocating input and output buffers
Encoding frame
Frame type: 2 Bytes generated 0
Allocating input and output buffers
Encoding frame
Frame type: 1 Bytes generated 0
Allocating input and output buffers
Encoding frame
Frame type: 2 Bytes generated 0
Allocating input and output buffers
Encoding frame
Frame type: 2 Bytes generated 0
Allocating input and output buffers
Encoding frame
....

Also with little different call order encoder is able to generate bytes so I am attaching generated data for you to compare:

output.264 - generated by test (with little different call order)
airshow_p352x288.264 - generated by original demo

Log of test with changed call order:

...
Encoder created and configured
Allocating input and output buffers
Encoding frame
Frame type: -1 Bytes generated 0
Allocating input and output buffers
Encoding frame
Frame type: -1 Bytes generated 0
Allocating input and output buffers
Encoding frame
Frame type: 3 Bytes generated 0
Allocating input and output buffers
Encoding frame
Frame type: 1 Bytes generated 103
Output 103 bytes from 0 buffer
Allocating input and output buffers
Encoding frame
Frame type: 2 Bytes generated 16
Output 16 bytes from 0 buffer
Allocating input and output buffers
Encoding frame
Frame type: 2 Bytes generated 14
Output 14 bytes from 0 buffer
Allocating input and output buffers
Encoding frame
Frame type: 1 Bytes generated 14
Output 14 bytes from 0 buffer
Allocating input and output buffers
Encoding frame
Frame type: 2 Bytes generated 16
Output 16 bytes from 0 buffer
Allocating input and output buffers
Encoding frame

As you see in this case Bytest generated = 0, when Frame type = 3 (IDR) so most likely IDR frame just missing.

I can not understand where is the problem because H.264 HP encoder is a black box for me and all the "magic" that generates bytes is in it.

Can you clarify the reason of this strange encoder behaviour?

Regards,

Andrey Lisnevich

test_files.zip
  • Hi Andrey,

    We have tried same configuration file you have used in unit test application, with input frames as all 0s. We are not observing any issue everything looks fine.

    It looks like with little different call order you were able to encode stream properly, there were no syntax errors with the file you shared. Can we know what is the change between two trials?

    Also we have used mplayer version "r31743-4.2.5" we were able to play without any error...

  • In reply to Prasad RSV50057:

    Hello,

    Modified call order with which I managed to get bytes is:

    algNumAlloc
    algAlloc
    algInit

    algActivate
    control XDM_GETVERSION
    algDeactivate

    algActivate
    control XDM_GETBUFINFO
    algDeactivate

    algActivate
    RMAN_assignResources
    RMAN_activateAllResources
    algDeactivate

    algActivate

    loop {
      control XDM_SETPARAMS
     
      process
     
      control XDM_GETSTATUS
    }

    In previous message I attached CCS project of my test. I debugged it and I do not see any problem.

    But encoder produces wrong stream (or doesn't produce any). Since I have no source code of encoder I can not debug deeper into encoder and find the reason why is it so.

    Can you help me find the reason by running and debugging my very simple test project?

  • In reply to Andrey Lisnevich:

    Hi Andrey,

    Looks like cache issue are present in the application provided by you. 

    1) By default on power on Cache is enabled. So to disable cache we need to disable with cache APIs.

    2) Assuming that cache is enabled, shared memory sync, allocation APIs are not implemented. Though app is for single core, Codec uses EDMA to update shared buffers, since sync is not implemented, codec will not work.

    Just as a work around to make the app working please call  "Cache_wbInvAll();" in function "shmmap_sync_test" it will work. we are able to see proper output with work around without any syntax errors.

    Rama Mohana Reddy

  • In reply to Prasad RSV50057:

    Thanks Rama,

    You are right - by default L1P and L1D caches are enabled. "Cache_wbInvAll();" in function "shmmap_sync_test" solves the issue.

    Andrey Lisnevich

  • In reply to Prasad RSV50057:

    Hi Rama,

    This workaround works perfectly but only for core0:

    [C66xx_0] main() on CORE=0
    Initialize RMAN
    Start SYS/BIOS
    test_task
    Create encoder
    WARNING: Not supported parent functions
    space=17 pointer=80000180 size=d900
    space=0 pointer=00800000 size=32000
    space=17 pointer=8000da80 size=300000
    space=17 pointer=8030da80 size=a1b80
    space=17 pointer=803af600 size=a1b80
    space=17 pointer=80451180 size=32000
    space=17 pointer=80483180 size=518c
    space=0 pointer=00832000 size=1800
    space=17 pointer=80488380 size=2580
    space=17 pointer=8048a900 size=10000
    space=17 pointer=8049a900 size=5e00
    space=0 pointer=00833800 size=800
    space=0 pointer=00834000 size=300
    space=17 pointer=804a0700 size=1300
    space=17 pointer=804a1a00 size=5000
    space=0 pointer=00834300 size=2000
    space=17 pointer=804a6a00 size=500
    space=17 pointer=804a6f00 size=500
    space=17 pointer=804a7400 size=500
    space=17 pointer=804a7900 size=2a80
    space=17 pointer=804aa380 size=1300
    shmmap 0 15048 2
    shmmap 1 176 2
    shmmap 2 11104 2
    shmmap 3 760 2
    shmmap 4 2921240 0
    shmmap 5 5576 2
    shmmap 6 960 0
    shmmap 7 3145728 0
    Version: DEV.100.V.H264HP.E.C66X.01.00.00.00
    Configure encoder2 buffers
    minNumInBufs 3
    minNumOutBufs 1
    minInBufSize[0] 101376 0
    minInBufSize[1] 25344 0
    minInBufSize[2] 25344 0
    minOutBufSize[0] 3145728 0
    Input buffers size (bytes in YUV frame) = 152064
    Output buffers size = 3145728
    Configure encoder resources
    Encoder created and configured
    Allocating input and output buffers
    Encoding frame
    Frame type: -1 Bytes generated 0
    Allocating input and output buffers
    Encoding frame
    Frame type: -1 Bytes generated 0
    Allocating input and output buffers
    Encoding frame
    Frame type: 3 Bytes generated 111
    Output 111 bytes from 0 buffer
    Allocating input and output buffers
    Encoding frame
    Frame type: 1 Bytes generated 16
    Output 16 bytes from 0 buffer
    Allocating input and output buffers
    Encoding frame
    Frame type: 2 Bytes generated 14
    Output 14 bytes from 0 buffer
    Allocating input and output buffers
    Encoding frame
    Frame type: 2 Bytes generated 14
    Output 14 bytes from 0 buffer
    Allocating input and output buffers
    Encoding frame
    Frame type: 1 Bytes generated 16

    When I run it on other cores result is the same:

    [C66xx_1] main() on CORE=1
    Initialize RMAN
    Start SYS/BIOS
    test_task
    Create encoder
    WARNING: Not supported parent functions
    space=17 pointer=80000180 size=d900
    space=0 pointer=00800000 size=32000
    space=17 pointer=8000da80 size=300000
    space=17 pointer=8030da80 size=a1b80
    space=17 pointer=803af600 size=a1b80
    space=17 pointer=80451180 size=32000
    space=17 pointer=80483180 size=518c
    space=0 pointer=00832000 size=1800
    space=17 pointer=80488380 size=2580
    space=17 pointer=8048a900 size=10000
    space=17 pointer=8049a900 size=5e00
    space=0 pointer=00833800 size=800
    space=0 pointer=00834000 size=300
    space=17 pointer=804a0700 size=1300
    space=17 pointer=804a1a00 size=5000
    space=0 pointer=00834300 size=2000
    space=17 pointer=804a6a00 size=500
    space=17 pointer=804a6f00 size=500
    space=17 pointer=804a7400 size=500
    space=17 pointer=804a7900 size=2a80
    space=17 pointer=804aa380 size=1300
    shmmap 0 15048 2
    shmmap 1 176 2
    shmmap 2 11104 2
    shmmap 3 760 2
    shmmap 4 2921240 0
    shmmap 5 5576 2
    shmmap 6 960 0
    shmmap 7 3145728 0
    Version: DEV.100.V.H264HP.E.C66X.01.00.00.00
    Configure encoder2 buffers
    minNumInBufs 3
    minNumOutBufs 1
    minInBufSize[0] 101376 0
    minInBufSize[1] 25344 0
    minInBufSize[2] 25344 0
    minOutBufSize[0] 3145728 0
    Input buffers size (bytes in YUV frame) = 152064
    Output buffers size = 3145728
    Configure encoder resources
    Encoder created and configured
    Allocating input and output buffers
    Encoding frame
    Frame type: -1 Bytes generated 0
    Allocating input and output buffers
    Encoding frame
    Frame type: -1 Bytes generated 0
    Allocating input and output buffers
    Encoding frame
    Frame type: 3 Bytes generated 0
    Allocating input and output buffers
    Encoding frame
    Frame type: 1 Bytes generated 0
    Allocating input and output buffers
    Encoding frame
    Frame type: 2 Bytes generated 0
    Allocating input and output buffers
    Encoding frame
    Frame type: 2 Bytes generated 0
    Allocating input and output buffers
    Encoding frame
    Frame type: 1 Bytes generated 0
    Allocating input and output buffers
    Encoding frame
    Frame type: 2 Bytes generated 0
    Allocating input and output buffers
    Encoding frame
    Frame type: 2 Bytes generated 0
    Allocating input and output buffers
    Encoding frame
    Frame type: 1 Bytes generated 0
    Allocating input and output buffers
    Encoding frame
    Frame type: 2 Bytes generated 0
    Allocating input and output buffers
    Encoding frame
    Frame type: 2 Bytes generated 0

    As you see frame type is correctly changing as before, but encoder generates 0 bytes. To reproduce the issue just run single instance of the same program on core other then core0.

    Can you please help to resolve the issue?

    Regards,

    Andrey Lisnevich

  • In reply to Andrey Lisnevich:

    Hi Andrey,

    Mutlicore code uses Master,Slave core concept. When CoreID is "zero" codec understands it as master core. So in case of single core we need to assign CoreID in ividmc params as "zero" instead of DNUM value(Only master is present).

    We have tried making CoreID zero while running on Core 1 instead of Core 0, it works fine no issues

    Regards

    Rama

  • In reply to Ramamohana Reddy:

    Hi Rama,

    In ividimc.h, part of HP encoder distribution, you can read opposite information:

     *  @param  core_task_ID : Core Task Name,can be master or slave core
     *
     *  @param  coreID : Core number of the active core,given by DNUM

    And the same according to documentation: core_task_ID is responsible for core's task identification. It can be set to:

    IVIDMC_TASK_MASTER = 0 - The master core task ID.
    IVIDMC_TASK_SLAVE = 1 - Slave Task ID. This is non specific to any particular task.
    IVIDMC_TASK_SLAVE_1 = 2 - Specific slave task ID 1.
    IVIDMC_TASK_SLAVE_2 = 3 - Specific slave task ID 2.

    etc.

    Documentation says that CoreID is just current core identification number. It should not be mandatory to set CoreID = 0 for master core.

    Most likely problem is in H.264 HP encoder implementation.

    Can you please confirm this?

    Andrey Lisnevich

  • In reply to Andrey Lisnevich:

    Hi Andrey,

    The information specified in ividmc.h file is correct. But codec algorithm use "CoreID" parameter to distribute number of rows encoding in multicore scenario. Same will is mapped to in single core also. 

    Codec uses "core_task_ID" as expected, but slice division logic, sync APIs are called based on coreID where it mandates coreID to start from zero.

    Regards

    Rama

  • In reply to Ramamohana Reddy:

    Hi Rama,

    I got your point. With coreID  = 0 transcoding works on all cores.

    But then the description in header file is untrue:

    @param  coreID : Core number of the active core,given by DNUM

    Also documentation never says that coreID should be == 0 for core with master task. I hope you will describe this point more detailed with HP encoder release.

    Thanks!