changeset 16366:e054a3c93a26

custom quantization matrix for x264, original patch by Robert Swain < robert POUM swain AH gmail POUM com> Lots of nits and improvement by the MPlayer team Original thread: Date: Jul 12, 2005 5:04 PM Subject: [MPlayer-dev-eng] [PATCH] CQMs in x264
author gpoirier
date Fri, 02 Sep 2005 21:54:17 +0000
parents a9a27763d567
children 8e859a01904f
files ChangeLog DOCS/man/en/mplayer.1 libmpcodecs/ve_x264.c
diffstat 3 files changed, 120 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Fri Sep 02 20:37:34 2005 +0000
+++ b/ChangeLog	Fri Sep 02 21:54:17 2005 +0000
@@ -72,6 +72,7 @@
     * raw audio muxer
     * fixed various bugs in the EDL code
     * x264 "turbo mode" to speed up first pass of multi-pass encoding
+    * x264 custom quantization matrices
     * -delay allows real audio delay instead of just a delay in the header
 
     Ports:
--- a/DOCS/man/en/mplayer.1	Fri Sep 02 20:37:34 2005 +0000
+++ b/DOCS/man/en/mplayer.1	Fri Sep 02 21:54:17 2005 +0000
@@ -8466,6 +8466,62 @@
 Useful values are in the range <-2\-2> (default: 0).
 .
 .TP
+.B cqm=<flat|jvt|<filename>>
+Either uses a predefined custom quantization matrix or loads a JM format
+matrix file.
+.PD 0
+.RSs
+.IPs flat\ 
+Use the predefined flat 16 matrix (default).
+.IPs jvt\ \ 
+Use the predefined JVT matrix.
+.IPs <filename>
+Use the provided JM format matrix file.
+.PD 1
+.RE
+.
+.TP
+.B cqm4iy=<list>
+custom 4x4 intra luminance matrix, given as a list of 16 comma separated
+values in the range 1-255.
+.
+.TP
+.B cqm4ic=<list>
+custom 4x4 intra chrominance matrix, given as a list of 16 comma
+separated values in the range 1-255.
+.
+.TP
+.B cqm4py=<list>
+custom 4x4 inter luminance matrix, given as a list of 16 comma separated
+values in the range 1-255.
+.
+.TP
+.B cqm4pc=<list>
+custom 4x4 inter chrominance matrix, given as a list of 16 comma
+separated values in the range 1-255.
+.
+.TP
+.B cqm8iy=<list>
+custom 8x8 intra luminance matrix, given as a list of 64 comma separated
+values in the range 1-255.
+.
+.TP
+.B cqm8py=<list>
+custom 8x8 inter luminance matrix, given as a list of 64 comma separated
+values in the range 1-255.
+.RE
+.I NOTES:
+Files encoded using CQMs are not currently decodable by FFmpeg based
+players.
+.br
+Windows CMD.EXE users may experience problems with parsing the command line
+if they attempt to use all the CQM lists.
+This is due to a command line length limitation.
+In this case it is recommended the lists be put into a JM format CQM
+file and loaded as specified above.
+.RE
+.
+.TP
 .B level_idc=<10\-51>
 Set the bitstream's Level as defined by Annex A of the H.264 standard
 (default: 40 - Level 4.0).
--- a/libmpcodecs/ve_x264.c	Fri Sep 02 20:37:34 2005 +0000
+++ b/libmpcodecs/ve_x264.c	Fri Sep 02 21:54:17 2005 +0000
@@ -106,6 +106,13 @@
 static int log_level = 2;
 static int turbo = 0;
 static int visualize = 0;
+static char *cqm = NULL;
+static char *cqm4iy = NULL;
+static char *cqm4ic = NULL;
+static char *cqm4py = NULL;
+static char *cqm4pc = NULL;
+static char *cqm8iy = NULL;
+static char *cqm8py = NULL;
 
 m_option_t x264encopts_conf[] = {
     {"bitrate", &bitrate, CONF_TYPE_INT, CONF_RANGE, 0, 24000000, NULL},
@@ -155,6 +162,13 @@
     {"qp_step", &qp_step, CONF_TYPE_INT, CONF_RANGE, 1, 50, NULL},
     {"pass", &pass, CONF_TYPE_INT, CONF_RANGE, 1, 3, NULL},
     {"rc_eq", &rc_eq, CONF_TYPE_STRING, 0, 0, 0, NULL},
+    {"cqm", &cqm, CONF_TYPE_STRING, 0, 0, 0, NULL},
+    {"cqm4iy", &cqm4iy, CONF_TYPE_STRING, 0, 0, 0, NULL},
+    {"cqm4ic", &cqm4ic, CONF_TYPE_STRING, 0, 0, 0, NULL},
+    {"cqm4py", &cqm4py, CONF_TYPE_STRING, 0, 0, 0, NULL},
+    {"cqm4pc", &cqm4pc, CONF_TYPE_STRING, 0, 0, 0, NULL},
+    {"cqm8iy", &cqm8iy, CONF_TYPE_STRING, 0, 0, 0, NULL},
+    {"cqm8py", &cqm8py, CONF_TYPE_STRING, 0, 0, 0, NULL},
     {"qcomp", &qcomp, CONF_TYPE_FLOAT, CONF_RANGE, 0, 1, NULL},
     {"qblur", &qblur, CONF_TYPE_FLOAT, CONF_RANGE, 0, 99, NULL},
     {"cplx_blur", &complexity_blur, CONF_TYPE_FLOAT, CONF_RANGE, 0, 999, NULL},
@@ -173,6 +187,23 @@
     {NULL, NULL, 0, 0, 0, 0, NULL}
 };
 
+static int parse_cqm(const char *str, uint8_t *cqm, int length,
+                     h264_module_t *mod, char *matrix_name) {
+    int i;
+    if (!str) return 0;
+    for (i = 0; i < length; i++) {
+        long coef = strtol(str, &str, 0);
+        if (coef < 1 || coef > 255 || str[0] != ((i + 1 == length)?0:',')) {
+            mp_msg( MSGT_MENCODER, MSGL_ERR, "x264: Invalid entry in cqm%s at position %d.\n", matrix_name, i+1 );
+            return -1;
+        }
+        cqm[i] = coef;
+        str = &str[1];
+    }
+    mod->param.i_cqm_preset = X264_CQM_CUSTOM;
+    return 0;
+}
+
 static int put_image(struct vf_instance_s *vf, mp_image_t *mpi);
 static int encode_frame(struct vf_instance_s *vf, x264_picture_t *pic_in);
 
@@ -263,6 +294,38 @@
     mod->param.vui.i_sar_height = d_height*width;
     mod->param.i_threads = threads;
 
+    if(cqm != NULL)
+    {
+        if( !strcmp(cqm, "flat") )
+            mod->param.i_cqm_preset = X264_CQM_FLAT;
+        else if( !strcmp(cqm, "jvt") )
+            mod->param.i_cqm_preset = X264_CQM_JVT;
+        else
+        {
+            FILE *cqm_test;
+            cqm_test = fopen( cqm, "rb" );
+            if( cqm_test )
+            {
+                mod->param.i_cqm_preset = X264_CQM_CUSTOM;
+                mod->param.psz_cqm_file = cqm;
+                fclose( cqm_test );
+            }
+            else
+            {
+                mp_msg( MSGT_MENCODER, MSGL_ERR, "x264: CQM file failed to open.\n" );
+                return 0;
+            }
+        }
+    }
+
+    if( (parse_cqm(cqm4iy, mod->param.cqm_4iy, 16, mod, "4iy") < 0) ||
+        (parse_cqm(cqm4ic, mod->param.cqm_4ic, 16, mod, "4ic") < 0) ||
+        (parse_cqm(cqm4py, mod->param.cqm_4py, 16, mod, "4py") < 0) ||
+        (parse_cqm(cqm4pc, mod->param.cqm_4pc, 16, mod, "4pc") < 0) ||
+        (parse_cqm(cqm8iy, mod->param.cqm_8iy, 64, mod, "8iy") < 0) ||
+        (parse_cqm(cqm8py, mod->param.cqm_8py, 64, mod, "8py") < 0) )
+        return 0;
+
     switch(pass) {
     case 0:
         mod->param.rc.b_stat_write = 0;