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

📄 dvdsubber.cpp

📁 DVD工具dvdsynth的源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/***********************************************************************
 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>.
***********************************************************************/


#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <commdlg.h>

#include "DVDSubber.h"
#include "DVDSubber-dialog.h"
#include "DVDSubber-vobscan.h"
#include "DVDSubber-compile.h"

#include "../include/dvdsynth-filter.h"

#include <stdio.h>


HINSTANCE g_hinstance;

DvsDockingBayGlobal* g_bays;


//scsi_result_t ScsiCommand(DvsDeviceKernel* self, const unsigned char* cdb, int cdblen, unsigned char* buffer, unsigned long* pbuflen, int inout, SenseData* sense);


/********************************************************************
********************************************************************/


struct DVDSubberUser : DvsDeviceUser {
   DVDSubberKernel* k;
   dvs_driver_handle driver_handle;
   DvsDockingBay* bay;
   HANDLE data_file_handle;
};


/********************************************************************
********************************************************************/


unsigned updcrc32(unsigned crc, unsigned char *buf, int len) {
   static unsigned table[256];
   const unsigned poly = 0xEDB88320;
   if (table[255] == 0) {
      for (unsigned n = 0; n < 256; n++) {
         unsigned c = n;
         for (int k = 0; k < 8; k++) {
            if (c & 1) {
               c = poly ^ (c >> 1);
            } else {
               c = c >> 1;
            }
         }
         table[n] = c;
      }
   }

   crc = ~crc;
   for (int n = 0; n < len; n++) {
      crc = table[(crc ^ buf[n]) & 0xff] ^ (crc >> 8);
   }
   return ~crc;
}


class SlidingBuffer {
   DvsDeviceKernel* k;
   unsigned cur_sector;
   unsigned crc;
   unsigned char buf[2048];
public:
   SlidingBuffer(DvsDeviceKernel* _k) {
      k = _k;
      cur_sector = ~0U;
      crc = 0;
   }
   unsigned GetDword(unsigned base_sector, unsigned offset);
   unsigned GetDword(unsigned offset);
   unsigned GetCumulativeCRC() { return crc; }
};


unsigned SlidingBuffer::GetDword(unsigned base_sector, unsigned offset) {
   base_sector += (offset>>11);
   offset &= 2047;
   if (base_sector != cur_sector) {
      static unsigned char cdb[10] = { 0x28, 0, 0, 0, 0, 0, 0, 0, 1, 0 };
      for (int i=0; i<4; ++i) {
         cdb[5-i] = base_sector >> (i*8);
      }
      unsigned long buflen = 2048;
      SenseData sense;
      scsi_result_t result = g_bays->KernelScsiCommand(k, cdb, 10, buf, &buflen, 1, &sense);
      if (result != SCSIRESULT_SUCCESS) {
         throw result;
      }
      cur_sector = base_sector;
      crc = updcrc32(crc, buf, 2048);
   }
   return GetDword(offset);
}


unsigned SlidingBuffer::GetDword(unsigned offset) {
   return buf[offset]*16777216 + buf[offset+1]*65536 + buf[offset+2]*256 + buf[offset+3];
}


DiscInfo* GetDiscInfo(DvsDeviceKernel* dev, DvsDockingBay* bay) {
   DvdVideoInfo dvd_video_info;
   int result = g_bays->GetDvdVideoInfo(dev, &dvd_video_info);
   if (result < 0) {
      return 0;
   }
   DiscInfo di;
   SlidingBuffer disc(dev);

   di.vmg_ifo_sector = dvd_video_info.vmg_ifo_sector;
   di.vmg_vobs_sector = di.vmg_ifo_sector + disc.GetDword(di.vmg_ifo_sector, 0xC0);
   di.vmg_bup_sector = di.vmg_ifo_sector + disc.GetDword(0x0C) - disc.GetDword(0x1C);

   unsigned tt_srpt_sector = disc.GetDword(0xC4);
   di.vmg_tt_srpt_offset = tt_srpt_sector * 2048 + 8;
   tt_srpt_sector += di.vmg_ifo_sector;

   di.num_title_sets = disc.GetDword(tt_srpt_sector, 0) >> 16;
   di.vmg_tt_srpt_end_offset = di.vmg_tt_srpt_offset + disc.GetDword(4) - 7;
   di.titlesets = (TitleSetInfo*)bay->vtable->SharedPool_Alloc(bay, di.num_title_sets * sizeof(TitleSetInfo));
   di.num_title_sets = 0;
   memset(di.titlesets, 0, di.num_title_sets * sizeof(TitleSetInfo));
   for (unsigned ofs = di.vmg_tt_srpt_offset; ofs < di.vmg_tt_srpt_end_offset; ofs += 12) {
      unsigned title_set = ((disc.GetDword(di.vmg_ifo_sector, ofs+4) >> 8) & 255) - 1;
      if (title_set < 99) {
         di.titlesets[title_set].vts_ifo_sector = di.vmg_ifo_sector + disc.GetDword(di.vmg_ifo_sector, ofs+8);
         if (title_set >= di.num_title_sets) {
            di.num_title_sets = title_set+1;
         }
      }
   }
   for (unsigned ts = 0; ts < di.num_title_sets; ++ts) {
      TitleSetInfo& tsi = di.titlesets[ts];
      if (tsi.vts_ifo_sector == 0) continue;
      tsi.vtsm_vobs_sector = tsi.vts_ifo_sector + disc.GetDword(tsi.vts_ifo_sector, 0xC0);
      tsi.vts_vobs_sector = tsi.vts_ifo_sector + disc.GetDword(0xC4);
      tsi.vts_bup_sector = tsi.vts_ifo_sector + disc.GetDword(0x0C) - disc.GetDword(0x1C);
      tsi.number_of_existing_subpicture_tracks = disc.GetDword(0x254) >> 16;
      unsigned flags = disc.GetDword(0x200);
      tsi.ntsc = ~(flags >> 28) & 1;
      tsi.wide_aspect = (flags >> 27) & 1;
      unsigned pgci_sector = disc.GetDword(0xCC);
      unsigned tmapti_sector = disc.GetDword(0xD4);
      unsigned c_adt_sector = disc.GetDword(0xE0);
      unsigned vobu_admap_sector = disc.GetDword(0xE4);
      if (pgci_sector) {
         tsi.num_pgcs = disc.GetDword(tsi.vts_ifo_sector + pgci_sector, 0) >> 16;
         tsi.pgcs = (TitlePGCInfo*)bay->vtable->SharedPool_Alloc(bay, tsi.num_pgcs * sizeof(TitlePGCInfo));
         unsigned pgc;
         for (pgc = 0; pgc < tsi.num_pgcs; ++pgc) {
            tsi.pgcs[pgc].subpicture_status_offset = pgci_sector*2048 + disc.GetDword(tsi.vts_ifo_sector + pgci_sector, pgc*8+12) + 0x1C;
         }
         for (pgc = 0; pgc < tsi.num_pgcs; ++pgc) {
            unsigned pgc_offset = tsi.pgcs[pgc].subpicture_status_offset - 0x1C;
            unsigned num_cells = disc.GetDword(tsi.vts_ifo_sector, pgc_offset) & 255;
            tsi.pgcs[pgc].cell_playback_info_table_offset = pgc_offset + (disc.GetDword(tsi.vts_ifo_sector, pgc_offset+0xE8) >> 16);
            tsi.pgcs[pgc].cell_playback_info_table_end_offset = tsi.pgcs[pgc].cell_playback_info_table_offset + 24 * num_cells;
         }
      }
      if (tmapti_sector) {
         tsi.num_tmaps = disc.GetDword(tsi.vts_ifo_sector+tmapti_sector, 0) >> 16;
         tsi.tmaps = (TitleTmapInfo*)bay->vtable->SharedPool_Alloc(bay, tsi.num_tmaps * sizeof(TitleTmapInfo));
         unsigned tmap;
         for (tmap = 0; tmap < tsi.num_tmaps; ++tmap) {
            tsi.tmaps[tmap].offset = tmapti_sector * 2048 + disc.GetDword(tsi.vts_ifo_sector+tmapti_sector, 8 + tmap*4) + 4;
         }
         for (tmap = 0; tmap < tsi.num_tmaps; ++tmap) {
            tsi.tmaps[tmap].end_offset = tsi.tmaps[tmap].offset + (disc.GetDword(tsi.vts_ifo_sector, tsi.tmaps[tmap].offset - 4) & 65535) * 4;
         }
      }
      if (c_adt_sector) {
         tsi.vts_c_adt_offset = c_adt_sector*2048 + 8;
         tsi.vts_c_adt_end_offset = tsi.vts_c_adt_offset - 7 + disc.GetDword(tsi.vts_ifo_sector, tsi.vts_c_adt_offset - 4);
      }
      if (vobu_admap_sector) {
         tsi.vts_vobu_admap_offset = vobu_admap_sector*2048 + 4;
         tsi.vts_vobu_admap_end_offset = tsi.vts_vobu_admap_offset - 3 + disc.GetDword(tsi.vts_ifo_sector, tsi.vts_vobu_admap_offset - 4);
      }
   }
   di.disc_id = disc.GetCumulativeCRC();
   DiscInfo* pdi = (DiscInfo*)bay->vtable->SharedPool_Alloc(bay, sizeof(DiscInfo));
   *pdi = di;
   return pdi;
}


void PrintDiscInfo(DiscInfo* di) {
   printf("di->vmg_ifo_sector = %X\n", di->vmg_ifo_sector);
   printf("di->vmg_vobs_sector = %X\n", di->vmg_vobs_sector);
   printf("di->vmg_bup_sector = %X\n", di->vmg_bup_sector);
   printf("di->vmg_tt_srpt_offset = %X\n", di->vmg_tt_srpt_offset);
   printf("di->vmg_tt_srpt_end_offset = %X\n", di->vmg_tt_srpt_end_offset);
   printf("di->num_title_sets = %X\n", di->num_title_sets);
   for (unsigned i=0; i<di->num_title_sets; ++i) {
      printf("di->titlesets[%d].vts_ifo_sector = %X\n", i, di->titlesets[i].vts_ifo_sector);
      printf("di->titlesets[%d].vtsm_vobs_sector = %X\n", i, di->titlesets[i].vtsm_vobs_sector);
      printf("di->titlesets[%d].vts_vobs_sector = %X\n", i, di->titlesets[i].vts_vobs_sector);
      printf("di->titlesets[%d].vts_bup_sector = %X\n", i, di->titlesets[i].vts_bup_sector);
      printf("di->titlesets[%d].number_of_existing_subpicture_tracks = %X\n", i, di->titlesets[i].number_of_existing_subpicture_tracks);
      printf("di->titlesets[%d].vts_c_adt_offset = %X\n", i, di->titlesets[i].vts_c_adt_offset);
      printf("di->titlesets[%d].vts_c_adt_end_offset = %X\n", i, di->titlesets[i].vts_c_adt_end_offset);
      printf("di->titlesets[%d].vts_vobu_admap_offset = %X\n", i, di->titlesets[i].vts_vobu_admap_offset);
      printf("di->titlesets[%d].vts_vobu_admap_end_offset = %X\n", i, di->titlesets[i].vts_vobu_admap_end_offset);
      printf("di->titlesets[%d].num_pgcs = %X\n", i, di->titlesets[i].num_pgcs);
      printf("di->titlesets[%d].num_tmaps = %X\n", i, di->titlesets[i].num_tmaps);
      unsigned j;
      for (j=0; j<di->titlesets[i].num_pgcs; ++j) {
         printf("di->titlesets[%d].pgcs[%d].subpicture_status_offset = %X\n", i, j, di->titlesets[i].pgcs[j].subpicture_status_offset);
         printf("di->titlesets[%d].pgcs[%d].cell_playback_info_table_offset = %X\n", i, j, di->titlesets[i].pgcs[j].cell_playback_info_table_offset);
         printf("di->titlesets[%d].pgcs[%d].cell_playback_info_table_end_offset = %X\n", i, j, di->titlesets[i].pgcs[j].cell_playback_info_table_end_offset);
      }
      for (j=0; j<di->titlesets[i].num_tmaps; ++j) {
         printf("di->titlesets[%d].tmaps[%d].offset = %X\n", i, j, di->titlesets[i].tmaps[j].offset);
         printf("di->titlesets[%d].tmaps[%d].end_offset = %X\n", i, j, di->titlesets[i].tmaps[j].end_offset);
      }
   }
};


/********************************************************************
********************************************************************/


class SubpictureReceiver : public ICompilerCallbacks, public IScannerCallbacks {
   CompileDialog* const compile_dialog;
   DVDSubberKernel* const k;
   DvsDockingBay* const bay;
//   const unsigned char* const map_data;
//   unsigned const map_len;
   HANDLE const hdatafile;
   unsigned datafilepos;
   SubpictureInfo** psi;
   int angle;
   bool got_title, got_angle;
   unsigned numerator, denominator;
   bool got_warning;

   unsigned char* map_data;
   unsigned map_pos, map_len;

   unsigned num_vobus;

   void LookupField(unsigned field, unsigned angle, bool ntsc, unsigned* plba, unsigned* pptm);
   void Error(const char* msg, const char* fmt, int value);

   void SubpictureReceiver::GrowMap();

public:
   SubpictureReceiver(CompileDialog* _compile_dialog, DVDSubberKernel* _k, DvsDockingBay* _bay, HANDLE _hdatafile)
      : compile_dialog(_compile_dialog), k(_k), bay(_bay), hdatafile(_hdatafile)
   {
      datafilepos = 0;
      psi = &k->subpic_inf;
      k->title = 0; angle = 1;
      got_title = false; got_angle = false;
      numerator = 0; denominator = 1;
      got_warning = false;
      map_data = 0;
      k->num_subpics = 0;
      k->palette_size = 0;
   }

   bool UserAborted();
   bool GotWarning() { return got_warning; }

   void NotifySubpictureCount(unsigned num_subpictures);
   void NotifyDoneParsing();
   bool IsNTSC();
   void AddSubpicture(unsigned base_field, const unsigned char* data);
   int  ColorLookup(unsigned rgb);
   void SetVTSNumber(int vts_number);
   void SetAngle(int angle);

   bool ReadSector(unsigned lba, unsigned char* buf);
   void AddVOBU(unsigned lba, unsigned vobu_number, unsigned num_fields, unsigned num_data_blocks);
   void ChangePTM(unsigned new_ptm);
   void ChangeAngle(unsigned new_angle);

   void Note(const char* msg);
   void Warning(const char* msg);
   void ErrorAtLine(const char* msg, int line);
   void ErrorAtTime(const char* msg, unsigned field);
   void ErrorAtLBA(const char* msg, unsigned lba);
};


void SubpictureReceiver::LookupField(unsigned field, unsigned angle, bool ntsc, unsigned* plba, unsigned* pptm) {
   const unsigned char* p = map_data;
   const unsigned char* end = map_data + map_len;
   unsigned base_ptm = 0, base_field = 0, cur_field = 0, cur_sector = 0, cur_angle = 0;
   while (p < end) {
      unsigned char ch = *p++;
      if (ch < 0xF0 || ch == 0xFE) {
         unsigned fields, intervening_sectors;
         if (ch < 0xF0) {
            fields = ch >> 2;
            intervening_sectors = (ch&3) * 256 + (*p++);
         } else {
            fields = p[0]*256 + p[1];
            intervening_sectors = p[2]*256 + p[3];
            p += 4;
         }
         if (cur_angle==0 || cur_angle==angle) {
            cur_field += fields;
            if (cur_field > field) {
               *plba = cur_sector + 2;
               *pptm = base_ptm + (field-base_field) * (ntsc?3003:3600) / 2;
               return;
            }
         }
         cur_sector += intervening_sectors+1;
      } else if (ch == 0xFF) {
         if (cur_angle==0 || cur_angle==angle) {
            base_field = cur_field;
            base_ptm = 0;
            for (int i=0; i<4; ++i) base_ptm = base_ptm*256 + (*p++);
         } else {
            p += 4;
         }
      } else {
         cur_angle = ch & 15;
      }
   }
   // this is caught in DVDSubber-compile.cpp; not really kosher
   throw "Field number too large";
}


void SubpictureReceiver::NotifySubpictureCount(unsigned num_subpictures) {
   denominator = num_subpictures;
}


void SubpictureReceiver::NotifyDoneParsing() {
   char map_file[MAX_PATH+32];
   wsprintf(map_file, "%sdvdsub_%08x_%x.map",
      g_bays->GetDvdsynthDirectory(),
      k->disc_info->disc_id, k->title);

   HANDLE hmapfile = CreateFile(map_file, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
   if (hmapfile != INVALID_HANDLE_VALUE) {
      map_len = GetFileSize(hmapfile, NULL);
      map_data = new unsigned char[map_len];
      DWORD read;
      ReadFile(hmapfile, map_data, map_len, &read, NULL);
      CloseHandle(hmapfile);
   } else {
      hmapfile = CreateFile(map_file, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
      if (hmapfile != INVALID_HANDLE_VALUE) {
         map_len = 10000;
         map_pos = 0;
         map_data = new unsigned char[map_len];
         const TitleSetInfo& tsi = k->disc_info->titlesets[k->title];
         unsigned vts_vobs_lba = tsi.vts_vobs_sector;
         unsigned vobu_admap_lba = tsi.vts_ifo_sector + (tsi.vts_vobu_admap_offset >> 11);
         num_vobus = (tsi.vts_vobu_admap_end_offset - tsi.vts_vobu_admap_offset) >> 2;
         if (Scan(vobu_admap_lba, num_vobus, vts_vobs_lba, this)) {
            map_len = map_pos;
            DWORD written;
            WriteFile(hmapfile, map_data, map_pos, &written, NULL);
            CloseHandle(hmapfile);
         } else {
            CloseHandle(hmapfile);
            DeleteFile(map_file);
            throw 0;
         }
      } else {
         Error("Could not open the cache file", " (\"%s\")", (int)map_file);
         throw 0;
      }
   }
}


bool SubpictureReceiver::UserAborted() {
   MSG msg;
   while (PeekMessage(&msg, NULL, 0, 0, TRUE)) {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
   }
   return compile_dialog->ButtonPressed();
}


bool SubpictureReceiver::IsNTSC() {
   return k->disc_info->titlesets[k->title].ntsc;
}


void SubpictureReceiver::AddSubpicture(unsigned base_field, const unsigned char* data) {
   if (*psi == 0) {
      *psi = (SubpictureInfo*)bay->vtable->SharedPool_Alloc(bay, sizeof(SubpictureInfo));
      (*psi)->next = 0;
   }
   SubpictureInfo* si = *psi;
   psi = &si->next;

   unsigned sector;
   LookupField(base_field, angle, true, &sector, &si->ptm);
   si->hard_lba = sector + k->disc_info->titlesets[k->title].vts_vobs_sector;
   si->file_offset = datafilepos;
   unsigned data_len = data[0]*256+data[1];
   si->data_len = data_len;
   si->num_sectors = (data_len + (rest_data_packet_len-first_data_packet_len) + (rest_data_packet_len-1)) / rest_data_packet_len;
   DWORD written;
   if (!WriteFile(hdatafile, data, data_len, &written, NULL) || written != data_len)
      throw "Unable to write temporary file -- the disk may be full";
   datafilepos += data_len;
   ++k->num_subpics;

⌨️ 快捷键说明

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