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

📄 spdif_wrapper.cpp

📁 ac3的解码程序
💻 CPP
字号:
#include <stdio.h>
#include "spdif_header.h"
#include "spdif_wrapper.h"

#include "../../bitstream.h"
#include "../mpa/mpa_header.h"
#include "../ac3/ac3_header.h"
#include "../dts/dts_header.h"

#define MAX_SPDIF_FRAME_SIZE 8192


inline bool is_14bit(int bs_type)
{
  return (bs_type == BITSTREAM_14LE) || (bs_type == BITSTREAM_14BE);
}


SPDIFWrapper::SPDIFWrapper(int _dts_mode, int _dts_conv)
:dts_mode(_dts_mode), dts_conv(_dts_conv), spdif_parser(false)
{
  const HeaderParser *parsers[] = { &spdif_header, &mpa_header, &ac3_header, &dts_header };
  spdifable.set_parsers(parsers, array_size(parsers));
  buf = new uint8_t[MAX_SPDIF_FRAME_SIZE];
}

SPDIFWrapper::~SPDIFWrapper()
{
  safe_delete(buf);
}

///////////////////////////////////////////////////////////////////////////////
// FrameParser overrides

const HeaderParser *
SPDIFWrapper::header_parser() const
{
  return &spdifable;
}

void 
SPDIFWrapper::reset()
{
  hdr.drop();
  spdif_parser.reset();

  spk = spk_unknown;
  spdif_frame = 0;
  spdif_size = 0;
}

bool
SPDIFWrapper::parse_frame(uint8_t *frame, size_t size)
{
  spdif_frame = 0;
  spdif_size = 0;

  /////////////////////////////////////////////////////////
  // Determine frame's characteristics

  if (!spdifable.parse_header(frame, &hdr))
    // unknown format
    return false;

  if (!hdr.spdif_type)
  {
    // passthrough non-spdifable format
    spk = hdr.spk;
    spdif_frame = frame;
    spdif_size = size;
    return true;
  }

  /////////////////////////////////////////////////////////
  // Parse spdif input if nessesary

  uint8_t *raw_frame;
  size_t raw_size;

  if (hdr.spk.format == FORMAT_SPDIF)
  {
    if (!spdif_parser.parse_frame(frame, size))
      // cannot parse spdif frame
      return false;

    hdr = spdif_parser.header_info();
    raw_frame = spdif_parser.get_rawdata();
    raw_size = spdif_parser.get_rawsize();
  }
  else
  {
    raw_frame = frame;
    raw_size = size;
  }
  
  /////////////////////////////////////////////////////////
  // SPDIF frame size

  size_t spdif_frame_size = hdr.nsamples * 4;
  if (spdif_frame_size > MAX_SPDIF_FRAME_SIZE)
  {
    // impossible to send over spdif
    // passthrough non-spdifable data
    spk = hdr.spk;
    spdif_frame = raw_frame;
    spdif_size = raw_size;
    return true;
  }

  /////////////////////////////////////////////////////////
  // Determine output bitstream type and header usage

  if (hdr.spk.format == FORMAT_DTS)
  {
    // DTS frame may grow if conversion to 14bit stream format is used
    bool frame_grows = (dts_conv == DTS_CONV_14BIT) && !is_14bit(hdr.bs_type);
    // DTS frame may shrink if conversion to 16bit stream format is used
    bool frame_shrinks = (dts_conv == DTS_CONV_16BIT) && is_14bit(hdr.bs_type);

    switch (dts_mode)
    {
    case DTS_MODE_WRAPPED:
      use_header = true;
      if (frame_grows && (raw_size * 8 / 7 <= spdif_frame_size - sizeof(spdif_header_s)))
        spdif_bs = BITSTREAM_14LE;
      else if (frame_shrinks && (raw_size * 7 / 8 <= spdif_frame_size - sizeof(spdif_header_s)))
        spdif_bs = BITSTREAM_16LE;
      else if (raw_size <= spdif_frame_size - sizeof(spdif_header_s))
        spdif_bs = is_14bit(hdr.bs_type)? BITSTREAM_14LE: BITSTREAM_16LE;
      else
      {
        // impossible to wrap
        // passthrough non-spdifable data
        spk = hdr.spk;
        spdif_frame = raw_frame;
        spdif_size = raw_size;
        return true;
      }
      break;

    case DTS_MODE_PADDED:
      use_header = false;
      if (frame_grows && (raw_size * 8 / 7 <= spdif_frame_size))
        spdif_bs = BITSTREAM_14LE;
      else if (frame_shrinks && (raw_size * 7 / 8 <= spdif_frame_size))
        spdif_bs = BITSTREAM_16LE;
      else if (raw_size <= spdif_frame_size)
        spdif_bs = is_14bit(hdr.bs_type)? BITSTREAM_14LE: BITSTREAM_16LE;
      else
      {
        // impossible to send over spdif
        // passthrough non-spdifable data
        spk = hdr.spk;
        spdif_frame = raw_frame;
        spdif_size = raw_size;
        return true;
      }
      break;

    case DTS_MODE_AUTO:
    default:
      if (frame_grows && (raw_size * 8 / 7 <= spdif_frame_size - sizeof(spdif_header_s)))
      {
        use_header = true;
        spdif_bs = BITSTREAM_14LE;
      }
      else if (frame_grows && (raw_size * 8 / 7 <= spdif_frame_size))
      {
        use_header = false;
        spdif_bs = BITSTREAM_14LE;
      }
      if (frame_shrinks && (raw_size * 7 / 8 <= spdif_frame_size - sizeof(spdif_header_s)))
      {
        use_header = true;
        spdif_bs = BITSTREAM_14LE;
      }
      else if (frame_shrinks && (raw_size * 7 / 8 <= spdif_frame_size))
      {
        use_header = false;
        spdif_bs = BITSTREAM_14LE;
      }
      else if (raw_size <= spdif_frame_size - sizeof(spdif_header_s))
      {
        use_header = true;
        spdif_bs = is_14bit(hdr.bs_type)? BITSTREAM_14LE: BITSTREAM_16LE;
      }
      else if (raw_size <= spdif_frame_size)
      {
        use_header = false;
        spdif_bs = is_14bit(hdr.bs_type)? BITSTREAM_14LE: BITSTREAM_16LE;
      }
      else
      {
        // impossible to send over spdif
        // passthrough non-spdifable data
        spk = hdr.spk;
        spdif_frame = raw_frame;
        spdif_size = raw_size;
        return true;
      }
      break;
    }
  }
  else
  {
    if (raw_size <= spdif_frame_size - sizeof(spdif_header_s))
    {
      use_header = true;
      spdif_bs = BITSTREAM_16LE;
    }
    else
    {
      // impossible to wrap
      // passthrough non-spdifable data
      spk = hdr.spk;
      spdif_frame = raw_frame;
      spdif_size = raw_size;
      return true;
    }
  }

  /////////////////////////////////////////////////////////
  // Fill payload, convert bitstream type and init header

  size_t payload_size;
  if (use_header)
  {
    payload_size = bs_convert(raw_frame, raw_size, hdr.bs_type, buf + sizeof(spdif_header_s), spdif_bs);
    assert(payload_size < MAX_SPDIF_FRAME_SIZE - sizeof(spdif_header_s));
    memset(buf + sizeof(spdif_header_s) + payload_size, 0, spdif_frame_size - sizeof(spdif_header_s) - payload_size);

    // We must correct DTS synword when converting to 14bit
    if (spdif_bs == BITSTREAM_14LE)
      buf[sizeof(spdif_header_s) + 3] = 0xe8;

    spdif_header_s *header = (spdif_header_s *)buf;
    header->set(hdr.spdif_type, payload_size * 8);
  }
  else
  {
    payload_size = bs_convert(raw_frame, raw_size, hdr.bs_type, buf, spdif_bs);
    assert(payload_size < MAX_SPDIF_FRAME_SIZE);
    memset(buf + payload_size, 0, spdif_frame_size - payload_size);

    // We must correct DTS synword when converting to 14bit
    if (spdif_bs == BITSTREAM_14LE)
      buf[3] = 0xe8;
  }

  if (!payload_size)
    // cannot convert bitstream
    return false;

  /////////////////////////////////////////////////////////
  // Send spdif frame

  spk = hdr.spk;
  spk.format = FORMAT_SPDIF;
  spdif_frame = buf;
  spdif_size = spdif_frame_size;

  return true;
}

size_t
SPDIFWrapper::stream_info(char *buf, size_t size) const 
{
  char info[1024];
  size_t len = 0;

  char *bitstream = "???";
  switch (spdif_bs)
  {
    case BITSTREAM_16BE: bitstream = "16bit BE"; break;
    case BITSTREAM_16LE: bitstream = "16bit LE"; break;
    case BITSTREAM_14BE: bitstream = "14bit BE"; break;
    case BITSTREAM_14LE: bitstream = "14bit LE"; break;
  }

  if (!spk.is_unknown())
  {
    len += sprintf(info,
      "Output format: %s %s %iHz\n"
      "SPDIF format: %s\n"
      "Bitstream: %s\n"
      "Frame size: %i\n",
      spk.format_text(), spk.mode_text(), spk.sample_rate,
      use_header? "wrapped": "padded",
      bitstream,
      spdif_size);
  }

  if (len + 1 > size) len = size - 1;
  memcpy(buf, info, len + 1);
  buf[len] = 0;
  return len;
}

size_t
SPDIFWrapper::frame_info(char *buf, size_t size) const 
{
  if (buf && size) buf[0] = 0;
  return 0;
}

⌨️ 快捷键说明

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