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

📄 vobsub.cpp

📁 从FFMPEG转换而来的H264解码程序,VC下编译..
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    if (vobsub_ensure_spu_stream( index) < 0)
        return PARSE_ERROR;
    if (id && idlen) {
        if (spu_streams[index].id)
            free(spu_streams[index].id);
        spu_streams[index].id = (char_t*)calloc(idlen + 1,sizeof(char_t));
        if (spu_streams[index].id == NULL) {
            DPRINTF(_l("vobsub_add_id: malloc failure"));
            return PARSE_ERROR;
        }
        //memcpy(spu_streams[index].id, id, idlen)
        //spu_streams[index].id[idlen] = 0;
        text<char_t>(id, idlen, spu_streams[index].id, idlen + 1);//strncpy(spu_streams[index].id,id,idlen);// ;
    }
    spu_streams_current = index;
    DPRINTF(_l("[vobsub] subtitle (vobsubid): %d language %s"),index, spu_streams[index].id);
    return PARSE_OK;
}

Tvobsub::PARSE_RES Tvobsub::vobsub_add_altid( const char *id, size_t idlen)
{
    if (spu_streams == 0) {
        DPRINTF(_l("[vobsub] warning, binning some index entries.  Check your index file"));
        return PARSE_ERROR;
    }
    packet_queue_t *queue = spu_streams + spu_streams_current;
    if (queue->altid) free(queue->altid);
    queue->altid=(char_t*)calloc(idlen+1,sizeof(char_t));
    //memcpy(queue->altid,id,idlen);
    //queue->altid[idlen]='\0';
    text<char_t>(id, idlen, queue->altid, idlen + 1);
    return PARSE_OK;
}

Tvobsub::PARSE_RES Tvobsub::vobsub_add_timestamp( long filepos, int ms)
{
    packet_queue_t *queue;
    packet_t *pkt;
    if (spu_streams == 0) {
        DPRINTF(_l("[vobsub] warning, binning some index entries.  Check your index file"));
        return PARSE_ERROR;
    }
    queue = spu_streams + spu_streams_current;
    if (queue->packet_queue_grow() >= 0) {
        pkt = queue->packets + (queue->packets_size - 1);
        pkt->filepos = filepos;
        pkt->pts100 = ms < 0 ? UINT_MAX : (unsigned int)ms * 90;
        return PARSE_OK;
    }
    return PARSE_ERROR;
}

Tvobsub::PARSE_RES Tvobsub::vobsub_parse_id(const char *line)
{
    // id: xx, index: n
    size_t idlen;
    const char *p, *q;
    p  = line;
    while (isspace(*p))
        ++p;
    q = p;
    while (isalpha(*q))
        ++q;
    idlen = q - p;
    if (idlen == 0)
        return PARSE_ERROR;
    ++q;
    while (isspace(*q))
        ++q;
    if (strncmp("index:", q, 6))
        return PARSE_ERROR;
    q += 6;
    while (isspace(*q))
        ++q;
    if (!isdigit(*q))
        return PARSE_ERROR;
    return vobsub_add_id(p, idlen, atoi(q));
}

Tvobsub::PARSE_RES Tvobsub::vobsub_parse_altid(const char *line)
{
    // id: xx, index: n
    size_t idlen;
    const char *p, *q;
    p  = line;
    while (isspace(*p))
        ++p;
    q = p;
    while (*q && *q!='\n')
        ++q;
    idlen = q - p;
    if (idlen == 0)
        return PARSE_ERROR;
    return vobsub_add_altid(p, idlen);
}

Tvobsub::PARSE_RES Tvobsub::vobsub_parse_timestamp(const char *line)
{
    // timestamp: HH:MM:SS.mmm, filepos: 0nnnnnnnnn
    int ms;
    const char *p=parseTimestamp(line,ms);
    if (!p)
        return PARSE_ERROR;
    if (*p != ',')
        return PARSE_ERROR;
    line = p + 1;
    while (isspace(*line))
        ++line;
    if (strncmp("filepos:", line, 8))
        return PARSE_ERROR;
    line += 8;
    while (isspace(*line))
        ++line;
    if (! isxdigit(*line))
        return PARSE_ERROR;
    long filepos = strtol(line, NULL, 16);
    return vobsub_add_timestamp(filepos, delay + ms/* + 1000 * (s + 60 * (m + 60 * h))*/);
}

/* don't know how to use tridx */
Tvobsub::PARSE_RES Tvobsub::vobsub_set_lang(const char *line)
{
    if (vobsub_id == -1)
        vobsub_id = atoi(line + 8);
    return PARSE_OK;
}

Tvobsub::PARSE_RES Tvobsub::idx_parse_one_line(const char *line)
{
 if (strncmp("langidx:", line, 8) == 0)
  return vobsub_set_lang(line);
 else if (strncmp("id:", line, 3) == 0)
  return vobsub_parse_id( line + 3);
 else if (strncmp("alt:", line, 4) == 0)
  return vobsub_parse_altid( line + 4);
 else if (strncmp("timestamp:", line, 10) == 0)
  return vobsub_parse_timestamp( line + 10);
 else
  return TsubtitleDVDparent::idx_parse_one_line(line);
}

Tvobsub::Tvobsub(Tstream &fd,const char_t *const name,const char_t *const ifo,const int force,Tspudec* *spu,IffdshowBase *deci)
{
 deci->getConfig(&config);
 ok=false;
 if(spu)
   *spu = NULL;
 char_t *buf;
 spu_streams = NULL;
 spu_streams_size = 0;
 spu_streams_current = 0;
 vobsub_id=-1;
 delay = 0;
 forced_subs=0;
 buf = (char_t*)malloc((strlen(name) + 5) * sizeof(char_t));
 if (buf)
  {
   idx_parse(fd);
   /* if no palette in .idx then use custom colors */
   if ((custom_colors == 0)&&(fsppal!=1))
    custom_colors = 1;
   if (spu && rectOrig.dx && rectOrig.dy)
    *spu = new Tspudec(deci,sppal, cuspal, custom_colors, rectOrig.dx, rectOrig.dy);

   /* read the indexed mpeg_stream */
   strcpy(buf, name);
   strcat(buf, _l(".sub"));
   mpeg_t *mpg = mpeg_open(buf);
   if (mpg == NULL)
    {
     if(force)
      DPRINTF(_l("VobSub: Can't open SUB file"));
     else
      {
       free(buf);
       //free(vob);
       return /*NULL*/;
      }
    }
   else
    {
     long last_pts_diff = 0;
     while (!mpeg_eof(mpg))
      {
       long pos = mpeg_tell(mpg);
       if (mpeg_run(mpg) < 0)
        {
         if (!mpeg_eof(mpg))
          DPRINTF(_l("VobSub: mpeg_run error"));
         break;
        }
       if (mpg->packet_size)
        {
         if ((mpg->aid & 0xe0) == 0x20)
          {
           unsigned int sid = mpg->aid & 0x1f;
           if (vobsub_ensure_spu_stream(sid) >= 0)
            {
             packet_queue_t *queue = spu_streams + sid;
             //get the packet to fill
             if (queue->packets_size == 0 && queue->packet_queue_grow()  < 0)
              return;
             while (queue->current_index + 1 < queue->packets_size && queue->packets[queue->current_index + 1].filepos <= pos)
              ++queue->current_index;
             if (queue->current_index < queue->packets_size)
              {
               packet_t *pkt;
               if (queue->packets[queue->current_index].data)
                {
                 // insert a new packet and fix the PTS !
                 queue->packet_queue_insert();
                 queue->packets[queue->current_index].pts100 = mpg->pts + last_pts_diff;
                }
               pkt = queue->packets + queue->current_index;
               if (pkt->pts100 != UINT_MAX)
                {
                 if (queue->packets_size > 1)
                  last_pts_diff = pkt->pts100 - mpg->pts;
                 else
                  pkt->pts100 = mpg->pts;
                 // FIXME: should not use mpg_sub internal informations, make a copy
                 pkt->data = mpg->packet;
                 pkt->size = mpg->packet_size;
                 mpg->packet = NULL;
                 mpg->packet_reserve = 0;
                 mpg->packet_size = 0;
                }
              }
            }
          }
        }
      }
     spu_streams_current = spu_streams_size;
     while (spu_streams_current-- > 0)
      spu_streams[spu_streams_current].current_index = 0;
     mpeg_free(mpg);
    }
   free(buf);
  }
 ok=true;
}

Tvobsub::~Tvobsub()
{
    if (spu_streams) {
        while (spu_streams_size--)
            (spu_streams + spu_streams_size)->packet_queue_destroy();
        free(spu_streams);
    }
}

unsigned int Tvobsub::vobsub_get_indexes_count(void)
{
    return spu_streams_size;
}

char_t* Tvobsub::vobsub_get_id( unsigned int index)
{
    return (index < spu_streams_size) ? spu_streams[index].id : NULL;
}

unsigned int Tvobsub::vobsub_get_forced_subs_flag(void)
{
    return forced_subs;
}
/*
int Tvobsub::vobsub_set_from_lang(const char * lang)
{
    unsigned int i;
    while(lang && strlen(lang) >= 2){
      for(i=0; i < spu_streams_size; i++)
        if (spu_streams[i].id)
          if ((strncmp(spu_streams[i].id, lang, 2)==0)){
            vobsub_id=i;
            DPRINTF( _l("Selected VOBSUB language: %d language: %s"), i, text<char_t>(spu_streams[i].id));
            return 0;
          }
      lang+=2;while (lang[0]==',' || lang[0]==' ') ++lang;
    }
    DPRINTF(_l("No matching VOBSUB language found!"));
    return -1;
}
*/
int Tvobsub::vobsub_get_packet(unsigned int pts,void** data, int* timestamp) {
  unsigned int pts100 = (unsigned int)pts;//(90000 * pts);
  if (spu_streams && 0 <= vobsub_id && (unsigned) vobsub_id < spu_streams_size) {
    packet_queue_t *queue = spu_streams + vobsub_id;
    while (queue->current_index < queue->packets_size) {
      packet_t *pkt = queue->packets + queue->current_index;
      if (pkt->pts100 != UINT_MAX)
      if (pkt->pts100 <= pts100) {
        ++queue->current_index;
        *data = pkt->data;
        *timestamp = pkt->pts100;
        return pkt->size;
      } else break;
      else
          ++queue->current_index;
    }
  }
  return -1;
}

int Tvobsub::vobsub_get_next_packet( void** data, int* timestamp)
{
  if (spu_streams && 0 <= vobsub_id && (unsigned) vobsub_id < spu_streams_size) {
    packet_queue_t *queue = spu_streams + vobsub_id;
    if (queue->current_index < queue->packets_size) {
      packet_t *pkt = queue->packets + queue->current_index;
      ++queue->current_index;
      *data = pkt->data;
      *timestamp = pkt->pts100;
      return pkt->size;
    }
  }
  return -1;
}

void Tvobsub::vobsub_seek(int pts)
{
  packet_queue_t * queue;
  unsigned int seek_pts100 = (int)pts;// * 90000;

  if (spu_streams && 0 <= vobsub_id && (unsigned) vobsub_id < spu_streams_size) {
    /* do not seek if we don't know the id */
    if (vobsub_get_id(vobsub_id) == NULL)
            return;
    queue = spu_streams + vobsub_id;
    queue->current_index = 0;
    while ((queue->packets + queue->current_index)->pts100 < seek_pts100)
      ++queue->current_index;
    if (queue->current_index > 0)
      --queue->current_index;
  }
}

void Tvobsub::vobsub_reset(void)
{
    if (spu_streams) {
        unsigned int n = spu_streams_size;
        while (n-- > 0)
            spu_streams[n].current_index = 0;
    }
}

⌨️ 快捷键说明

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