⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dvdsubber-vobscan.cpp

📁 DVD工具dvdsynth的源码
💻 CPP
字号:
/***********************************************************************
 Copyright 2002 Ben Rudiak-Gould.

 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.

 This program 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 General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA,
 or visit <http://www.gnu.org/copyleft/gpl.html>.
***********************************************************************/


#include "DVDSubber-vobscan.h"
#include <string.h>
#include <stdio.h>


static unsigned get4(unsigned char* p) {
   unsigned result = 0;
   for (int i=0; i<4; ++i)
      result = result*256 + p[i];
   return result;
}


bool Scan(unsigned vobu_admap_lba, unsigned num_vobus, unsigned vts_vobs_lba, IScannerCallbacks* scanner_callbacks) {
   scanner_callbacks->Note("Scanning the DVD (this may take a while)...");

   unsigned vobu_admap_sectors = (num_vobus >> 9) + 1;
   unsigned char* vobu_lbas = new unsigned char[vobu_admap_sectors * 2048];
   for (unsigned s=0; s<vobu_admap_sectors; ++s) {
      if (!scanner_callbacks->ReadSector(vobu_admap_lba+s, vobu_lbas + s*2048)) {
         scanner_callbacks->ErrorAtLBA("Could not read the DVD disc", vobu_admap_lba+s);
         return false;
      }
   }

   int old_angle = 0, max_angle = 0;

   unsigned last_saved_ptm = 0;

   unsigned ptm_by_angle[10];
   memset(ptm_by_angle, 0, sizeof(ptm_by_angle));

   for (unsigned vobu_number = 1; vobu_number <= num_vobus; ++vobu_number) {

      if (scanner_callbacks->UserAborted()) {
         return false;
      }

      unsigned lba = vts_vobs_lba + get4(vobu_lbas + vobu_number * 4);

      unsigned char buf[2048];
      if (!scanner_callbacks->ReadSector(lba, buf)) {
         scanner_callbacks->ErrorAtLBA("Could not read the DVD disc", lba);
         return false;
      }

      if (get4(buf) != 0x000001BA) {
         scanner_callbacks->ErrorAtLBA("Not an MPEG-2 pack!", lba);
         return false;
      }
      unsigned char* p = buf + 14 + (buf[13] & 7);
      if (get4(p) != 0x000001BB) {
         scanner_callbacks->ErrorAtLBA("Not a NAV pack!", lba);
         return false;
      }
      unsigned flags = buf[0x427] >> 4;
      int angle = 0;
      if (flags & 4) {
         for (angle = 1; angle <= 9; ++angle) {
            if (get4(buf + 0x65 + angle*4) == 0x80000000) {
               break;
            }
         }
         if (angle > 9) {
            scanner_callbacks->Warning("Warning: passed angle 9 (this is probably a bug)");
            angle = 0;
         }
      }
      if (angle != old_angle) {
         scanner_callbacks->ChangeAngle(angle);
         if (angle > 0) {
            if (old_angle == 0) {
               for (int a=1; a<=9; ++a) {
                  ptm_by_angle[a] = ptm_by_angle[0];
               }
            }
            if (max_angle < angle) max_angle = angle;
         } else {
            ptm_by_angle[0] = ptm_by_angle[1];
            for (int a=2; a<=max_angle; ++a) {
               if (ptm_by_angle[0] != ptm_by_angle[a]) {
                  scanner_callbacks->Warning("Warning: bad PTM on angle merge (this is probably a bug)");
               }
            }
            max_angle = 0;
         }
         old_angle = angle;
      }
      unsigned skip_blocks = get4(buf+0x40f);
      unsigned s_ptm = get4(buf+0x39);
      if (ptm_by_angle[angle] != s_ptm) {
         last_saved_ptm = s_ptm;
         scanner_callbacks->ChangePTM(s_ptm);
      }
      unsigned e_ptm = get4(buf+0x3D);
      ptm_by_angle[angle] = e_ptm;
      unsigned ptm_delta = e_ptm - s_ptm;
      bool ntsc = (buf[0x48] >> 7) & 1;
      unsigned fields;
      if (ntsc) {
         fields = (ptm_delta / 3003) * 2;
         switch (ptm_delta % 3003) {
         case 0:
            break;
         case 1501: case 1502:
            ++fields;
            break;
         default:
            scanner_callbacks->Warning("Warning: unexpected PTM delta");
         }
         unsigned foo = (e_ptm - last_saved_ptm) % 3003;
         if (foo != 0 && foo != 1501) {
            printf("foo = %d\n", foo);
         }
      } else {
         fields = ptm_delta / 1800;
         if (ptm_delta % 1800 != 0) {
            scanner_callbacks->Warning("Warning: unexpected PTM delta");
         }
      }
      scanner_callbacks->AddVOBU(lba, vobu_number, fields, skip_blocks);
   }

   return true;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -