diff --git a/dec265/dec265.cc b/dec265/dec265.cc index 30f544311..4bf0c71c7 100644 --- a/dec265/dec265.cc +++ b/dec265/dec265.cc @@ -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; @@ -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' }, @@ -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 @@ -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; @@ -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); diff --git a/libde265/de265.cc b/libde265/de265.cc index 75dd0a893..68b648a34 100644 --- a/libde265/de265.cc +++ b/libde265/de265.cc @@ -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; diff --git a/libde265/de265.h b/libde265/de265.h index 6481d8f0a..fba09ed13 100644 --- a/libde265/de265.h +++ b/libde265/de265.h @@ -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 diff --git a/libde265/decctx.cc b/libde265/decctx.cc index edebb7136..07d53d19a 100644 --- a/libde265/decctx.cc +++ b/libde265/decctx.cc @@ -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; @@ -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 diff --git a/libde265/decctx.h b/libde265/decctx.h index c1acdcef0..3750ab861 100644 --- a/libde265/decctx.h +++ b/libde265/decctx.h @@ -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; diff --git a/libde265/slice.cc b/libde265/slice.cc index e85ecc619..6f5768b46 100644 --- a/libde265/slice.cc +++ b/libde265/slice.cc @@ -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;y0get_log2CbSize_cbUnits(x0,y0); + if (log2CbSize==0) { + continue; + } + + int xb = x0*minCbSize; + int yb = y0*minCbSize; + + int CbSize = 1<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) diff --git a/libde265/slice.h b/libde265/slice.h index 0f476f293..d1b15c137 100644 --- a/libde265/slice.h +++ b/libde265/slice.h @@ -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();