OpenHarmony 录制时dump视频输入数据的方法
一、简介 当OpenHarmony 应用调用AVRecorder或VideoRecorder ArkTS API进行视频录制时,录制的文件可能出现播放花屏等异常,此时可以尝试dump输入视频数据来排查是数据源的问题还是后续编码的问题 二、版本信息 OpenHarmony-4.X-Release 标准系统,录制引擎为gstreamer引擎 三、修改方法 原生
一、简介
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编码数据,可直接使用电脑端播放器播放。
更多推荐
所有评论(0)