changeset 22252:c5a591c4a372

Controllable quality setting of VFW enconding, through the dumped state of the dialog box. Patch by Gianluigi Tiesi
author alex
date Sun, 18 Feb 2007 23:24:21 +0000
parents f2f62540bd0d
children 389c91ead5b6
files TOOLS/vfw2menc.c libmpcodecs/ve_vfw.c
diffstat 2 files changed, 308 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TOOLS/vfw2menc.c	Sun Feb 18 23:24:21 2007 +0000
@@ -0,0 +1,257 @@
+/*
+ * VFW Compressor Settings Tool
+ *
+ * Copyright (c) 2006 Gianluigi Tiesi <sherpya@netfarm.it>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this software; if not, write to the
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* On mingw compile with: gcc getopt.c vfw2menc.c -o vfw2menc.exe -lwinmm */
+/* Using wine: winegcc getopt.c vfw2menc.c -o vfw2menc -lwinmm */
+
+#ifdef _MSC_VER
+#define _CRT_SECURE_NO_DEPRECATE
+#pragma warning(disable: 4996)
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <getopt.h>
+#include <windows.h>
+#include <vfw.h>
+
+#define BAIL(msg) { printf("%s: %s\n", argv[0], msg); ret = -1; goto cleanup; }
+
+enum
+{
+    MODE_NONE = 0,
+    MODE_CHECK,
+    MODE_SAVE,
+    MODE_VIEW
+};
+
+int save_settings(HDRVR hDriver, const char *filename)
+{
+    FILE *fd = NULL;
+    DWORD cb = (DWORD) SendDriverMessage(hDriver, ICM_GETSTATE, 0, 0);
+    char *pv = NULL;
+
+    if (!cb)
+    {
+        printf("ICM_GETSTATE returned 0 size\n");
+        return -1;
+    }
+
+    pv = (char *) malloc(cb);
+    if (SendDriverMessage(hDriver, ICM_GETSTATE, (LPARAM) pv, (LPARAM) &cb) != ICERR_OK)
+    {
+        printf("ICM_GETSTATE failed\n");
+        free(pv);
+        return -1;
+    }
+
+    fd = fopen(filename, "wb");
+    if (!fd)
+    {
+        printf("Cannot open file %s for writing\n", filename);
+        free(pv);
+        return -1;
+    }
+
+    if (fwrite(pv, cb, 1, fd) != 1)
+    {
+        printf("fwrite() failed on %s\n", filename);
+        free(pv);
+        fclose(fd);
+        return -1;
+    }
+    fclose(fd);
+    free(pv);
+    return 0;
+}
+
+int load_settings(HDRVR hDriver, const char *filename)
+{
+    struct stat info;
+    FILE *fd = NULL;
+    char *pv;
+
+    if (stat(filename, &info) < 0)
+    {
+        printf("stat() on %s failed\n", filename);
+        return -1;
+    }
+
+    pv = (char *) malloc(info.st_size);
+    fd = fopen(filename, "rb");
+
+    if (!fd)
+    {
+        printf("Cannot open file %s for reading\n", filename);
+        free(pv);
+        return -1;
+    }
+
+    if (fread(pv, info.st_size, 1, fd) != 1)
+    {
+        printf("fread() failed on %s\n", filename);
+        free(pv);
+        fclose(fd);
+        return -1;
+    }
+    fclose(fd);
+    if (!SendDriverMessage(hDriver, ICM_SETSTATE, (LPARAM) pv, (LPARAM) info.st_size))
+    {
+        printf("ICM_SETSTATE failed\n");
+        free(pv);
+        return -1;
+    }
+    free(pv);
+    return 0;
+}
+
+static struct option long_options[] =
+{
+    { "help",   no_argument,        NULL,   'h' },
+    { "driver", required_argument,  NULL,   'd' },
+    { "fourcc", required_argument,  NULL,   'f' },
+    { "save",   required_argument,  NULL,   's' },
+    { "check",  required_argument,  NULL,   'c' },
+    { "view",   no_argument,        NULL,   'v' },
+    { 0, 0, 0, 0 }
+};
+
+void help(const char *progname)
+{
+    printf("VFW to mencoder - Copyright 2006 - Gianluigi Tiesi <sherpya@netfarm.it>\n");
+    printf("This program is Free Software\n\n");
+    printf("Usage: %s\n", progname);
+    printf("      -h|--help            - displays this help\n");
+    printf("      -d|--driver filename - dll or drv to load\n");
+    printf("      -f|--fourcc fourcc   - fourcc of selected driver (look at codecs.conf)\n");
+    printf("      -s|--save filename   - save settings to file\n");
+    printf("      -c|--check filename  - load and show setting in filename\n");
+    printf("      -v|--view            - displays the config dialog and do nothing\n");
+    printf("\nExamples:\n");
+    printf(" %s -f VP62 -d vp6vfw.dll -s firstpass.mcf\n", progname);
+    printf(" %s -f VP62 -d vp6vfw.dll -c firstpass.mcf\n", progname);
+    printf(" %s -f VP62 -d vp6vfw.dll -v\n", progname);
+    printf("\nIf the driver dialog doesn't work, you can try without specifing a fourcc,\n");
+    printf("but the compdata file will not work with mencoder.\n");
+    printf("Driver option is required and you must specify at least -s, -c -o -v\n");
+    printf("Usage with mencoder -ovc vfw -xvfwopts codec=vp6vfw.dll:compdata=settings.mcf\n");
+}
+
+
+int main(int argc, char *argv[])
+{
+    char *driver = NULL;
+    char *fourcc = NULL;
+    char *filename = NULL;
+    unsigned char mode = 0;
+
+    wchar_t drvfile[MAX_PATH];
+    HDRVR hDriver = NULL;
+    int ret = 0;
+    int c = -1, long_options_index = -1;
+
+    if (argc < 2)
+    {
+        help(argv[0]);
+        ret = -1;
+        goto cleanup;
+    }
+
+    while ((c = getopt_long(argc, argv, "hd:f:s:c:v", long_options, &long_options_index)) != -1)
+    {
+        switch (c)
+        {
+            case 'h':
+                help(argv[0]);
+                ret = 0;
+                goto cleanup;
+            case 'd':
+                driver = strdup(optarg);
+                break;
+            case 'f':
+                fourcc = strdup(optarg);
+                if (strlen(optarg) != 4) BAIL("Fourcc must be exactly 4 chars");
+                break;
+            case 's':
+                if (mode != MODE_NONE) BAIL("Incompatible arguments");
+                filename = strdup(optarg);
+                mode = MODE_SAVE;
+                break;
+            case 'c':
+                if (mode != MODE_NONE) BAIL("Incompatible arguments");
+                filename = strdup(optarg);
+                mode = MODE_CHECK;
+                break;
+            case 'v':
+                if (mode != MODE_NONE) BAIL("Incompatible arguments");
+                mode = MODE_VIEW;
+                break;
+            default:
+                printf("Wrong arguments!\n");
+        }
+    }
+
+
+    if (!(argc == optind) && (mode != MODE_NONE) &&
+        driver && (filename || (mode == MODE_VIEW)))
+    {
+        help(argv[0]);
+        goto cleanup;
+    }
+
+    if (!MultiByteToWideChar(CP_ACP, 0, driver, -1, drvfile, MAX_PATH))
+        BAIL("MultiByteToWideChar() failed\n");
+
+    if (!(hDriver = OpenDriver(drvfile, 0, (fourcc) ? ((LPARAM) fourcc) : 0)))
+        BAIL("OpenDriver() failed\n");
+
+    if (SendDriverMessage(hDriver, ICM_CONFIGURE, -1, 0) != ICERR_OK)
+        BAIL("The driver doesn't provide a configure dialog");
+
+    switch(mode)
+    {
+        case MODE_CHECK:
+            if (load_settings(hDriver, filename))
+                BAIL("Cannot load settings from file");
+            if (SendDriverMessage(hDriver, ICM_CONFIGURE, 0, 0) != ICERR_OK)
+                BAIL("ICM_CONFIGURE failed");
+            break;
+        case MODE_SAVE:
+            if (SendDriverMessage(hDriver, ICM_CONFIGURE, 0, 0) != ICERR_OK)
+                BAIL("ICM_CONFIGURE failed");
+            if (save_settings(hDriver, filename))
+                BAIL("Cannot save settings to file");
+            break;
+        case MODE_VIEW:
+            if (SendDriverMessage(hDriver, ICM_CONFIGURE, 0, 0) != ICERR_OK)
+                BAIL("ICM_CONFIGURE failed");
+            break;
+        default:
+            BAIL("This should not happen :)");
+    }
+
+cleanup:
+    if (driver) free(driver);
+    if (fourcc) free(fourcc);
+    if (filename) free(filename);
+    if (hDriver) CloseDriver(hDriver, 0, 0);
+    return ret;
+}
--- a/libmpcodecs/ve_vfw.c	Sun Feb 18 22:57:47 2007 +0000
+++ b/libmpcodecs/ve_vfw.c	Sun Feb 18 23:24:21 2007 +0000
@@ -3,6 +3,7 @@
 #include <string.h>
 #include <unistd.h>
 #include <inttypes.h>
+#include <sys/stat.h>
 
 #include "config.h"
 
@@ -29,11 +30,13 @@
 //===========================================================================//
 
 static char *vfw_param_codec = NULL;
+static char *vfw_param_compdata = NULL;
 
 #include "m_option.h"
 
 m_option_t vfwopts_conf[]={
     {"codec", &vfw_param_codec, CONF_TYPE_STRING, 0, 0, 0, NULL},
+    {"compdata", &vfw_param_compdata, CONF_TYPE_STRING, 0, 0, 0, NULL},
     {NULL, NULL, 0, 0, 0, 0, NULL}
 };
 
@@ -48,11 +51,14 @@
 static int encoder_frameno=0;
 
 //int init_vfw_encoder(char *dll_name, BITMAPINFOHEADER *input_bih, BITMAPINFOHEADER *output_bih)
-static BITMAPINFOHEADER* vfw_open_encoder(char *dll_name, BITMAPINFOHEADER *input_bih,unsigned int out_fourcc)
+static BITMAPINFOHEADER* vfw_open_encoder(char *dll_name, char *compdatafile, BITMAPINFOHEADER *input_bih,unsigned int out_fourcc)
 {
   HRESULT ret;
   BITMAPINFOHEADER* output_bih=NULL;
   int temp_len;
+  FILE *fd=NULL;
+  char *drvdata=NULL;
+  struct stat st;
 
 //sh_video = malloc(sizeof(sh_video_t));
 
@@ -93,6 +99,47 @@
 }
 #endif
 
+  if(compdatafile){
+    if (!strncmp(compdatafile, "dialog", 6)){
+      if (ICSendMessage(encoder_hic, ICM_CONFIGURE, -1, 0) != ICERR_OK){
+        mp_msg(MSGT_WIN32,MSGL_ERR,"Compressor doesn't have a configure dialog!\n");
+        return NULL;
+      }
+      if (ICSendMessage(encoder_hic, ICM_CONFIGURE, 0, 0) != ICERR_OK){
+        mp_msg(MSGT_WIN32,MSGL_ERR,"Compressor configure dialog failed!\n");
+        return NULL;
+      }
+    }
+    else {
+      if (stat(compdatafile, &st) < 0){
+        mp_msg(MSGT_WIN32,MSGL_ERR,"Compressor data file not found!\n");
+        return NULL;
+      }
+      fd = fopen(compdatafile, "rb");
+      if (!fd){
+        mp_msg(MSGT_WIN32,MSGL_ERR,"Cannot open Compressor data file!\n");
+        return NULL;
+      }
+      drvdata = (char *) malloc(st.st_size);
+      if (fread(drvdata, st.st_size, 1, fd) != 1) {
+        mp_msg(MSGT_WIN32,MSGL_ERR,"Cannot read Compressor data file!\n");
+        fclose(fd);
+        free(drvdata);
+        return NULL;
+      }
+      fclose(fd);
+      mp_msg(MSGT_WIN32,MSGL_ERR,"Compressor data %d bytes\n", st.st_size);
+      if (!(temp_len = (unsigned int) ICSendMessage(encoder_hic, ICM_SETSTATE, (LPARAM) drvdata, (int) st.st_size))){
+        mp_msg(MSGT_WIN32,MSGL_ERR,"ICSetState failed!\n");
+        fclose(fd);
+        free(drvdata);
+        return NULL;
+      }
+      free(drvdata);
+      mp_msg(MSGT_WIN32,MSGL_INFO,"ICSetState ret: %d\n", temp_len);
+    }
+  }
+
   temp_len = ICCompressGetFormatSize(encoder_hic, input_bih);
   mp_msg(MSGT_WIN32,MSGL_INFO,"ICCompressGetFormatSize ret: %d\n", temp_len);
 
@@ -243,6 +290,8 @@
     int ret;
 //    flip_upside_down(vo_image_ptr,vo_image_ptr,3*vo_w,vo_h); // dirty hack
     ret=vfw_encode_frame(mux_v->bih, mux_v->buffer, vfw_bih, mpi->planes[0], &flags, 10000);
+//    if (ret != ICERR_OK)
+//	return 0;
     muxer_write_chunk(mux_v,mux_v->bih->biSizeImage,flags, pts, pts);
     return 1;
 }
@@ -275,7 +324,7 @@
     }
 //    mux_v->bih=vfw_open_encoder("divxc32.dll",vfw_bih,mmioFOURCC('D', 'I', 'V', '3'));
 //    mux_v->bih=vfw_open_encoder("AvidAVICodec.dll",vfw_bih, 0);
-    mux_v->bih = vfw_open_encoder(vfw_param_codec, vfw_bih, 0);
+    mux_v->bih = vfw_open_encoder(vfw_param_codec, vfw_param_compdata, vfw_bih, 0);
     if(!mux_v->bih) return 0;
 
     return 1;