New programs for dealing with VOBs ripped without being decrypted.
authorMark Wooding <mdw@distorted.org.uk>
Sun, 6 Mar 2022 01:11:00 +0000 (01:11 +0000)
committerMark Wooding <mdw@distorted.org.uk>
Sun, 6 Mar 2022 01:11:00 +0000 (01:11 +0000)
When my drives were configured with the wrong region, `libdvdcss' would
have to crack the keys the hard way, and it sometimes failed.  I mostly
shrugged my shoulders, but now I've fixed this problem, I thought I'd
track down the miscopied VOBs and make some tools for fixing the
problem.

.gitignore
Makefile
dvd-check-keys.c [new file with mode: 0644]
dvdrip-check-batch [new file with mode: 0755]
dvdrip-retry-botched-vobs [new file with mode: 0755]

index de68a31..86f1d2f 100644 (file)
@@ -2,5 +2,6 @@
 *.o
 
 /dvd-cache-keys
+/dvd-check-keys
 /dvd-id
 /dvd-sector-copy
index eecede2..f858660 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -45,9 +45,15 @@ dvd-cache-keys_SRCS   = dvd-cache-keys.c lib.c multiprogress.c
 PROGS                  += dvd-id
 dvd-id_SRCS             = dvd-id.c lib.c multiprogress.c
 
+PROGS                  += dvd-check-keys
+dvd-check-keys_SRCS     = dvd-check-keys.c lib.c multiprogress.c
+dvd-check-keys_LIBS     = -ldvdcss
+
 SCRIPTS                        += dvdrip
 SCRIPTS                        += dvdrip-upload
 SCRIPTS                        += dvdrip-monitor
+SCRIPTS                        += dvdrip-check-batch
+SCRIPTS                        += dvdrip-retry-botched-vobs
 
 %.o: %.c
        $(call v-tag,CC)$(CC) -c $(CFLAGS) -o$@ -MD -MF $*.dep $<
diff --git a/dvd-check-keys.c b/dvd-check-keys.c
new file mode 100644 (file)
index 0000000..9aecc49
--- /dev/null
@@ -0,0 +1,81 @@
+#include "lib.h"
+#include "dvdcss/dvdcss.h"
+
+static void usage(FILE *fp)
+  { fprintf(fp, "usage: %s [-b BADFILE] DEVICE\n", prog); }
+
+static dvd_reader_t *dvd;
+static dvdcss_t css;
+
+static FILE *badfp;
+static const char *badfile;
+
+static int check_vob(unsigned index, unsigned titlep)
+{
+  secaddr start, end, pos, len;
+  char fn[MAXFNSZ], fn2[MAXFNSZ];
+  unsigned j;
+  int rc = 0;
+
+  store_filename(fn, mkident(VOB, index, titlep));
+  start = UDFFindFile(dvd, fn, &len);
+  if (!start) return (0);
+  end = start + SECTORS(len);
+
+  if (dvdcss_seek(css, start, DVDCSS_SEEK_KEY) < 0) {
+    if (titlep)
+      for (j = 2; j < 10; j++) {
+       store_filename(fn2, mkident(VOB, index, j));
+       pos = UDFFindFile(dvd, fn2, &len);
+       if (!pos) break;
+       assert(pos == end);
+       end += SECTORS(len);
+      }
+    open_file_on_demand(badfile, &badfp, "uncracked video objects");
+    fprintf(badfp, "%"PRIuSEC" %"PRIuSEC" # %s\n", start, end, fn);
+    rc = -1;
+  }
+
+  return (rc);
+}
+
+int main(int argc, char *argv[])
+{
+  int opt, rc = 0;
+  unsigned j, f = 0;
+#define f_bogus 1u
+
+  set_prog(argv[0]);
+  for (;;) {
+    opt = getopt(argc, argv, "hb:"); if (opt < 0) break;
+    switch (opt) {
+      case 'h': usage(stderr); exit(0);
+      case 'b': badfile = optarg; break;
+      default: f |= f_bogus; break;
+    }
+  }
+  if (argc - optind != 1) f |= f_bogus;
+  if (f&f_bogus) { usage(stderr); exit(2); }
+
+  if (!badfile) badfp = stdout;
+
+  setlocale(LC_ALL, "");
+  progress_init(&progress);
+
+  open_dvd(argv[optind], 0, &dvd);
+  css = dvdcss_open(argv[optind]);
+  if (!css)
+    bail_syserr(errno, "failed to attach CSS machinery to `%s'",
+               argv[optind]);
+
+  for (j = 0; j < 100; j++) {
+    if (check_vob(j, 0)) rc = 1;
+    if (j && check_vob(j, 1)) rc = 1;
+  }
+
+  dvdcss_close(css);
+  DVDClose(dvd);
+  progress_free(&progress);
+  carefully_fclose(badfp, "uncracked objects file");
+  return (rc);
+}
diff --git a/dvdrip-check-batch b/dvdrip-check-batch
new file mode 100755 (executable)
index 0000000..f0f8d37
--- /dev/null
@@ -0,0 +1,33 @@
+#! /bin/bash -e
+
+prog=${0##*/}
+bogus=nil
+usage () {
+  cat <<EOF
+usage: $prog DIR ...
+EOF
+}
+while getopts "h" opt; do
+  case $opt in
+    h) usage; exit 0 ;;
+    *) bogus=t ;;
+  esac
+done
+shift $(( $OPTIND - 1 ))
+case $# in 0) bogus=t ;; esac
+case $bogus in t) usage >&2; exit 2 ;; esac
+
+if [ -t 1 ]; then red=$(tput setaf 1) green=$(tput setaf 2) plain=$(tput op)
+else red= green= plain=; fi
+
+DVDCSS_CACHE=off; export DVDCSS_CACHE
+find "$@" -type f -name "*.iso" | sort | while IFS= read -r iso; do
+  echo -n "check $iso..."
+  retry=${iso%.iso}.retry
+  set +e; dvd-check-keys -b"$retry.new" "$iso"; rc=$?; set -e
+  case $rc in
+    0) rm -f "$retry" echo " ${green}ok${plain}" ;;
+    1) mv "$retry.new" "$retry"; echo " ${red}FAILED${plain}" ;;
+    *) echo " ${red}ERROR${plain}"; exit 2 ;;
+  esac
+done
diff --git a/dvdrip-retry-botched-vobs b/dvdrip-retry-botched-vobs
new file mode 100755 (executable)
index 0000000..4504aad
--- /dev/null
@@ -0,0 +1,27 @@
+#! /bin/sh -e
+
+dev=${DVDRIP_DEVICE-/dev/dvd}
+
+find "$@" -type f -name "*.retry" -print | while IFS= read -r r; do
+  iso=${r%.retry}.iso
+
+  want_id=$(dvd-id "$iso")
+  echo "Insert $iso..."
+  while :; do
+    id=$(dvd-id "$dev")
+    case $id in "$want_id") break ;; esac
+    sleep 2
+  done
+
+  for try in 3 2 1 0; do
+    dvd-sector-copy -R"$r" "$dev" "$iso"
+
+    set +e; DVDCSS_CACHE=off dvd-check-keys -b"$r.new" "$dev"; rc=$?; set -e
+    case $rc,$try in
+      0,*) rm -f "$retry"; break ;;
+      1,0) echo "Giving up :-("; mv "$r.new" "$r"; break ;;
+      1,*) echo "Still broken!  Let's try again..." ;;
+      *) echo "Failed! :-("; exit 2 ;;
+    esac
+  done
+done