--cqmfile reads quant matrices in a JM-compatible format.
authorLoren Merritt <pengvado@videolan.org>
Tue, 21 Jun 2005 08:16:01 +0000 (08:16 +0000)
committerLoren Merritt <pengvado@videolan.org>
Tue, 21 Jun 2005 08:16:01 +0000 (08:16 +0000)
git-svn-id: svn://svn.videolan.org/x264/trunk@269 df754926-b1dd-0310-bc7b-ec298dee348c

common/common.c
common/common.h
common/set.c
common/set.h
encoder/encoder.c
x264.c
x264.h

index c6286f9..b354e6e 100644 (file)
@@ -387,3 +387,34 @@ void *x264_realloc( void *p, int i_size )
 #endif
 }
 
+/****************************************************************************
+ * x264_slurp_file:
+ ****************************************************************************/
+char *x264_slurp_file( const char *filename )
+{
+    int b_error = 0;
+    int i_size;
+    char *buf;
+    FILE *fh = fopen( filename, "rb" );
+    if( !fh )
+        return NULL;
+    b_error |= fseek( fh, 0, SEEK_END ) < 0;
+    b_error |= ( i_size = ftell( fh ) ) <= 0;
+    b_error |= fseek( fh, 0, SEEK_SET ) < 0;
+    if( b_error )
+        return NULL;
+    buf = x264_malloc( i_size+2 );
+    if( buf == NULL )
+        return NULL;
+    b_error |= fread( buf, 1, i_size, fh ) != i_size;
+    if( buf[i_size-1] != '\n' )
+        buf[i_size++] = '\n';
+    buf[i_size] = 0;
+    fclose( fh );
+    if( b_error )
+    {
+        x264_free( buf );
+        return NULL;
+    }
+    return buf;
+}
index e561ccc..e0986c4 100644 (file)
@@ -67,6 +67,9 @@ void *x264_malloc( int );
 void *x264_realloc( void *p, int i_size );
 void  x264_free( void * );
 
+/* x264_slurp_file: malloc space for the whole file and read it */
+char *x264_slurp_file( const char *filename );
+
 /* mdate: return the current date in microsecond */
 int64_t x264_mdate( void );
 
index 60bad3a..13d9993 100644 (file)
@@ -21,6 +21,8 @@
  *****************************************************************************/
 
 #include "common.h"
+#include <stdio.h>
+#include <string.h>
 
 static const int dequant4_scale[6][3] =
 {
@@ -105,3 +107,77 @@ void x264_cqm_init( x264_t *h )
     }
 }
 
+int x264_cqm_parse_jmlist( x264_t *h, const char *buf, const char *name,
+                           uint8_t *cqm, const uint8_t *jvt, int length )
+{
+    char *p;
+    char *nextvar;
+    int i;
+
+    p = strstr( buf, name );
+    if( !p )
+    {
+        memset( cqm, 16, length );
+        return 0;
+    }
+
+    p += strlen( name );
+    if( *p == 'U' || *p == 'V' )
+        p++;
+
+    nextvar = strstr( p, "INT" );
+
+    for( i = 0; i < length && (p = strpbrk( p, " \t\n," )) && (p = strpbrk( p, "0123456789" )); i++ )
+    {
+        int coef = -1;
+        sscanf( p, "%d", &coef );
+        if( i == 0 && coef == 0 )
+        {
+            memcpy( cqm, jvt, length );
+            return 0;
+        }
+        if( coef < 1 || coef > 255 )
+        {
+            x264_log( h, X264_LOG_ERROR, "bad coefficient in list '%s'\n", name );
+            return -1;
+        }
+        cqm[i] = coef;
+    }
+
+    if( (nextvar && p > nextvar) || i != length )
+    {
+        x264_log( h, X264_LOG_ERROR, "not enough coefficients in list '%s'\n", name );
+        return -1;
+    }
+
+    return 0;
+}
+
+int x264_cqm_parse_file( x264_t *h, const char *filename )
+{
+    char *buf, *p;
+    int b_error = 0;
+
+    h->param.i_cqm_preset = X264_CQM_CUSTOM;
+    
+    buf = x264_slurp_file( filename );
+    if( !buf )
+    {
+        x264_log( h, X264_LOG_ERROR, "can't open file '%s'\n", filename );
+        return -1;
+    }
+
+    while( (p = strchr( buf, '#' )) != NULL )
+        memset( p, ' ', strcspn( p, "\n" ) );
+
+    b_error |= x264_cqm_parse_jmlist( h, buf, "INTRA4X4_LUMA",   h->param.cqm_4iy, x264_cqm_jvt4i, 16 );
+    b_error |= x264_cqm_parse_jmlist( h, buf, "INTRA4X4_CHROMA", h->param.cqm_4ic, x264_cqm_jvt4i, 16 );
+    b_error |= x264_cqm_parse_jmlist( h, buf, "INTER4X4_LUMA",   h->param.cqm_4py, x264_cqm_jvt4p, 16 );
+    b_error |= x264_cqm_parse_jmlist( h, buf, "INTER4X4_CHROMA", h->param.cqm_4pc, x264_cqm_jvt4p, 16 );
+    b_error |= x264_cqm_parse_jmlist( h, buf, "INTRA8X8_LUMA",   h->param.cqm_8iy, x264_cqm_jvt8i, 64 );
+    b_error |= x264_cqm_parse_jmlist( h, buf, "INTER8X8_LUMA",   h->param.cqm_8py, x264_cqm_jvt8p, 64 );
+
+    x264_free( buf );
+    return b_error;
+}
+
index 3f588fc..9a1bb7d 100644 (file)
@@ -215,5 +215,6 @@ static const uint8_t x264_cqm_flat16[64] =
 };
 
 void x264_cqm_init( x264_t *h );
+int  x264_cqm_parse_file( x264_t *h, const char *filename );
 
 #endif
index b562b2f..bab0134 100644 (file)
@@ -464,6 +464,13 @@ x264_t *x264_encoder_open   ( x264_param_t *param )
         return NULL;
     }
 
+    if( h->param.psz_cqm_file )
+        if( x264_cqm_parse_file( h, h->param.psz_cqm_file ) < 0 )
+        {
+            x264_free( h );
+            return NULL;
+        }
+
     if( h->param.rc.psz_stat_out )
         h->param.rc.psz_stat_out = strdup( h->param.rc.psz_stat_out );
     if( h->param.rc.psz_stat_in )
diff --git a/x264.c b/x264.c
index 0901ab7..f0ba4b8 100644 (file)
--- a/x264.c
+++ b/x264.c
@@ -234,6 +234,8 @@ static void Help( x264_param_t *defaults )
              "\n"
              "      --cqm <string>          Preset quant matrices [\"flat\"]\n"
              "                                  - jvt, flat\n"
+             "      --cqmfile <string>      Read quant matrices from a JM-compatible file\n"
+             "                                  Overrides any other --cqm* options.\n"
              "      --cqm4 <list>           Set all 4x4 quant matrices\n"
              "                                  Takes a comma-separated list of 16 integers.\n"
              "      --cqm8 <list>           Set all 8x8 quant matrices\n"
@@ -395,6 +397,7 @@ static int  Parse( int argc, char **argv,
 #define OPT_CQM8 302
 #define OPT_CQM8I 303
 #define OPT_CQM8P 304
+#define OPT_CQMFILE 305
 
         static struct option long_options[] =
         {
@@ -452,6 +455,7 @@ static int  Parse( int argc, char **argv,
             { "visualize",no_argument,      NULL, OPT_VISUALIZE },
             { "aud",     no_argument,       NULL, OPT_AUD },
             { "cqm",     required_argument, NULL, OPT_CQM },
+            { "cqmfile", required_argument, NULL, OPT_CQMFILE },
             { "cqm4",    required_argument, NULL, OPT_CQM4 },
             { "cqm4i",   required_argument, NULL, OPT_CQM4I },
             { "cqm4iy",  required_argument, NULL, OPT_CQM4IY },
@@ -741,6 +745,9 @@ static int  Parse( int argc, char **argv,
                     return -1;
                 }
                 break;
+            case OPT_CQMFILE:
+                param->psz_cqm_file = optarg;
+                break;
             case OPT_CQM4:
                 param->i_cqm_preset = X264_CQM_CUSTOM;
                 b_error |= parse_cqm( optarg, param->cqm_4iy, 16 );
diff --git a/x264.h b/x264.h
index e396900..381c78d 100644 (file)
--- a/x264.h
+++ b/x264.h
@@ -26,7 +26,7 @@
 
 #include <stdarg.h>
 
-#define X264_BUILD 32
+#define X264_BUILD 33
 
 /* x264_t:
  *      opaque handler for decoder and encoder */
@@ -144,6 +144,7 @@ typedef struct
     int         i_cabac_init_idc;
 
     int         i_cqm_preset;
+    char        *psz_cqm_file;      /* JM format */
     int8_t      cqm_4iy[16];        /* used only if i_cqm_preset == X264_CQM_CUSTOM */
     int8_t      cqm_4ic[16];
     int8_t      cqm_4py[16];