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

📄 cc_decoder.cpp

📁 从FFMPEG转换而来的H264解码程序,VC下编译..
💻 CPP
字号:
/*
 * Copyright (C) 2000-2003 the xine project
 *
 * Copyright (C) Christian Vogler
 *               cvogler@gradient.cis.upenn.edu - December 2001
 *
 * This file is part of xine, a free video player.
 *
 * xine 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.
 *
 * xine 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Some small bits and pieces of the EIA-608 captioning decoder were
 * adapted from CCDecoder 0.9.1 by Mike Baker. The latest version is
 * available at http://sourceforge.net/projects/ccdecoder/.
 */

#include "stdafx.h"
#include "cc_decoder.h"
#include "ffdebug.h"
#include "IffdshowDecVideo.h"

char TccDecoder::chartbl[128];

int TccDecoder::good_parity(uint16_t data)
{
 struct Tparity
  {
  private:
   static int parity(uint8_t byte)
    {
     int ones = 0;
     for (int i = 0; i < 7; i++)
      if (byte & (1 << i))
       ones++;
     return ones & 1;
    }
  public:
   int table[256];
   Tparity(void)
    {
     for (uint8_t byte = 0; byte <= 127; byte++)
      {
       int parity_v = parity(byte);
       /* CC uses odd parity (i.e., # of 1's in byte is odd.) */
       table[byte] = parity_v;
       table[byte | 0x80] = !parity_v;
      }
    }
  };
 static const Tparity parity;
 int ret = parity.table[data & 0xff] && parity.table[(data & 0xff00) >> 8];
 if (!ret)
  DPRINTFA("Bad parity in EIA-608 data (%x)\n", data);
 return ret;
}

TccDecoder::cc_buffer_t* TccDecoder::active_ccbuffer(void)
{
 cc_memory_t *mem=*this->active;
 return &mem->channel[mem->channel_no];
}

void TccDecoder::cc_row_t::ccrow_fill_transp(void)
{
 for (int i = this->num_chars; i < this->pos; i++)
  {
   this->cells[i].c = TRANSP_SPACE;
   this->cells[i].midrow_attr = 0;
  }
}

int TccDecoder::cc_row_t::ccrow_find_next_text_part(int pos)
{
 while (pos < this->num_chars && this->cells[pos].c == TRANSP_SPACE)
   pos++;
 return pos;
}

int TccDecoder::cc_row_t::ccrow_find_end_of_text_part(int pos)
{
  while (pos < this->num_chars && this->cells[pos].c != TRANSP_SPACE)
    pos++;
  return pos;
}

int TccDecoder::cc_row_t::ccrow_find_current_attr(int pos)
{
  while (pos > 0 && !this->cells[pos].midrow_attr)
    pos--;
  return pos;
}

int TccDecoder::cc_row_t::ccrow_find_next_attr_change(int pos, int lastpos)
{
  pos++;
  while (pos < lastpos && !this->cells[pos].midrow_attr)
    pos++;
  return pos;
}

bool TccDecoder::cc_row_t::ccrow_render(cc_renderer_t *renderer, int rownum)
{
 bool was=false;
 int pos = ccrow_find_next_text_part(0);
 while (pos < this->num_chars) {
    int endpos = ccrow_find_end_of_text_part(pos);
    int seg_begin = pos;

    //int seg_pos[CC_COLUMNS + 1];seg_pos[0] = seg_begin;
    //int cumulative_seg_width[CC_COLUMNS + 1];cumulative_seg_width[0] = 0;
    char buf[CC_COLUMNS + 1];
    //int seg_attr[CC_COLUMNS];int num_seg = 0;

    while (seg_begin < endpos) {
      int attr_pos = ccrow_find_current_attr(seg_begin);
      int seg_end = ccrow_find_next_attr_change(seg_begin, endpos);

      /* compute text size of segment */
      for (int i = seg_begin; i < seg_end; i++)
	buf[i - seg_begin] = this->cells[i].c;
      buf[seg_end - seg_begin] = '\0';

      const cc_attribute_t *attr = &this->cells[attr_pos].attributes;
      char sub[CC_COLUMNS*2]="";
      if (attr->italic) strcat(sub,"<i>");
      if (attr->underline) strcat(sub,"<u>");
      strcat(sub,buf);
      if (attr->italic) strcat(sub,"</i>");
      if (attr->underline) strcat(sub,"</u>");
      renderer->deciV->addClosedCaption(sub);
      was=true;
      //ccrow_set_attributes(renderer, this, attr_pos);
      //osd_renderer->get_text_size(renderer->cap_display, buf, &seg_w, &seg_h);

      /* update cumulative segment statistics */
      //text_w += seg_w;
      //text_h += seg_h;
      //seg_pos[num_seg + 1] = seg_end;
      //seg_attr[num_seg] = attr_pos;
      //cumulative_seg_width[num_seg + 1] = text_w;
      //num_seg++;

      seg_begin = seg_end;
    }

    //renderer->deciV->shortOSDmessage(buf+pos,
    pos = ccrow_find_next_text_part(endpos);
 }
 return was;
}

void TccDecoder::cc_buffer_t::ccbuf_add_char(uint8_t c)
{
  cc_row_t *rowbuf = &this->rows[this->rowpos];
  int pos = rowbuf->pos;
  int left_displayable = (pos > 0) && (pos <= rowbuf->num_chars);

#if LOG_DEBUG > 2
  printf("cc_decoder: ccbuf_add_char: %c @ %d/%d\n", c, this->rowpos, pos);
#endif

  if (pos >= CC_COLUMNS) {
    //printf("cc_decoder: ccbuf_add_char: row buffer overflow\n");
    return;
  }

  if (pos > rowbuf->num_chars) {
    /* fill up to indented position with transparent spaces, if necessary */
    rowbuf->ccrow_fill_transp();
  }

  /* midrow PAC attributes are applied only if there is no displayable */
  /* character to the immediate left. This makes the implementation rather */
  /* complicated, but this is what the EIA-608 standard specifies. :-( */
  if (rowbuf->pac_attr_chg && !rowbuf->attr_chg && !left_displayable) {
    rowbuf->attr_chg = 1;
    rowbuf->cells[pos].attributes = rowbuf->pac_attr;
#ifdef LOG_DEBUG
    printf("cc_decoder: ccbuf_add_char: Applying midrow PAC.\n");
#endif
  }

  rowbuf->cells[pos].c = c;
  rowbuf->cells[pos].midrow_attr = rowbuf->attr_chg;
  rowbuf->pos++;

  if (rowbuf->num_chars < rowbuf->pos)
    rowbuf->num_chars = rowbuf->pos;

  rowbuf->attr_chg = 0;
  rowbuf->pac_attr_chg = 0;
}

void TccDecoder::cc_buffer_t::ccbuf_set_cursor(int row, int column, int underline, int italics, int color)
{
 cc_row_t *rowbuf = &this->rows[row];
 cc_attribute_t attr;

 attr.italic = (uint8_t)italics;
 attr.underline = (uint8_t)underline;
 attr.foreground = (uint8_t)color;
 attr.background = BLACK;

 rowbuf->pac_attr = attr;
 rowbuf->pac_attr_chg = 1;

 this->rowpos = row;
 rowbuf->pos = column;
 rowbuf->attr_chg = 0;
}

void TccDecoder::cc_buffer_t::ccbuf_apply_attribute(cc_attribute_t *attr)
{
  cc_row_t *rowbuf = &this->rows[this->rowpos];
  int pos = rowbuf->pos;

  rowbuf->attr_chg = 1;
  rowbuf->cells[pos].attributes = *attr;
  /* A midrow attribute always counts as a space */
  ccbuf_add_char(chartbl[(unsigned int) ' ']);
}

void TccDecoder::cc_buffer_t::ccbuf_tab(int tabsize)
{
  cc_row_t *rowbuf = &this->rows[this->rowpos];
  rowbuf->pos += tabsize;
  if (rowbuf->pos > CC_COLUMNS) {
    rowbuf->pos = CC_COLUMNS;
    return;
  }
  /* tabs have no effect on pending PAC attribute changes */
}

int TccDecoder::cc_buffer_t::cc_buf_has_displayable(void)
{
  for (int i = 0; i < CC_ROWS; i++) {
    if (this->rows[i].num_chars > 0)
      return 1;
  }
  return 0;
}

void TccDecoder::cc_buffer_t::ccbuf_render(cc_renderer_t *renderer)
{
 bool wasrow=false;
  for (int row = 0; row < CC_ROWS; ++row) {
    if (this->rows[row].num_chars > 0)
      wasrow|=this->rows[row].ccrow_render(renderer, row);
    else
      if (wasrow)
       renderer->deciV->addClosedCaption("");
  }
}


void TccDecoder::cc_memory_t::ccmem_clear(void)
{
 memset(this, 0, sizeof (cc_memory_t));
}

void TccDecoder::cc_set_channel(int channel)
{
 (*this->active)->channel_no = channel;
}

void TccDecoder::cc_renderer_t::cc_renderer_show_caption(cc_buffer_t *buf, int64_t vpts)
{
#ifdef LOG_DEBUG
  printf("spucc: cc_renderer: show\n");
#endif

  if (this->displayed) {
    cc_renderer_hide_caption(vpts);
  //printf("spucc: cc_renderer: show: OOPS - caption was already displayed!\n");
  }

  //this->osd_renderer->clear(this->cap_display);
  buf->ccbuf_render(this);
  //this->osd_renderer->set_position(this->cap_display, this->x, this->y);
  //vpts = std::max(vpts, this->last_hide_vpts);
  //this->osd_renderer->show(this->cap_display, vpts);

  this->displayed = 1;
  //this->display_vpts = vpts;
}

void TccDecoder::cc_renderer_t::cc_renderer_hide_caption(int64_t vpts)
{
  if (this->displayed) {
    //this->osd_renderer->hide(this->cap_display, vpts);
    deciV->hideClosedCaptions();
    this->displayed = 0;
    //this->last_hide_vpts = vpts;
  }
}


void TccDecoder::cc_decode_PAC(int channel,  uint8_t c1, uint8_t c2)
{
  cc_buffer_t *buf;
  int row, column = 0;
  int underline, italics = 0, color;

  /* There is one invalid PAC code combination. Ignore it. */
  if (c1 == 0x10 && c2 > 0x5f)
    return;

  cc_set_channel(channel);
  buf = active_ccbuffer();

 static const int rowdata[] = {10, -1, 0, 1, 2, 3, 11, 12, 13, 14, 4, 5, 6, 7, 8, 9};
  row = rowdata[((c1 & 0x07) << 1) | ((c2 & 0x20) >> 5)];
  if (c2 & 0x10) {
    column = ((c2 & 0x0e) >> 1) * 4;   /* preamble indentation */
    color = WHITE;                     /* indented lines have white color */
  }
  else if ((c2 & 0x0e) == 0x0e) {
    italics = 1;                       /* italics, they are always white */
    color = WHITE;
  }
  else
    color = (c2 & 0x0e) >> 1;
  underline = c2 & 0x01;

#ifdef LOG_DEBUG
  printf("cc_decoder: cc_decode_PAC: row %d, col %d, ul %d, it %d, clr %d\n",
	 row, column, underline, italics, color);
#endif

  buf->ccbuf_set_cursor(row, column, underline, italics, color);
}

void TccDecoder::cc_decode_standard_char(uint8_t c1, uint8_t c2)
{
 cc_buffer_t *buf = active_ccbuffer();

 /* c1 always is a valid character */
 buf->ccbuf_add_char(chartbl[c1]);
 /* c2 might not be a printable character, even if c1 was */
 if (c2 & 0x60)
  buf->ccbuf_add_char(chartbl[c2]);
}

void TccDecoder::cc_decode_ext_attribute(int channel, uint8_t c1, uint8_t c2)
{
  cc_set_channel(channel);
}

void TccDecoder::cc_decode_special_char(int channel,  uint8_t c1, uint8_t c2)
{
 /* FIXME: do real TM */
 /* must be mapped as a music note in the captioning font */
  //static const char specialchar[] = {'

⌨️ 快捷键说明

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