Files
mpp/mpp/mpp_impl.cpp
Ding Wei 60c82d6d7b [mpp]: add dump function for nv12 10bit to 8bit
tips: when dump 10bit yuv, change it to 8bit, and write out.

Change-Id: I710399d61056e32d68c3f6f9d6ff209d73f6b904
Signed-off-by: Ding Wei <leo.ding@rock-chips.com>
2019-08-29 16:10:50 +08:00

447 lines
12 KiB
C++

/*
*
* Copyright 2015 Rockchip Electronics Co. LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define MODULE_TAG "mpp_impl"
#include <time.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include "rk_mpi_cmd.h"
#include "mpp_env.h"
#include "mpp_log.h"
#include "mpp_mem.h"
#include "mpp_time.h"
#include "mpp_thread.h"
#include "mpp_common.h"
#include "mpp_impl.h"
#define MAX_FILE_NAME_LEN 512
#define MAX_DUMP_WIDTH 960
#define MAX_DUMP_HEIGHT 540
#define ops_log(fp, fmt, ...) _ops_log(fp, fmt, ## __VA_ARGS__)
typedef enum MppOpsType_e {
MPP_DEC_OPS_BASE = 0,
MPP_DEC_INIT = MPP_DEC_OPS_BASE,
MPP_DEC_SE
} MppOpsType;
/* dump data */
typedef struct MppDumpImpl_t {
Mutex *lock;
RK_U32 log_version;
RK_U32 debug;
pid_t tid;
RK_S64 time_base;
MppCtxType type;
MppCodingType coding;
FILE *fp_in; // file for MppPacket
FILE *fp_out; // file for MppFrame
FILE *fp_ops; // file for decoder / encoder extra info
RK_U8 *fp_buf; // for resample frame
RK_U32 pkt_offset;
RK_U32 dump_width;
RK_U32 dump_height;
RK_U32 dump_size;
RK_U32 idx;
} MppDumpImpl;
typedef struct MppOpsInfo_t {
RK_U32 idx;
RK_U32 id;
RK_S64 time;
union OpsArgs_u {
struct MppOpsInitArg_t {
MppCtxType type;
MppCodingType coding;
};
struct MppOpsPktArg_t {
RK_U32 offset; // offset in packet file
RK_U32 length; // pakcet length
RK_S64 pts;
};
struct MppOpsFrmArg_t {
RK_U32 fd;
RK_U32 info_change;
RK_U32 error;
RK_U32 discard;
RK_S64 pts;
};
struct MppOpCtrlArg_t {
MpiCmd cmd;
};
};
} MppOpsInfo;
/*
* decoder file dump:
* dec_pkt - decoder input byte raw stream file
* dec_cfg - decoder input stream offset and size info in format [u32 offset|u32 size]
* dec_frm - decoder output frame file with snapshot method
*/
static const char dec_pkt_path[] = "/data/mpp_dec_in.bin";
static const char dec_ops_path[] = "/data/mpp_dec_ops.bin";
static const char dec_frm_path[] = "/data/mpp_dec_out.bin";
static const char enc_frm_path[] = "/data/mpp_enc_in.bin";
static const char enc_ops_path[] = "/data/mpp_enc_ops.bin";
static const char enc_pkt_path[] = "/data/mpp_enc_out.bin";
static FILE *try_env_file(const char *env, const char *path, pid_t tid)
{
const char *fname = NULL;
FILE *fp = NULL;
char name[MAX_FILE_NAME_LEN];
mpp_env_get_str(env, &fname, path);
if (fname == path) {
snprintf(name, sizeof(name), "%s-%d", path, tid);
fname = name;
}
fp = fopen(fname, "w+b");
mpp_log("open %s %p for dump\n", fname, fp);
return fp;
}
static RK_U8 fetch_data(RK_U32 fmt, RK_U8 *line, RK_U32 num)
{
RK_U32 offset = 0;
RK_U32 value = 0;
if (fmt == MPP_FMT_YUV420SP_10BIT) {
offset = (num * 2) & 7;
value = (line[num * 10 / 8] >> offset) |
(line[num * 10 / 8 + 1] << (8 - offset));
value = (value & 0x3ff) >> 2;
} else if (fmt == MPP_FMT_YUV420SP) {
value = line[num];
}
return RK_U8(value);
}
static void dump_frame(FILE *fp, MppFrame frame, RK_U8 *tmp, RK_U32 w, RK_U32 h)
{
RK_U32 i = 0, j = 0;
RK_U32 fmt = mpp_frame_get_fmt(frame);
RK_U32 width = mpp_frame_get_width(frame);
RK_U32 height = mpp_frame_get_height(frame);
RK_U32 hor_stride = mpp_frame_get_hor_stride(frame);
RK_U32 ver_stride = mpp_frame_get_ver_stride(frame);
RK_U8 *p_buf = (RK_U8 *) mpp_buffer_get_ptr(mpp_frame_get_buffer(frame));
RK_U8 *psrc = p_buf;
RK_U8 *pdes = tmp;
if (hor_stride > w || ver_stride > h) {
RK_U32 step = MPP_MAX((hor_stride + w - 1) / w,
(ver_stride + h - 1) / h);
RK_U32 img_w = width / step;
RK_U32 img_h = height / step;
img_w -= img_w & 0x1;
img_h -= img_h & 0x1;
for (i = 0; i < img_h; i++) {
for (j = 0; j < img_w; j++)
pdes[j] = fetch_data(fmt, psrc, j * step);
pdes += img_w;
psrc += step * hor_stride;
}
psrc = p_buf + hor_stride * ver_stride;
pdes = tmp + img_w * img_h;
for (i = 0; i < (img_h / 2); i++) {
for (j = 0; j < (img_w / 2); j++) {
pdes[2 * j + 0] = fetch_data(fmt, psrc, 2 * j * step + 0);
pdes[2 * j + 1] = fetch_data(fmt, psrc, 2 * j * step + 1);
}
pdes += img_w;
psrc += step * hor_stride;
}
width = img_w;
height = img_h;
} else if (fmt == MPP_FMT_YUV420SP_10BIT) {
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++)
pdes[j] = fetch_data(fmt, psrc, j);
pdes += width;
psrc += hor_stride;
}
psrc = p_buf + hor_stride * ver_stride;
pdes = tmp + width * height;
for (i = 0; i < height / 2; i++) {
for (j = 0; j < width; j++)
pdes[j] = fetch_data(fmt, psrc, j);
pdes += width;
psrc += hor_stride;
}
} else {
tmp = p_buf;
width = hor_stride;
height = ver_stride;
}
mpp_log("dump_yuv: [%d:%d] pts %lld\n", width, height, mpp_frame_get_pts(frame));
fwrite(tmp, 1, width * height * 3 / 2, fp);
fflush(fp);
}
void _ops_log(FILE *fp, const char *fmt, ...)
{
struct tm tm_buf;
struct tm* ptm;
struct timespec tp;
char logs[64];
size_t len = 0;
va_list args;
va_start(args, fmt);
clock_gettime(CLOCK_REALTIME_COARSE, &tp);
ptm = localtime_r(&tp.tv_sec, &tm_buf);
len = strftime(logs, sizeof(logs), "%m-%d %H:%M:%S", ptm);
mpp_assert(len < sizeof(logs));
fprintf(fp, "%s.%03ld,", logs, tp.tv_nsec / 1000000);
vfprintf(fp, fmt, args);
fflush(fp);
va_end(args);
}
MPP_RET mpp_dump_init(MppDump *info)
{
if (!(mpp_debug & (MPP_DBG_DUMP_IN | MPP_DBG_DUMP_OUT | MPP_DBG_DUMP_CFG))) {
*info = NULL;
return MPP_OK;
}
MppDumpImpl *p = mpp_calloc(MppDumpImpl, 1);
mpp_env_get_u32("mpp_dump_width", &p->dump_width, MAX_DUMP_WIDTH);
mpp_env_get_u32("mpp_dump_height", &p->dump_height, MAX_DUMP_HEIGHT);
p->dump_size = p->dump_width * p->dump_height * 3 / 2;
p->lock = new Mutex();
p->debug = mpp_debug;
p->tid = syscall(SYS_gettid);
p->log_version = 0;
p->time_base = mpp_time();
*info = p;
return MPP_OK;
}
MPP_RET mpp_dump_deinit(MppDump *info)
{
if (info && *info) {
MppDumpImpl *p = (MppDumpImpl *)*info;
MPP_FCLOSE(p->fp_in);
MPP_FCLOSE(p->fp_out);
MPP_FCLOSE(p->fp_ops);
MPP_FREE(p->fp_buf);
if (p->lock) {
delete p->lock;
p->lock = NULL;
}
}
return MPP_OK;
}
MPP_RET mpp_ops_init(MppDump info, MppCtxType type, MppCodingType coding)
{
if (NULL == info)
return MPP_OK;
MppDumpImpl *p = (MppDumpImpl *)info;
AutoMutex auto_lock(p->lock);
p->type = type;
p->coding = coding;
if (type == MPP_CTX_DEC) {
if (p->debug & MPP_DBG_DUMP_IN)
p->fp_in = try_env_file("mpp_dump_in", dec_pkt_path, p->tid);
if (p->debug & MPP_DBG_DUMP_OUT) {
p->fp_out = try_env_file("mpp_dump_out", dec_frm_path, p->tid);
p->fp_buf = mpp_malloc(RK_U8, p->dump_size);
}
if (p->debug & MPP_DBG_DUMP_CFG)
p->fp_ops = try_env_file("mpp_dump_ops", dec_ops_path, p->tid);
} else {
if (p->debug & MPP_DBG_DUMP_IN) {
p->fp_in = try_env_file("mpp_dump_in", enc_frm_path, p->tid);
p->fp_buf = mpp_malloc(RK_U8, p->dump_size);
}
if (p->debug & MPP_DBG_DUMP_OUT)
p->fp_out = try_env_file("mpp_dump_out", enc_pkt_path, p->tid);
if (p->debug & MPP_DBG_DUMP_CFG)
p->fp_ops = try_env_file("mpp_dump_ops", enc_ops_path, p->tid);
}
if (p->fp_ops)
ops_log(p->fp_ops, "%d,%s,%d,%d\n", p->idx++, "init", type, coding);
return MPP_OK;
}
MPP_RET mpp_ops_dec_put_pkt(MppDump info, MppPacket pkt)
{
MppDumpImpl *p = (MppDumpImpl *)info;
if (NULL == p || NULL == pkt)
return MPP_OK;
RK_U32 length = mpp_packet_get_length(pkt);
AutoMutex auto_lock(p->lock);
if (p->fp_in) {
fwrite(mpp_packet_get_data(pkt), 1, length, p->fp_in);
fflush(p->fp_in);
}
if (p->fp_ops) {
ops_log(p->fp_ops, "%d,%s,%d,%d\n", p->idx++, "pkt", p->pkt_offset, length);
p->pkt_offset += length;
}
return MPP_OK;
}
MPP_RET mpp_ops_dec_get_frm(MppDump info, MppFrame frame)
{
MppDumpImpl *p = (MppDumpImpl *)info;
if (NULL == p || NULL == frame || NULL == p->fp_out || NULL == p->fp_buf)
return MPP_OK;
AutoMutex auto_lock(p->lock);
MppBuffer buf = mpp_frame_get_buffer(frame);
RK_S32 fd = (buf) ? mpp_buffer_get_fd(buf) : (-1);
RK_U32 info_change = mpp_frame_get_info_change(frame);
RK_U32 error = mpp_frame_get_errinfo(frame);
RK_U32 discard = mpp_frame_get_discard(frame);
if (p->fp_ops) {
ops_log(p->fp_ops, "%d,%s,%d,%d,%d,%d,%lld\n", p->idx, "frm", fd,
info_change, error, discard, mpp_frame_get_pts(frame));
}
if (NULL == buf || fd < 0) {
mpp_err("failed to dump frame\n");
return MPP_NOK;
}
dump_frame(p->fp_out, frame, p->fp_buf, p->dump_width, p->dump_height);
if (p->debug & MPP_DBG_DUMP_LOG) {
RK_S64 pts = mpp_frame_get_pts(frame);
RK_U32 width = mpp_frame_get_hor_stride(frame);
RK_U32 height = mpp_frame_get_ver_stride(frame);
mpp_log("yuv_info: [%d:%d] pts %lld", width, height, pts);
}
return MPP_OK;
}
MPP_RET mpp_ops_enc_put_frm(MppDump info, MppFrame frame)
{
MppDumpImpl *p = (MppDumpImpl *)info;
if (NULL == p || NULL == frame || NULL == p->fp_out || NULL == p->fp_buf)
return MPP_OK;
AutoMutex auto_lock(p->lock);
dump_frame(p->fp_out, frame, p->fp_buf, p->dump_width, p->dump_height);
if (p->debug & MPP_DBG_DUMP_LOG) {
RK_S64 pts = mpp_frame_get_pts(frame);
RK_U32 width = mpp_frame_get_hor_stride(frame);
RK_U32 height = mpp_frame_get_ver_stride(frame);
mpp_log("yuv_info: [%d:%d] pts %lld", width, height, pts);
}
return MPP_OK;
}
MPP_RET mpp_ops_enc_get_pkt(MppDump info, MppPacket pkt)
{
MppDumpImpl *p = (MppDumpImpl *)info;
if (NULL == p || NULL == pkt)
return MPP_OK;
RK_U32 length = mpp_packet_get_length(pkt);
AutoMutex auto_lock(p->lock);
if (p->fp_out) {
fwrite(mpp_packet_get_data(pkt), 1, length, p->fp_out);
fflush(p->fp_out);
}
return MPP_OK;
}
MPP_RET mpp_ops_ctrl(MppDump info, MpiCmd cmd)
{
MppDumpImpl *p = (MppDumpImpl *)info;
if (NULL == p)
return MPP_OK;
AutoMutex auto_lock(p->lock);
if (p->fp_ops)
ops_log(p->fp_ops, "%d,%s,%d\n", p->idx, "ctrl", cmd);
return MPP_OK;
}
MPP_RET mpp_ops_reset(MppDump info)
{
MppDumpImpl *p = (MppDumpImpl *)info;
if (NULL == p)
return MPP_OK;
AutoMutex auto_lock(p->lock);
if (p->fp_ops)
ops_log(p->fp_ops, "%d,%s\n", p->idx, "rst");
return MPP_OK;
}