Firefly开源社区

打印 上一主题 下一主题

[应用开发] 使用ffmedia库正常运行一段时间后画面概率出现闪烁/花屏

82

积分

0

威望

0

贡献

技术小白

积分
82

使用ffmedia库正常运行一段时间后画面概率出现闪烁/花屏

发表于 2024-10-21 18:41:30      浏览:97 | 回复:1        打印      只看该作者   [复制链接] 楼主
问题描述及复现步骤:
本帖最后由 MaybeNot 于 2024-10-21 18:44 编辑

使用ffmedia对本地mp4视频文件进行mpp解码+rga颜色空间转换和缩放,将获取到的rgb数据通过opencv显示,发现在正常执行一段时间后(从几分钟到半小时不等),概率出现画面异常,如下图所示,且画面出现异常时没有报错信息。


  1. firefly@firefly:~/ymplayer/test/ffmedia/demo$ sudo ./ymtest /home/firefly/material/127.mp4
  2. Firefly FFMedia: v2.3.1
  3. INFO: 16ModuleFileReader: init: Get Video Resolution( 140 x 1080 )
  4. [INFO] (2024-10-21 18:37:00) (ymtest.cpp:401) source_module_output_para.width=140, height=1080
  5. rga_api version 1.3.2_[0] ( build: 2024-08-08 03:16:34 base: )
  6. ==================Pipe===================
  7. ModuleFileReader (H264 140x1080)
  8.    |--->ModuleMppDec (NV12 140x1080)
  9.            |--->ModuleRga (RGB24 384x2960)

  10. INFO: 10MppDecoder: getTimeoutSample: 0x55cbd9e300 frame info changed 1 error 0 discard 0
复制代码












代码大致如下:之所以不用drm显示而是用opencv是为了测试得到的数据画面是否正常,若用drm display的话无法设置384x2960(是16对齐)的宽高。不知道对于宽高差距较大是否有问题,需不需要调节setBufferCount的大小呢?


void callback_external(void* _ctx, shared_ptr<MediaBuffer> buffer)
{
    External_ctx* ctx = static_cast<External_ctx*>(_ctx);
    shared_ptr<ModuleRga> module = ctx->module;

    if (buffer == NULL || buffer->getMediaBufferType() != BUFFER_TYPE_VIDEO)
        return;

    shared_ptr<VideoBuffer> buf = static_pointer_cast<VideoBuffer>(buffer);
    void *data = buf->getActiveData();
    uint32_t size = buf->getActiveSize();
    pthread_mutex_lock(&rgb_data_ctx.mutex);
    while (rgb_data_ctx.count == VBUFFER_SIZE) {

        pthread_cond_wait(&rgb_data_ctx.not_full, &rgb_data_ctx.mutex);
    }
    memcpy(rgb_data_ctx.rgb_buf[(rgb_data_ctx.in % VBUFFER_SIZE)].rgb_frame, (uchar *)data, size);
    rgb_data_ctx.in = (rgb_data_ctx.in + 1) % VBUFFER_SIZE;
    rgb_data_ctx.count++;
    pthread_cond_signal(&rgb_data_ctx.not_empty);
    pthread_mutex_unlock(&rgb_data_ctx.mutex);
}

void process_rgb_frame(void *_ctx)
{


    while (true){
        pthread_mutex_lock(&rgb_data_ctx.mutex);
        if (rgb_data_ctx.count == 0 && rgb_data_ctx.done == 1){
            pthread_mutex_unlock(&rgb_data_ctx.mutex);
            log_info("done, break");
            break;
        }

        while(rgb_data_ctx.count == 0 && rgb_data_ctx.done == 0){
            pthread_cond_wait(&rgb_data_ctx.not_empty, &rgb_data_ctx.mutex);
        }

        void *data = rgb_data_ctx.rgb_buf[rgb_data_ctx.out].rgb_frame;
        if(rgb_data_ctx.count > 0)
            rgb_data_ctx.count--;
        rgb_data_ctx.out = (rgb_data_ctx.out+1) % VBUFFER_SIZE;

        cv::Mat mat(cv::Size(384, 2960), CV_8UC3, data);
        cv::imshow("display window", mat);
        cv::waitKey(1);

        pthread_cond_signal(&rgb_data_ctx.not_full);
        pthread_mutex_unlock(&rgb_data_ctx.mutex);
    }

    for(int i=0; i<VBUFFER_SIZE; i++){
        free(rgb_data_ctx.rgb_buf[i].rgb_frame);
        rgb_data_ctx.rgb_buf[i].rgb_frame = NULL;
        rgb_data_ctx.rgb_buf[i].rgb_ts = 0;
    }
    return;
}


int start_instance(External_ctx* ctx)
{
    int ret;
    DemoConfig* inst_conf = &(ctx->config);


    file_reader->setProductor(NULL);
    file_reader->setBufferCount(20);
    ret = file_reader->init();



    shared_ptr<ModuleMppDec> dec = make_shared<ModuleMppDec>(inst_conf->input_image_para);
    dec->setProductor(file_reader);
    dec->setBufferCount(10);
    ret = dec->init();
    if (ret < 0) {
        ff_error("Dec init failed\n");
        // goto FAILED;
    }



    shared_ptr<ModuleRga> rga = make_shared<ModuleRga>(inst_conf->output_image_para, inst_conf->rotate);
    rga->setProductor(dec);
    rga->setBufferCount(2);
    ret = rga->init();
    if (ret < 0) {
        ff_error("rga init failed\n");
        // goto FAILED;
    }



    ctx->module = rga;
    ctx->rga_buffer = rga->newModuleMediaBuffer();    // 默认为cacheable的buffer
    rga->setOutputDataCallback(ctx, callback_external);

    std::thread frame_processor(process_rgb_frame, ctx);
    frame_processor.detach();

    clock_gettime(CLOCK_MONOTONIC, &ctx->start);
    file_reader->start();
    file_reader->dumpPipe();

    while (true) {
        int played_cnt = 0;
        if(STATUS_EOS == file_reader->getModuleStatus()){   // 获取当前组件工作状态
            log_info("STATUS_EOS, end of stream. cnt = %d", played_cnt++);
            goto STOP;
        }
        usleep(5000);
    }




}












log.zip

646 Bytes, 下载次数: 0, 下载积分: 灯泡 -1 , 经验 -1

回复

使用道具 举报

980

积分

0

威望

0

贡献

技术大神

Rank: 3Rank: 3

积分
980
发表于 2024-10-22 09:26:21        只看该作者  沙发
1.可以更新版本试试
2.drm在init之后可以通过setPlaneRect或setWindowRect控制显示画面大小。
3.回调传递进来的buffer先调用flushDrmBuf,将数据从cache刷下来。
4. 像这种提前申请了videobuffer的,可以用rga模块导出接口交换buf,避免拷贝。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

友情链接 : 爱板网 电子发烧友论坛 云汉电子社区 粤ICP备14022046号-2
快速回复 返回顶部 返回列表