使用openh264解码通过UDP发送的libvlc广播

问题描述

使用以下代码,我通过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,int size)
{
    spdlog::debug("videoPrerender");
    videoBuffer_.resize(size);
    *pp_pixel_buffer = videoBuffer_.data();
}

void Broadcaster::videoPostrender(
    void* p_video_data,int64_t pts)
{
    spdlog::debug("videoPostrender");

    std::vector<unsigned char> frame;
    frame.resize(size);
    memcpy(frame.data(),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,sizeof(SBufferInfo));
    DECODING_STATE iRet = pSvcDecoder_->DecodeFrameNoDelay(data,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,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

解决方法

VLC日志报告该流是高配置文件。 Open264仅支持基线配置文件。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...