Skip to content

Commit

Permalink
dec265: add image dumper
Browse files Browse the repository at this point in the history
Tested: run with a video:

```
./dec265/dec265 -qdD -t 0 tears_400_x265.h265
...
INFO: ----------------- SLICE -----------------
...
INFO: entry point [11] : 2466
INFO: ----------------- IMAGE -----------------
INFO: qp_distro[29:34] { 174 552 397 241 137 62 }
INFO: ----------------- SLICE -----------------
...
INFO: ----------------- IMAGE -----------------
INFO: qp_distro[32:40] { 85 325 297 191 63 15 0 0 5 }
...

```
  • Loading branch information
chemag committed Apr 4, 2019
1 parent c172dd8 commit 8f61dc0
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 2 deletions.
8 changes: 7 additions & 1 deletion dec265/dec265.cc
Expand Up @@ -65,6 +65,7 @@ int quiet=0;
bool check_hash=false;
bool show_help=false;
bool dump_headers=false;
bool dump_image_data_flag=false;
bool write_yuv=false;
bool output_with_videogfx=false;
bool logging=true;
Expand All @@ -91,6 +92,7 @@ static struct option long_options[] = {
{"frames", required_argument, 0, 'f' },
{"output", required_argument, 0, 'o' },
{"dump", no_argument, 0, 'd' },
{"dump-image-data", no_argument, 0, 'I' },
{"nal", no_argument, 0, 'n' },
{"videogfx", no_argument, 0, 'V' },
{"no-logging", no_argument, 0, 'L' },
Expand Down Expand Up @@ -559,7 +561,7 @@ int main(int argc, char** argv)
while (1) {
int option_index = 0;

int c = getopt_long(argc, argv, "qt:chf:o:dLB:n0vT:m:se"
int c = getopt_long(argc, argv, "qt:chf:o:dILB:n0vT:m:se"
#if HAVE_VIDEOGFX && HAVE_SDL
"V"
#endif
Expand All @@ -575,6 +577,7 @@ int main(int argc, char** argv)
case 'o': write_yuv=true; output_filename=optarg; break;
case 'h': show_help=true; break;
case 'd': dump_headers=true; break;
case 'I': dump_image_data_flag=true; break;
case 'n': nal_input=true; break;
case 'V': output_with_videogfx=true; break;
case 'L': logging=false; break;
Expand Down Expand Up @@ -639,6 +642,9 @@ int main(int argc, char** argv)
de265_set_parameter_int(ctx, DE265_DECODER_PARAM_DUMP_PPS_HEADERS, 1);
de265_set_parameter_int(ctx, DE265_DECODER_PARAM_DUMP_SLICE_HEADERS, 1);
}
if (dump_image_data_flag) {
de265_set_parameter_int(ctx, DE265_DECODER_PARAM_DUMP_IMAGE_DATA, 1);
}

if (no_acceleration) {
de265_set_parameter_int(ctx, DE265_DECODER_PARAM_ACCELERATION_CODE, de265_acceleration_SCALAR);
Expand Down
4 changes: 4 additions & 0 deletions libde265/de265.cc
Expand Up @@ -537,6 +537,10 @@ LIBDE265_API void de265_set_parameter_int(de265_decoder_context* de265ctx, enum
ctx->param_slice_headers_fd = value;
break;

case DE265_DECODER_PARAM_DUMP_IMAGE_DATA:
ctx->param_image_data_fd = value;
break;

case DE265_DECODER_PARAM_ACCELERATION_CODE:
ctx->set_acceleration_functions((enum de265_acceleration)value);
break;
Expand Down
3 changes: 2 additions & 1 deletion libde265/de265.h
Expand Up @@ -382,9 +382,10 @@ enum de265_param {
DE265_DECODER_PARAM_SUPPRESS_FAULTY_PICTURES=6, // (bool) do not output frames with decoding errors, default: no (output all images)

DE265_DECODER_PARAM_DISABLE_DEBLOCKING=7, // (bool) disable deblocking
DE265_DECODER_PARAM_DISABLE_SAO=8 // (bool) disable SAO filter
DE265_DECODER_PARAM_DISABLE_SAO=8, // (bool) disable SAO filter
//DE265_DECODER_PARAM_DISABLE_MC_RESIDUAL_IDCT=9, // (bool) disable decoding of IDCT residuals in MC blocks
//DE265_DECODER_PARAM_DISABLE_INTRA_RESIDUAL_IDCT=10 // (bool) disable decoding of IDCT residuals in MC blocks
DE265_DECODER_PARAM_DUMP_IMAGE_DATA=11
};

// sorted such that a large ID includes all optimizations from lower IDs
Expand Down
5 changes: 5 additions & 0 deletions libde265/decctx.cc
Expand Up @@ -223,6 +223,7 @@ decoder_context::decoder_context()
param_vps_headers_fd = -1;
param_pps_headers_fd = -1;
param_slice_headers_fd = -1;
param_image_data_fd = -1;

param_image_allocation_functions = de265_image::default_image_allocation;
param_image_allocation_userdata = NULL;
Expand Down Expand Up @@ -750,6 +751,10 @@ de265_error decoder_context::decode_some(bool* did_work)

*did_work=true;

if (param_image_data_fd>=0) {
dump_image_data(imgunit->img, param_image_data_fd);
}


// mark all CTBs as decoded even if they are not, because faulty input
// streams could miss part of the picture
Expand Down
1 change: 1 addition & 0 deletions libde265/decctx.h
Expand Up @@ -349,6 +349,7 @@ class decoder_context : public base_context {
int param_vps_headers_fd;
int param_pps_headers_fd;
int param_slice_headers_fd;
int param_image_data_fd;

bool param_disable_deblocking;
bool param_disable_sao;
Expand Down
100 changes: 100 additions & 0 deletions libde265/slice.cc
Expand Up @@ -1502,6 +1502,106 @@ void slice_segment_header::dump_slice_segment_header(const decoder_context* ctx,
//#endif
}

void dump_image_data_qp_distro(const de265_image* img, int fd)
{
FILE* fh;
if (fd==1) fh=stdout;
else if (fd==2) fh=stderr;
else { return; }

#define LOG0(t) log2fh(fh, t)
#define LOG1(t,d) log2fh(fh, t,d)
#define LOG2(t,d1,d2) log2fh(fh, t,d1,d2)
#define LOG3(t,d1,d2,d3) log2fh(fh, t,d1,d2,d3)
#define LOG4(t,d1,d2,d3,d4) log2fh(fh, t,d1,d2,d3,d4)

const seq_parameter_set& sps = img->get_sps();
int minCbSize = sps.MinCbSizeY;

// calculate QP distro
int qp_distro[100];
for (int q=0;q<100;q++)
qp_distro[q] = 0;

for (int y0=0;y0<sps.PicHeightInMinCbsY;y0++)
for (int x0=0;x0<sps.PicWidthInMinCbsY;x0++)
{
int log2CbSize = img->get_log2CbSize_cbUnits(x0,y0);
if (log2CbSize==0) {
continue;
}

int xb = x0*minCbSize;
int yb = y0*minCbSize;

int CbSize = 1<<log2CbSize;
//printf("----qp_distro value---- x0: %i, y0: %i, xb: %i, yb: %i, log2CbSize: %i, CbSize: %i\n", x0, y0, xb, yb, log2CbSize, CbSize); // XXX

int q = img->get_QPY(xb,yb);
if (q < 0 || q >= 100) {
LOG1("error: q: %d\n",q);
} else {
//qp_distro[q] += (CbSize*CbSize);
qp_distro[q] += 1;
}
}

// dump QP distro
bool first_nonzero = false;
int lowest_nonzero = 0;
int highest_nonzero = 0;
#define BUFSIZE 1024
char buffer[BUFSIZE] = {};
int bi = 0;
for (int q=0;q<100;q++)
{
if (qp_distro[q] != 0 && !first_nonzero)
{
first_nonzero = true;
lowest_nonzero = q;
}
if (qp_distro[q] != 0)
highest_nonzero = q;
}
bi += snprintf(buffer+bi, BUFSIZE-bi, "qp_distro[%i:%i] { ", lowest_nonzero, highest_nonzero);
for (int q=0;q<100;q++)
{
if (q < lowest_nonzero || q > highest_nonzero)
continue;
bi += snprintf(buffer+bi, BUFSIZE-bi, "%d ", qp_distro[q]);
}
bi += snprintf(buffer+bi, BUFSIZE-bi, "}\n");
LOG0(buffer);

#undef LOG0
#undef LOG1
#undef LOG2
#undef LOG3
#undef LOG4
}

void dump_image_data(const de265_image* img, int fd)
{
FILE* fh;
if (fd==1) fh=stdout;
else if (fd==2) fh=stderr;
else { return; }

#define LOG0(t) log2fh(fh, t)
#define LOG1(t,d) log2fh(fh, t,d)
#define LOG2(t,d1,d2) log2fh(fh, t,d1,d2)
#define LOG3(t,d1,d2,d3) log2fh(fh, t,d1,d2,d3)
#define LOG4(t,d1,d2,d3,d4) log2fh(fh, t,d1,d2,d3,d4)

LOG0("----------------- IMAGE -----------------\n");
dump_image_data_qp_distro(img, fd);

#undef LOG0
#undef LOG1
#undef LOG2
#undef LOG3
#undef LOG4
}


void initialize_CABAC_models(thread_context* tctx)
Expand Down
3 changes: 3 additions & 0 deletions libde265/slice.h
Expand Up @@ -280,6 +280,9 @@ typedef struct {

de265_error read_slice_segment_data(thread_context* tctx);

void dump_image_data_qp_distro(const de265_image*, int fd);
void dump_image_data(const de265_image*, int fd);

bool alloc_and_init_significant_coeff_ctxIdx_lookupTable();
void free_significant_coeff_ctxIdx_lookupTable();

Expand Down

0 comments on commit 8f61dc0

Please sign in to comment.