Hardware Video Decoding - artefacts on screen

Post Reply
Isard7777
Posts: 23
Joined: Fri Aug 10, 2018 5:25 pm
languages_spoken: english french
ODROIDs: C2, C4
Has thanked: 1 time
Been thanked: 0
Contact:

Hardware Video Decoding - artefacts on screen

Post by Isard7777 »

Hello,

I've migrate a code, from the C2 to the C4, sending H.264 stream to the amlogic decoder. on the Odroid C2, this code works well and the render was correct. On the C4, I've seen that some artefacts appears on the screen (the stream has a high bitrate > 10M) if the first frame after the decoder initialisation is not a key frame( or I frame).

Artifacts are black and white spots not comparable with a lost of a P frame (not-a-key frame) in a Group of picture during one or two consecutive frame and they appear frequently.

Normally, a decoder must come back in a nominal behavior whenever it decodes a key frame and it seems unlikely that the behavior is not the same if the decoder is fed with a P frame first.

To have a correct behavior of the decoder, it seems mandatory to send an I frame first and never a P frame (we cannot start a stream in the middle and wait the begin of a Group of Picture).

Have you ever seen this behavior?

Here is an example of my decoder interface :

Code: Select all

#include "HardwareDecoderManager.h"
#include <cstring>
#include <iostream>
#include <fcntl.h>
#include <fstream>

#include "Ndi2Hdmi.h"
#include "LogManager.h"
#include "SystemCmd.h"

extern "C" {
#include <cmath>
#include <cstdio>
#include <cerrno>
#include <unistd.h>
#include "HardwareDecoderIOCTL.h"
}

#include <thread>
#include <chrono>

using namespace std;
static codec_para_t mVideoCodecParams;
static bool mFreeRunMode_b;
static bool mIsInitialized_b = false;


// ???
#define EXTERNAL_PTS        (1)
#define SYNC_OUTSIDE        (2)
#define USE_IDR_FRAMERATE   (4)
#define IPONLY_MODE         (8)
#define NO_DEC_REF_BUF      (0x10)
#define NO_ERROR_RECOVERY   (0x20)
#define UNSTABLE_PTS         (0x40)
// ???

#define PLAYBACK_FREQUENCY_HZ		(60)
#define ENABLE_TSYNC_CMD "echo 1 > /sys/class/tsync/enable"
#define DISABLE_TSYNC_CMD "echo 0 > /sys/class/tsync/enable"
#define DISPLAY_AXIS_CMD "echo 0 0 %d %d 0 0 0 0 > /sys/class/display/axis"


void HWDECMGR_DisableTsync(void);

void HWDECMGR_EnableTsync(void);

void HWDECMGR_DisplayAxis(void);

bool HWDECMGR_Initialize(const uint32_t Width_u32, const uint32_t Height_u32, const float FrameRate_f)
{
    auto Ret_i = 0;

    auto RetCode_b = false;
    
    if (!mIsInitialized_b)
    {
        mFreeRunMode_b = FreeRun_b;

        HWDECMGR_DisableTsync();

        mVideoCodecParams.has_video = 1;
        //mVideoCodecParams.vbuf_size = 524288;
        mVideoCodecParams.video_type = VFORMAT_H264;
        mVideoCodecParams.am_sysinfo.format = VIDEO_DEC_FORMAT_H264;
        mVideoCodecParams.am_sysinfo.param = reinterpret_cast<void*>(EXTERNAL_PTS | UNSTABLE_PTS | SYNC_OUTSIDE | IPONLY_MODE);
        mVideoCodecParams.stream_type = STREAM_TYPE_ES_VIDEO;

        mVideoCodecParams.am_sysinfo.rate = static_cast<unsigned int>(round(96000 / (FrameRate_f)));
        mVideoCodecParams.am_sysinfo.height = static_cast<unsigned int>(Height_u32);
        mVideoCodecParams.am_sysinfo.width = static_cast<unsigned int>(Width_u32);

        mVideoCodecParams.has_audio = 0;
        mVideoCodecParams.noblock = 1;
        mVideoCodecParams.video_pid = 0x1023;
        /* must be between 0x0020 and 0x1FFA, as per https://en.wikipedia.org/wiki/MPEG_transport_stream#Packet_identifier_(PID) */
        auto init_capture_start_chrono = chrono::high_resolution_clock::now();
        auto init_capture_time_ms = 0;
        do
        {
            init_capture_time_ms = static_cast<chrono::duration<double, milli>>(chrono::high_resolution_clock::
                now() - init_capture_start_chrono).count();
            Ret_i = codec_init(&mVideoCodecParams);
            if (Ret_i != CODEC_ERROR_NONE)
            {
                printf("ERR -- Failed to init Video CODEC\n");
               this_thread::sleep_for(chrono::milliseconds(HARDWARE_DECODER_RETRY_INIT_MS));
            }
            else
            {
                printf("INFO -- Initialize Hardware Decoder : " + to_string(Width_u32) +"x"+to_string(Height_u32) + "p@" + to_string(FrameRate_f) + "hz\n");
                RetCode_b = true;
                break;
            }
        }
        while (!gShutDownRequired  && init_capture_time_ms < HW_DEC_TIME_OUT_MS);

        codec_set_freerun_mode(&mVideoCodecParams, 1);

        const auto AmvideoHandle_s = open("/dev/amvideo", O_RDWR);
        if (!AmvideoHandle_s)
        {
            RetCode_b = false;

            printf("ERR -- Cannot open video handle\n");
        }
        close(AmvideoHandle_s);

        HWDECMGR_DisableTsync();

        mIsInitialized_b = true;
    }

    return RetCode_b;
}

uint32_t HWDECMGR_Push(uint8_t* pData_u8,
                       unsigned int DataSize_u8)
{
    unsigned int size = 0;

    if (mIsInitialized_b)
    {
        const auto push_start_chrono = chrono::high_resolution_clock::now();
        auto push_time_ms = 0;
        do
        {
            push_time_ms = static_cast<chrono::duration<double, milli>>(chrono::high_resolution_clock::
                now() - push_start_chrono).count();
            const auto Ret_i = codec_write(&mVideoCodecParams, &pData_u8[size], static_cast<int>(DataSize_u8));
            if (Ret_i < 0)
            {
                if (errno != EAGAIN)
                {
                    printf("Write data failed\n");
                    return -1;
                }
            }
            else if (Ret_i == 0)
            {                
                printf("Decoder send retry\n");
                usleep(1000);
            }
            else
            {
                DataSize_u8 -= Ret_i;
                size += Ret_i;
            }
        }
        while (DataSize_u8 > 0 && push_time_ms < HW_DEC_TIME_OUT_MS) ;
    }
    return DataSize_u8;
}

bool HWDECMGR_Shutdown()
{
    
    if (mIsInitialized_b)
    {
        codec_close(&mVideoCodecParams);
        mIsInitialized_b = false;
    }
    return true;
}



void HWDECMGR_DisableTsync(void)
{

    if (DoSystemCmd(DISABLE_TSYNC_CMD) == 0)
    {
        printf("Cannot Disable Tsync\n");
    }
    else
    {
        printf("Disable Tsync\n");	    
    }
}


void HWDECMGR_EnableTsync(void)
{

    if (DoSystemCmd(DISABLE_TSYNC_CMD) == 0)
    {
        printf("Cannot Enable Tsync\n");
    }
    else
    {
        printf("Enable Tsync\n");
    }
}
And a simplied sample of a main code to help you to understand how this interface is used (the H.264 stream is received as compressed individual frame):

Code: Select all

#include <csignal>
bool gShutDownRequired  = false; 
void StopHandler(int Signal_i)
{
    gShutDownRequired = true;
}
void main()
{
        signal(SIGINT, StopHandler);
#ifdef ODROIDC4
	auto first_frame_found = false;
#endif
	auto video_frame = get_video_frame();
	HWDECMGR_Initialize(video_frame.width, video_frame.height, (float)(video_frame.frame_rate_n / video_frame.frame_rate_d));
	while(!gShutDownRequired )
	{
#ifdef ODROIDC4
		if(video_frame.key_frame) //Test this to avoid artifacts!!!
			first_frame_found = true;
		if(first_frame_found) //Test this to avoid artifacts!!!
		{
#endif
			HWDECMGR_Push(video_frame.data, video_frame.data_size);

#ifdef ODROIDC4
		}
#endif
		release_frame(&video_frame);
		video_frame = get_video_frame();
	}
	
	
}

Thanks

crashoverride
Posts: 5429
Joined: Tue Dec 30, 2014 8:42 pm
languages_spoken: english
ODROIDs: C1
Has thanked: 0
Been thanked: 471 times
Contact:

Re: Hardware Video Decoding - artefacts on screen

Post by crashoverride »

Isard7777 wrote:
Wed Sep 29, 2021 5:57 pm
Have you ever seen this behavior?
In the past, I have tested both RTSP (viewtopic.php?p=327761#p327761) and my own custom streaming protocol. Neither exhibited this behavior despite receiving non-key frames at the start of a stream.
These users thanked the author crashoverride for the post:
odroid (Thu Sep 30, 2021 9:34 am)

Post Reply

Return to “Ubuntu”

Who is online

Users browsing this forum: No registered users and 0 guests