Проблема декодирования с помощью openh264 широковещательной передачи libvlc, отправленной по UDP

С помощью следующего кода я получаю те же данные по UDP, однако DecodeFrameNoDelay возвращает ошибку о наборах параметров последовательности.

Есть ли что-то, чего мне не хватает в конфигурации libvlc или использовании openh264?

Вещательная часть:

// broadcaster.h
class Broadcaster
{
    ...

    std::vector<uint8_t> audioBuffer_;
    std::vector<uint8_t> videoBuffer_;
};

// broadcaster.cpp
void cbVideoPrerender(void* p_video_data, uint8_t** pp_pixel_buffer, int size)
{
    Broadcaster::instance()->videoPrerender(p_video_data, pp_pixel_buffer, size);
}

void cbVideoPostrender(
    void* p_video_data, uint8_t* p_pixel_buffer, int width, int height, int pixel_pitch, int size, int64_t pts)
{
    Broadcaster::instance()->videoPostrender(p_video_data, p_pixel_buffer, width, height, pixel_pitch, size, pts);
}

void Broadcaster::videoPrerender(void* p_video_data, uint8_t** pp_pixel_buffer, int size)
{
    spdlog::debug("videoPrerender");
    videoBuffer_.resize(size);
    *pp_pixel_buffer = videoBuffer_.data();
}

void Broadcaster::videoPostrender(
    void* p_video_data, uint8_t* p_pixel_buffer, int width, int height, int pixel_pitch, int size, int64_t pts)
{
    spdlog::debug("videoPostrender");

    std::vector<unsigned char> frame;
    frame.resize(size);
    memcpy(frame.data(), p_pixel_buffer, size);
    spdlog::debug("size: {}", size);
    // sending data over UDP
}

Broadcaster::Broadcaster()
{
    std::ostringstream stream;
    stream << "#transcode{vcodec=h264,venc=x264{profile=baseline,level=3.0},vb=800,scale=1,acodec=mp3,ab=128,channels=2,samplerate=44100}:smem{";
    stream << "video-prerender-callback=" << (long long int)(intptr_t)(void*)&cbVideoPrerender << ",";
    stream << "video-postrender-callback=" << (long long int)(intptr_t)(void*)&cbVideoPostrender << ",";
    stream << "audio-prerender-callback=" << (long long int)(intptr_t)(void*)&cbAudioPrerender << ",";
    stream << "audio-postrender-callback=" << (long long int)(intptr_t)(void*)&cbAudioPostrender << ",";
    stream << "audio-data=" << (long long int)0 << ",";
    stream << "video-data=" << (long long int)0 << "";
    stream << "},";

    inst_ = libvlc_new(0, NULL);

    std::vector<const char*> params = {
        "sout", "sout-all", "screen-top=0", "screen-left=0", "screen-width=1920", "screen-height=1080", "screen-fps=10"};

    libvlc_vlm_add_broadcast(inst_, "stream", "screen://", stream.str().c_str(), params.size(), params.data(), 1, 0);
}

Часть декодирования (на основе https://github.com/cisco/openh264/wiki/UsageExampleForDecoder):

// streamwindow.h
class StreamWindow
{
    ...

    ISVCDecoder*   pSvcDecoder_;
    unsigned char* pData_[3];
    SDecodingParam sDecParam_ = {0};
};

// streamwindow.cpp
static spdlog::level::level_enum openh264_to_spdlog(int level)
{
    switch (level)
    {
    case WELS_LOG_QUIET:
        return spdlog::level::level_enum::trace;
    case WELS_LOG_ERROR:
        return spdlog::level::level_enum::err;
    case WELS_LOG_WARNING:
        return spdlog::level::level_enum::warn;
    case WELS_LOG_INFO:
        return spdlog::level::level_enum::info;
    case WELS_LOG_DEBUG:
        return spdlog::level::level_enum::debug;
    case WELS_LOG_DETAIL:
        return spdlog::level::level_enum::info;
    default:
        return spdlog::level::level_enum::debug;
    }
}

static void openh264_spdlog(void* context, int level, const char* message)
{
    spdlog::log(openh264_to_spdlog(level), message);
}

StreamWindow::StreamWindow()
{
    WelsCreateDecoder(&pSvcDecoder_);
    sDecParam_.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_SVC;
    pSvcDecoder_->Initialize(&sDecParam_);

    int               log_level = WELS_LOG_DETAIL;
    WelsTraceCallback callback_function;
    callback_function = openh264_spdlog;
    pSvcDecoder_->SetOption(DECODER_OPTION_TRACE_LEVEL, &log_level);
    pSvcDecoder_->SetOption(DECODER_OPTION_TRACE_CALLBACK, (void*)&callback_function);

    ...
}

// called on received udp data
void StreamWindow::decodeStreamData(unsigned char* data, int size)
{
    SBufferInfo sDstBufInfo;
    memset(&sDstBufInfo, 0, sizeof(SBufferInfo));
    DECODING_STATE iRet = pSvcDecoder_->DecodeFrameNoDelay(data, size, pData_, &sDstBufInfo);
    if (iRet != 0)
    {
        spdlog::warn("DecodeFrameNoDelay failed: 0x{0:x}", iRet);
    }

    ...
}

ИЗМЕНИТЬ:

журналы libVLC

[00007f2f440011f0] x264 encoder: using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX
[00007f2f440011f0] x264 encoder: profile Constrained Baseline, level 3.0, 4:2:0, 8-bit
[00007f2f440011f0] x264 encoder: final ratefactor: 38.99
[00007f2f440011f0] x264 encoder: using SAR=1/1
[00007f2f440011f0] x264 encoder: using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX
[00007f2f440011f0] x264 encoder: profile Constrained Baseline, level 3.0, 4:2:0, 8-bit

Журналы decodeStreamData

[2020-09-07 21:52:38.463] [debug] decodeStreamData, size: 47022
[2020-09-07 21:52:38.464] [warning] [OpenH264] this = 0x0x5630b8e202b0, Warning:parse_nal(), no exist Sequence Parameter Sets ahead of sequence when try to decode NAL(type:5).
[2020-09-07 21:52:38.464] [info] [OpenH264] this = 0x0x5630b8e202b0, Info:decode failed, failure type:16 

[2020-09-07 21:52:38.464] [warning] DecodeFrameNoDelay failed: 0x10

person xavi-b    schedule 06.09.2020    source источник
comment
не могли бы вы поделиться полными подробными журналами, пожалуйста?   -  person mfkl    schedule 07.09.2020
comment
Логи добавлены в конце исходного вопроса :)   -  person xavi-b    schedule 07.09.2020
comment
нет, полные логи от начала до конца, пожалуйста   -  person mfkl    schedule 07.09.2020
comment
включая журналы libvlc   -  person mfkl    schedule 07.09.2020
comment
Проект: github.com/xavi-b/stream Журналы: pastebin.com/02ZMvHEp   -  person xavi-b    schedule 07.09.2020
comment
Я обнаружил, что есть обратные вызовы журналов openh264, я добавил их в вопрос (см. часть журналов decodeStreamData)   -  person xavi-b    schedule 07.09.2020


Ответы (1)


Журналы VLC сообщают, что поток имеет высокий профиль. Open264 поддерживает только базовый профиль.

person szatmary    schedule 07.09.2020
comment
Я добавил в параметры трансляции venc=x264{profile=baseline}, и журналы показывают, что он выбран, но у меня все еще есть та же ошибка декодирования. - person xavi-b; 07.09.2020
comment
Я обнаружил, что есть обратные вызовы журналов openh264, я добавил их в вопрос (см. часть журналов decodeStreamData) - person xavi-b; 07.09.2020