Skip to content

Commit

Permalink
Add dump functions for encoder and decoder
Browse files Browse the repository at this point in the history
Add functions to dump input & output buffer for encoder and decoder.

Tracked-On: OAM-124732
Signed-off-by: Lina Sun <[email protected]>
  • Loading branch information
lsun30 committed Sep 30, 2024
1 parent 740af09 commit bc98683
Show file tree
Hide file tree
Showing 13 changed files with 283 additions and 19 deletions.
2 changes: 2 additions & 0 deletions c2_components/include/mfx_c2_component.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ class MfxC2Component : public C2ComponentInterface,
{
int flags{0};
bool dump_output{false};
bool dump_input{false};
uint32_t dump_frames_count{0};
uint32_t concurrent_instances{0};
bool low_power_mode{false};
};
Expand Down
6 changes: 6 additions & 0 deletions c2_components/include/mfx_c2_decoder_component.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "mfx_frame_pool_allocator.h"
#include "mfx_gralloc_instance.h"
#include "mfx_c2_setters.h"
#include "mfx_c2_utils.h"
#include <cutils/properties.h>

class MfxC2DecoderComponent : public MfxC2Component
Expand Down Expand Up @@ -252,6 +253,11 @@ class MfxC2DecoderComponent : public MfxC2Component
MFXVideoVPP* m_vpp;
bool m_vppConversion = false;

std::unique_ptr<BinaryWriter> m_outputWriter;
std::unique_ptr<BinaryWriter> m_inputWriter;

uint32_t m_dump_count = 0;

/* -----------------------C2Parameters--------------------------- */
std::shared_ptr<C2ComponentNameSetting> m_name;
std::shared_ptr<C2ComponentKindSetting> m_kind;
Expand Down
7 changes: 5 additions & 2 deletions c2_components/include/mfx_c2_encoder_component.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,6 @@ class MfxC2EncoderComponent : public MfxC2Component

std::shared_ptr<C2BlockPool> m_c2Allocator;

std::unique_ptr<BinaryWriter> m_outputWriter;

bool m_bHeaderSent{false};

mfxFrameSurface1 *m_encSrfPool;
Expand All @@ -220,6 +218,11 @@ class MfxC2EncoderComponent : public MfxC2Component
// Input frame info with width or height not 16byte aligned
mfxFrameInfo m_mfxInputInfo;

std::unique_ptr<BinaryWriter> m_outputWriter;
std::unique_ptr<BinaryWriter> m_inputWriter;

uint32_t m_dump_count = 0;

/* -----------------------C2Parameters--------------------------- */
std::mutex m_c2ParameterMutex;
std::shared_ptr<C2ComponentNameSetting> m_name;
Expand Down
145 changes: 145 additions & 0 deletions c2_components/src/mfx_c2_decoder_component.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -757,6 +757,56 @@ c2_status_t MfxC2DecoderComponent::DoStart()
m_waitingQueue.Start();
} while(false);

// Dump input/output for decoder/encoder steps:
// 1. $adb shell
// 2. $vi /vendor/etc/media_codecs_intel_c2_video.xml, config dump options by
// setting lines like below in specific decoder/encoder configure sections.
// "dump-frmaes-count" is for setting yuv frames number to dump for encoder
// input or decoder output.
//
// "<Limit name="dump-input" value="true" />"
// "<Limit name="dump-output" value="true" />"
// "<Limit name="dump-frmaes-count" value="10" />"
//
// 3. $adb reboot
// 4. $adb shell && setenforce 0
// 5. Run encode/decode, dumped files can be found in /data/local/traces. Files are
// named in "decoder/encoder name - year - month - day - hour - minute - second".
// Dumped files will not be automatically deleted/overwritten in next run, will
// need be deleted manually.
// 6. When viewing yuv frames, check surface width & height in logs if needed.

if (m_createConfig.dump_output || m_createConfig.dump_input) {

std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
std::time_t now_c = std::chrono::system_clock::to_time_t(now);
std::ostringstream oss;
std::tm local_tm;
localtime_r(&now_c, &local_tm);

if(m_createConfig.dump_output) {
oss << m_name->m.value << "-" << std::put_time(std::localtime(&now_c), "%Y-%m-%d-%H-%M-%S") << ".yuv";

MFX_DEBUG_TRACE_STREAM("Decoder output dump is started to " <<
MFX_C2_DUMP_DIR << "/" << MFX_C2_DUMP_OUTPUT_SUB_DIR << "/" <<
oss.str());

m_outputWriter = std::make_unique<BinaryWriter>(MFX_C2_DUMP_DIR,
std::vector<std::string>({MFX_C2_DUMP_OUTPUT_SUB_DIR}), oss.str());
}

if(m_createConfig.dump_input) {
oss << m_name->m.value << "-" << std::put_time(std::localtime(&now_c), "%Y-%m-%d-%H-%M-%S") << ".bin";

MFX_DEBUG_TRACE_STREAM("Decoder input dump is started to " <<
MFX_C2_DUMP_DIR << "/" << MFX_C2_DUMP_INPUT_SUB_DIR << "/" <<
oss.str());

m_inputWriter = std::make_unique<BinaryWriter>(MFX_C2_DUMP_DIR,
std::vector<std::string>({MFX_C2_DUMP_INPUT_SUB_DIR}), oss.str());
}
}

m_OperationState = OperationState::RUNNING;

return C2_OK;
Expand Down Expand Up @@ -801,6 +851,9 @@ c2_status_t MfxC2DecoderComponent::DoStop(bool abort)
m_c2Bitstream->GetFrameConstructor()->Close();
}

m_outputWriter.reset();
m_inputWriter.reset();

m_OperationState = OperationState::STOPPED;
return C2_OK;
}
Expand Down Expand Up @@ -2093,6 +2146,11 @@ void MfxC2DecoderComponent::DoWork(std::unique_ptr<C2Work>&& work)
if (!m_bSetHdrStatic) UpdateHdrStaticInfo();

mfxBitstream *bs = m_c2Bitstream->GetFrameConstructor()->GetMfxBitstream().get();

if (m_inputWriter && NULL != bs && bs->DataLength > 0) {
m_inputWriter->Write(bs->Data, bs->DataLength);
}

MfxC2FrameOut frame_out;
do {
// check bitsream is empty
Expand Down Expand Up @@ -2266,6 +2324,47 @@ void MfxC2DecoderComponent::Drain(std::unique_ptr<C2Work>&& work)
}
}

const u_int16_t ytile_width = 16;
const u_int16_t ytile_height = 32;
void one_ytiled_to_linear(const unsigned char *src, char *dst, u_int16_t x, u_int16_t y, u_int16_t width, u_int16_t height, uint32_t offset)
{
// x and y follow linear
u_int32_t count = x + y * width / ytile_width;

for (int j = 0; j < ytile_width * ytile_height; j += ytile_width) {
memcpy(dst + offset + width * ytile_height * y + width * j / ytile_width + x * ytile_width,
src + offset + j + ytile_width * ytile_height * count, ytile_width);
}
}

void* ytiled_to_linear(uint32_t total_size, uint32_t y_size, uint32_t stride, const unsigned char * src)
{
char* dst = (char*)malloc(total_size * 2);
if (NULL == dst) return NULL;

memset(dst, 0, total_size * 2);

u_int16_t height = y_size / stride;

// Y
u_int16_t y_hcount = height / ytile_height + (height % ytile_height != 0);
for (u_int16_t x = 0; x < stride / ytile_width; x ++) {
for (u_int16_t y = 0; y < y_hcount; y ++) {
one_ytiled_to_linear(src, dst, x, y, stride, height, 0);
}
}

// UV
u_int16_t uv_hcount = (height / ytile_height / 2) + (height % (ytile_height * 2) != 0);
for (u_int16_t x = 0; x < stride / ytile_width; x ++) {
for (u_int16_t y = 0; y < uv_hcount; y ++) {
one_ytiled_to_linear(src, dst, x, y, stride, height / 2, y_size);
}
}

return dst;
}

void MfxC2DecoderComponent::WaitWork(MfxC2FrameOut&& frame_out, mfxSyncPoint sync_point)
{
MFX_DEBUG_TRACE_FUNC;
Expand Down Expand Up @@ -2424,6 +2523,52 @@ void MfxC2DecoderComponent::WaitWork(MfxC2FrameOut&& frame_out, mfxSyncPoint syn
}
m_updatingC2Configures.clear();

if (m_createConfig.dump_output && m_dump_count < m_createConfig.dump_frames_count) {
const C2GraphicView& output_view = block->map().get();

const uint8_t* srcY = output_view.data()[C2PlanarLayout::PLANE_Y];
const uint8_t* srcUV = output_view.data()[C2PlanarLayout::PLANE_U];

if(MFX_IOPATTERN_OUT_VIDEO_MEMORY == m_mfxVideoParams.IOPattern) {
const uint32_t align_width = 128;
const uint32_t align_height = 32;

uint32_t surface_width = mfx_surface->Info.Width % align_width == 0? mfx_surface->Info.Width :
(mfx_surface->Info.Width / align_width + 1) * align_width;
uint32_t surface_height = mfx_surface->Info.Height % align_height == 0? mfx_surface->Info.Height :
(mfx_surface->Info.Height / align_height + 1) * align_height;

uint32_t pix_len = (MFX_FOURCC_P010 == mfx_surface->Info.FourCC) ? 2 : 1;

uint32_t total_size = surface_width * pix_len * surface_height * 3 / 2;
uint32_t y_size = surface_width * pix_len * surface_height;
uint32_t stride = surface_width * pix_len;

uint8_t* srcY_linear = (uint8_t*)ytiled_to_linear(total_size, y_size, stride, srcY);

if (NULL != srcY_linear) {
m_outputWriter->Write(srcY_linear, total_size);
free(srcY_linear);

MFX_DEBUG_TRACE_PRINTF("############# dumping #%d decoded buffer in size: %dx%d #################",
m_dump_count, surface_width, surface_height);
m_dump_count ++;
}
} else { // IOPattern is system memory
if (NULL != srcY && NULL != srcUV) {
m_outputWriter->Write(srcY, mfx_surface->Data.PitchLow * m_mfxVideoParams.mfx.FrameInfo.CropH);
m_outputWriter->Write(srcUV, mfx_surface->Data.PitchLow * m_mfxVideoParams.mfx.FrameInfo.CropH / 2);

uint32_t dump_width = (MFX_FOURCC_P010 == mfx_surface->Info.FourCC) ?
mfx_surface->Data.PitchLow / 2 : mfx_surface->Data.PitchLow;

MFX_DEBUG_TRACE_PRINTF("############# dumping #%d decoded buffer in size: %dx%d #################",
m_dump_count, dump_width, m_mfxVideoParams.mfx.FrameInfo.CropH);
m_dump_count ++;
}
}
}

worklet->output.buffers.push_back(out_buffer);
block = nullptr;
}
Expand Down
71 changes: 63 additions & 8 deletions c2_components/src/mfx_c2_encoder_component.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -656,24 +656,55 @@ c2_status_t MfxC2EncoderComponent::DoStart()
m_workingQueue.Start();
m_waitingQueue.Start();

if (m_createConfig.dump_output) {
// Dump input/output for decoder/encoder steps:
// 1. $adb shell
// 2. $vi /vendor/etc/media_codecs_intel_c2_video.xml, config dump options by
// setting lines like below in specific decoder/encoder configure sections.
// "dump-frmaes-count" is for setting yuv frames number to dump for encoder
// input or decoder output.
//
// "<Limit name="dump-input" value="true" />"
// "<Limit name="dump-output" value="true" />"
// "<Limit name="dump-frmaes-count" value="10" />"
//
// 3. $adb reboot
// 4. $adb shell && setenforce 0
// 5. Run encode/decode, dumped files can be found in /data/local/traces. Files are
// named in "decoder/encoder name - year - month - day - hour - minute - second".
// Dumped files will not be automatically deleted/overwritten in next run, will
// need be deleted manually.
// 6. When viewing yuv frames, check surface width & height in logs if needed.

if (m_createConfig.dump_output || m_createConfig.dump_input) {

std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
std::time_t now_c = std::chrono::system_clock::to_time_t(now);
std::ostringstream oss;
std::tm local_tm;
localtime_r(&now_c, &local_tm);

oss << m_name << "-" << std::put_time(std::localtime(&now_c), "%Y%m%d%H%M%S") << ".bin";
if(m_createConfig.dump_output) {
oss << m_name->m.value << "-" << std::put_time(std::localtime(&now_c), "%Y-%m-%d-%H-%M-%S") << ".bin";

MFX_DEBUG_TRACE_STREAM("Encoder output dump is started to " <<
MFX_C2_DUMP_DIR << "/" << MFX_C2_DUMP_OUTPUT_SUB_DIR << "/" <<
oss.str());
MFX_DEBUG_TRACE_STREAM("Encoder output dump is started to " <<
MFX_C2_DUMP_DIR << "/" << MFX_C2_DUMP_OUTPUT_SUB_DIR << "/" <<
oss.str());

m_outputWriter = std::make_unique<BinaryWriter>(MFX_C2_DUMP_DIR,
std::vector<std::string>({MFX_C2_DUMP_OUTPUT_SUB_DIR}), oss.str());
}
m_outputWriter = std::make_unique<BinaryWriter>(MFX_C2_DUMP_DIR,
std::vector<std::string>({MFX_C2_DUMP_OUTPUT_SUB_DIR}), oss.str());
}

if(m_createConfig.dump_input) {
oss << m_name->m.value << "-" << std::put_time(std::localtime(&now_c), "%Y-%m-%d-%H-%M-%S") << ".yuv";

MFX_DEBUG_TRACE_STREAM("Encoder input dump is started to " <<
MFX_C2_DUMP_DIR << "/" << MFX_C2_DUMP_INPUT_SUB_DIR << "/" <<
oss.str());

m_inputWriter = std::make_unique<BinaryWriter>(MFX_C2_DUMP_DIR,
std::vector<std::string>({MFX_C2_DUMP_INPUT_SUB_DIR}), oss.str());
}
}
} while(false);

return C2_OK;
Expand Down Expand Up @@ -706,6 +737,7 @@ c2_status_t MfxC2EncoderComponent::DoStop(bool abort)
FreeEncoder();

m_outputWriter.reset();
m_inputWriter.reset();

return C2_OK;
}
Expand Down Expand Up @@ -1432,6 +1464,29 @@ void MfxC2EncoderComponent::DoWork(std::unique_ptr<C2Work>&& work)
}
}

if (m_inputWriter && m_dump_count < m_createConfig.dump_frames_count
&& MFX_IOPATTERN_IN_SYSTEM_MEMORY == m_mfxVideoParamsConfig.IOPattern
&& (MFX_FOURCC_NV12 == m_mfxVideoParamsState.mfx.FrameInfo.FourCC
|| MFX_FOURCC_P010 == m_mfxVideoParamsState.mfx.FrameInfo.FourCC)) {

mfxFrameSurface1* mfx_surface = mfx_frame_in.GetMfxFrameSurface();
const uint8_t* srcY = mfx_surface->Data.Y;
const uint8_t* srcUV = mfx_surface->Data.UV;

if (NULL != srcY && NULL != srcUV) {
m_inputWriter->Write(srcY, mfx_surface->Data.PitchLow * mfx_surface->Info.CropH);
m_inputWriter->Write(srcUV, mfx_surface->Data.PitchLow * mfx_surface->Info.CropH / 2);

uint32_t dump_width = (MFX_FOURCC_P010 == m_mfxVideoParamsState.mfx.FrameInfo.FourCC) ?
mfx_surface->Data.PitchLow / 2 : mfx_surface->Data.PitchLow;

MFX_DEBUG_TRACE_PRINTF("############# dumping #%d encoder input buffer in size: %dx%d #################",
m_dump_count, dump_width, mfx_surface->Info.CropH);
}

m_dump_count ++;
}

MfxC2BitstreamOut mfx_bitstream;
res = AllocateBitstream(work, &mfx_bitstream);
if(C2_OK != res) break;
Expand Down
1 change: 1 addition & 0 deletions c2_store/seccomp_policy/[email protected]
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ restart_syscall: 1
rt_sigreturn: 1
getrandom: 1
madvise: 1
mkdirat: 1

# crash dump policy additions
sigreturn: 1
Expand Down
1 change: 1 addition & 0 deletions c2_store/seccomp_policy/[email protected]
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ restart_syscall: 1
rt_sigreturn: 1
getrandom: 1
madvise: 1
mkdirat: 1

# crash dump policy additions
clock_gettime: 1
Expand Down
1 change: 1 addition & 0 deletions c2_store/seccomp_policy/[email protected]
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ uname: 1
memfd_create: 1
ftruncate: 1
ftruncate64: 1
mkdirat: 1

# Required by AddressSanitizer
gettid: 1
Expand Down
1 change: 1 addition & 0 deletions c2_store/seccomp_policy/[email protected]_64.policy
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ uname: 1
memfd_create: 1
ftruncate: 1
ftruncate64: 1
mkdirat: 1

# Required by AddressSanitizer
gettid: 1
Expand Down
2 changes: 2 additions & 0 deletions c2_store/src/mfx_c2_store.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,8 @@ c2_status_t MfxC2ComponentStore::readConfigFile()
MfxC2Component::CreateConfig config;
config.flags = flags;
config.dump_output = m_xmlParser.dumpOutputEnabled(name.c_str());
config.dump_input = m_xmlParser.dumpInputEnabled(name.c_str());
config.dump_frames_count = m_xmlParser.getDumpFramesCount(name.c_str());
config.concurrent_instances = m_xmlParser.getConcurrentInstances(name.c_str());
config.low_power_mode = m_xmlParser.getLowPowerMode(name.c_str());

Expand Down
5 changes: 4 additions & 1 deletion c2_utils/include/mfx_c2_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,11 @@
#define MFX_C2_CONFIG_XML_FILE_NAME "media_codecs_intel_c2_video.xml"
#define MFX_C2_CONFIG_XML_FILE_PATH "/vendor/etc"

#define MFX_C2_DUMP_DIR "/data/local/tmp"
#define MFX_C2_DUMP_DIR "/data/local/traces"
#define MFX_C2_DUMP_OUTPUT_SUB_DIR "c2-output"
#define MFX_C2_DUMP_INPUT_SUB_DIR "c2-input"

constexpr uint32_t DEFAULT_DUMP_FRAMES_COUNT = 1;

const c2_nsecs_t MFX_SECOND_NS = 1000000000; // 1e9

Expand Down
Loading

0 comments on commit bc98683

Please sign in to comment.