一、简介

OpenHarmony 应用调用AVRecorder或VideoRecorder ArkTS API进行视频录制时,录制的视频文件可能出现播放花屏等异常,此时可以通过尝试dump视频输入数据来排查是数据源的问题还是后续编码的问题

二、版本信息

OpenHarmony-4.X-Release 标准系统,媒体引擎为gstreamer引擎

三、修改方法

原生框架提供了系统属性 sys.media.dump.surfacesrc.enable 可以dump录制时的视频输入数据,但是代码有些BUG,在部分场景下如果输入视频像素格式是RGBA或YUV时可能dump不到数据,可以做如下修改:
foundation/multimedia/player_framework/services/engine/gstreamer/plugins/source/memsource/gst_consumer_surface_pool.cpp 需修改最后3个函数(NEW_MODIFY宏包含的代码是新修改的)

static void gst_consumer_surface_pool_dump_data(FILE *dump_file, const void *addr,
    gint32 size, gint32 width, gint32 height)
{
    ...
    if (width != 0 && height != 0) {
        // The size of non-es streams needs to be adjusted, only dump video data
        gint32 rgbaSize = width * height * 4;   // rgba = w * h * 4
        gint32 yuvSize = width * height * 3 / 2; // yuv = w * h * 3 / 2
#ifdef NEW_MODIFY // 新增修改,rgba surface buffer size可能等于w*h*4
        if (size >= rgbaSize) {
#else
        if (size > rgbaSize) {
#endif
            data_size = rgbaSize;
        } else if (size > yuvSize) {
            data_size = yuvSize;
        }
    }    
    ...
}

static void gst_consumer_surface_pool_dump_surfacebuffer(GstConsumerSurfacePool *pool, sptr<SurfaceBuffer> &buffer)
{
    ...
    gint32 data_size = 0;
    const sptr<OHOS::BufferExtraData>& extraData = buffer->GetExtraData();
    if (extraData != nullptr) {
        (void)extraData->ExtraGet("dataSize", data_size);
    }
#ifdef NEW_MODIFY // surface buffer producer 可能没有设置"dataSize"的ExtraData
    if (data_size <= 0) {
        data_size = buffer->GetSize();
         g_return_if_fail(data_size > 0);
     }
#endif
    gst_consumer_surface_pool_dump_data(pool->priv->dump_file, buffer->GetVirAddr(),
        data_size, buffer->GetWidth(), buffer->GetHeight());
    return;
}

static void gst_consumer_surface_pool_dump_gstbuffer(GstConsumerSurfacePool *pool, GstBuffer *buf)
{
    ...
    GstBufferTypeMeta *meta = gst_buffer_get_buffer_type_meta(buf);
    g_return_if_fail(meta != nullptr);
    GstMapInfo info = GST_MAP_INFO_INIT;
    gst_buffer_map(buf, &info, GST_MAP_READ);
#ifdef NEW_MODIFY // meta->length通过ExtraDat赋值,可能为0
    gint32 data_size = (meta->length > 0) ? static_cast<gint32>(meta->length) : static_cast<gint32>(info.size);
    g_return_if_fail(data_size > 0);
    gst_consumer_surface_pool_dump_data(pool->priv->dump_file, info.data,
        data_size, static_cast<gint32>(meta->width), static_cast<gint32>(meta->height));
#else
    gst_consumer_surface_pool_dump_data(pool->priv->dump_file, info.data,
        static_cast<gint32>(meta->length), static_cast<gint32>(meta->width), static_cast<gint32>(meta->height));
#endif
    gst_buffer_unmap(buf, &info);
    return;
}

四、测试方法

1、上述代码修改后将编译生成的libgst_mem_src.z.so 动态库推到板子的/system/lib(64)/media/plugins/ 目录下,重启
2、板端创建dump文件目录并修改权限: mkdir /data/media;chmod 777 /data/media;
3、设置系统属性: param set sys.media.dump.surfacesrc.enable true
4、此时进行录制操作,录制结束后会在 /data/media/ 目录下生成 surface-inxxx.es_yuv dump文件
5、dump文件的视频数据格式可以是裸数据(YUV、RGBA)或H264编码数据
如果是裸数据,可以使用专业的YUV查看工具查看或者使用ffmpeg命令行工具查看(ffplay -f rawvideo -video_size 宽x高 -pixel_format rgba或nv12 surface-inxxx.es_yuv);
如果是H264编码数据,可直接使用电脑端播放器播放。

Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐