コード例 #1
0
ファイル: xtr_wav.cpp プロジェクト: Rodeo314/mkvtoolnix
void
xtr_wavpack4_c::create_file(xtr_base_c *master,
                            KaxTrackEntry &track) {
  memory_cptr mpriv;

  init_content_decoder(track);

  KaxCodecPrivate *priv = FindChild<KaxCodecPrivate>(&track);
  if (priv)
    mpriv = decode_codec_private(priv);

  if (!priv || (2 > mpriv->get_size()))
    mxerror(boost::format(Y("Track %1% with the CodecID '%2%' is missing the \"codec private\" element and cannot be extracted.\n")) % m_tid % m_codec_id);
  memcpy(m_version, mpriv->get_buffer(), 2);

  xtr_base_c::create_file(master, track);

  m_channels = kt_get_a_channels(track);

  if ((0 != kt_get_max_blockadd_id(track)) && (0 != m_extract_blockadd_level)) {
    std::string corr_name = m_file_name;
    size_t pos            = corr_name.rfind('.');

    if ((std::string::npos != pos) && (0 != pos))
      corr_name.erase(pos + 1);
    corr_name += "wvc";

    try {
      m_corr_out = mm_write_buffer_io_c::open(corr_name, 5 * 1024 * 1024);
    } catch (mtx::mm_io::exception &ex) {
      mxerror(boost::format(Y("The file '%1%' could not be opened for writing: %2%.\n")) % corr_name % ex);
    }
  }
}
コード例 #2
0
ファイル: xtr_wav.cpp プロジェクト: Azpidatziak/mkvtoolnix
void
xtr_wav_c::create_file(xtr_base_c *master,
                       KaxTrackEntry &track) {
  init_content_decoder(track);

  int channels = kt_get_a_channels(track);
  int sfreq    = (int)kt_get_a_sfreq(track);
  int bps      = kt_get_a_bps(track);

  if (-1 == bps)
    mxerror(boost::format(Y("Track %1% with the CodecID '%2%' is missing the \"bits per second (bps)\" element and cannot be extracted.\n")) % m_tid % m_codec_id);

  xtr_base_c::create_file(master, track);

  memcpy(&m_wh.riff.id,      "RIFF", 4);
  memcpy(&m_wh.riff.wave_id, "WAVE", 4);
  memcpy(&m_wh.format.id,    "fmt ", 4);
  memcpy(&m_wh.data.id,      "data", 4);

  put_uint32_le(&m_wh.format.len,              16);
  put_uint16_le(&m_wh.common.wFormatTag,        1);
  put_uint16_le(&m_wh.common.wChannels,        channels);
  put_uint32_le(&m_wh.common.dwSamplesPerSec,  sfreq);
  put_uint32_le(&m_wh.common.dwAvgBytesPerSec, channels * sfreq * bps / 8);
  put_uint16_le(&m_wh.common.wBlockAlign,       4);
  put_uint16_le(&m_wh.common.wBitsPerSample,   bps);

  m_out->write(&m_wh, sizeof(wave_header));
}
コード例 #3
0
ファイル: xtr_ogg.cpp プロジェクト: CharlesLio/mkvtoolnix
void
xtr_oggbase_c::create_standard_file(xtr_base_c *master,
                                    KaxTrackEntry &track,
                                    LacingType lacing) {
  KaxCodecPrivate *priv = FindChild<KaxCodecPrivate>(&track);
  if (!priv)
    mxerror(boost::format(Y("Track %1% with the CodecID '%2%' is missing the \"codec private\" element and cannot be extracted.\n")) % m_tid % m_codec_id);

  init_content_decoder(track);
  memory_cptr mpriv = decode_codec_private(priv);

  std::vector<memory_cptr> header_packets;

  try {
    if (lacing == LACING_NONE)
      header_packets.push_back(mpriv);

    else {
      header_packets = unlace_memory_xiph(mpriv);

      if (header_packets.empty())
        throw false;
    }

    header_packets_unlaced(header_packets);

  } catch (...) {
    mxerror(boost::format(Y("Track %1% with the CodecID '%2%' does not contain valid headers.\n")) % m_tid % m_codec_id);
  }

  xtr_oggbase_c::create_file(master, track);

  ogg_packet op;
  for (m_packetno = 0; header_packets.size() > m_packetno; ++m_packetno) {
    // Handle all the header packets: ID header, comments, etc
    op.b_o_s      = (0 == m_packetno ? 1 : 0);
    op.e_o_s      = 0;
    op.packetno   = m_packetno;
    op.packet     = header_packets[m_packetno]->get_buffer();
    op.bytes      = header_packets[m_packetno]->get_size();
    op.granulepos = 0;
    ogg_stream_packetin(&m_os, &op);

    if (0 == m_packetno) /* ID header must be alone on a separate page */
      flush_pages();
  }

  /* flush at last header, data must start on a new page */
  flush_pages();
}
コード例 #4
0
ファイル: xtr_wav.cpp プロジェクト: Rodeo314/mkvtoolnix
void
xtr_wav_c::create_file(xtr_base_c *master,
                       KaxTrackEntry &track) {
  init_content_decoder(track);

  auto channels    = kt_get_a_channels(track);
  auto sfreq       = static_cast<int>(kt_get_a_sfreq(track));
  auto bps         = kt_get_a_bps(track);
  auto block_align = bps * channels / boost::math::gcd(8, bps);


  if (-1 == bps)
    mxerror(boost::format(Y("Track %1% with the CodecID '%2%' is missing the \"bits per second (bps)\" element and cannot be extracted.\n")) % m_tid % m_codec_id);

  xtr_base_c::create_file(master, track);

  memcpy(&m_wh.riff.id,      "RIFF", 4);
  memcpy(&m_wh.riff.wave_id, "WAVE", 4);
  memcpy(&m_wh.format.id,    "fmt ", 4);
  memcpy(&m_wh.data.id,      "data", 4);

  put_uint32_le(&m_wh.format.len,              16);
  put_uint16_le(&m_wh.common.wFormatTag,        1);
  put_uint16_le(&m_wh.common.wChannels,        channels);
  put_uint32_le(&m_wh.common.dwSamplesPerSec,  sfreq);
  put_uint32_le(&m_wh.common.dwAvgBytesPerSec, channels * sfreq * bps / 8);
  put_uint16_le(&m_wh.common.wBlockAlign,      block_align);
  put_uint16_le(&m_wh.common.wBitsPerSample,   bps);

  m_out->write(&m_wh, sizeof(wave_header));

  if (m_codec_id == MKV_A_PCM_BE)
    m_byte_swapper = [bps](unsigned char const *src, unsigned char *dst, std::size_t num_bytes) {
      mtx::bytes::swap_buffer(src, dst, num_bytes, bps / 8);
    };
}
コード例 #5
0
ファイル: xtr_alac.cpp プロジェクト: CharlesLio/mkvtoolnix
void
xtr_alac_c::create_file(xtr_base_c *master, KaxTrackEntry &track) {
  init_content_decoder(track);

  auto channels = kt_get_a_channels(track);
  auto priv     = FindChild<KaxCodecPrivate>(&track);
  if (!priv)
    mxerror(boost::format(Y("Track %1% with the CodecID '%2%' is missing the \"codec private\" element and cannot be extracted.\n")) % m_tid % m_codec_id);

  m_priv = decode_codec_private(priv);
  if (m_priv->get_size() != sizeof(alac::codec_config_t))
    mxerror(boost::format(Y("ALAC private data size mismatch\n")));

  xtr_base_c::create_file(master, track);

  m_out->write(std::string{"caff"});                             // mFileType
  m_out->write_uint16_be(1);                                     // mFileVersion
  m_out->write_uint16_be(0);                                     // mFileFlags

  m_out->write(std::string{"desc"});                             // Audio Description chunk
  m_out->write_uint64_be(32ULL);                                 // mChunkSize
  m_out->write_double(static_cast<int>(kt_get_a_sfreq(track)));  // mSampleRate
  m_out->write(std::string{"alac"});                             // mFormatID
  m_out->write_uint32_be(0);                                     // mFormatFlags
  m_out->write_uint32_be(0);                                     // mBytesPerPacket
  m_out->write_uint32_be(caf::defs::default_frames_per_packet);  // mFramesPerPacket
  m_out->write_uint32_be(channels);                              // mChannelsPerFrame
  m_out->write_uint32_be(0);                                     // mBitsPerChannel

  auto kuki_size = 12 + 36 + 8 + (2 < channels ? 24 : 0);        // add the size of ALACChannelLayoutInfo for more than 2 channels
  m_out->write(std::string{"kuki"});
  m_out->write_uint64_be(kuki_size);
  m_out->write_uint8('\0');
  m_out->write_uint8('\0');
  m_out->write_uint8('\0');
  m_out->write_uint8('\14');
  m_out->write(std::string{"frma"});
  m_out->write(std::string{"alac"});

  m_out->write_uint32_be(12 + sizeof(alac::codec_config_t));     // ALAC Specific Info size = 36 (12 + sizeof(ALAXSpecificConfig))
  m_out->write(std::string{"alac"});                             // ALAC Specific Info ID
  m_out->write_uint32_be(0L);                                    // Version Flags

  m_out->write(m_priv);                                          // audio specific config

  auto alo = caf::channel_layout_t();
  if (2 < channels) {
    switch (channels) {
      case 3:
        alo.channel_layout_tag = caf::channel_layout_t::mpeg_3_0_b;
        alo.channel_bitmap     = caf::channel_layout_t::left | caf::channel_layout_t::right | caf::channel_layout_t::center;
        break;
      case 4:
        alo.channel_layout_tag = caf::channel_layout_t::mpeg_4_0_b;
        alo.channel_bitmap     = caf::channel_layout_t::left | caf::channel_layout_t::right | caf::channel_layout_t::center | caf::channel_layout_t::center_surround;
        break;
      case 5:
        alo.channel_layout_tag = caf::channel_layout_t::mpeg_5_0_d;
        alo.channel_bitmap     = caf::channel_layout_t::left | caf::channel_layout_t::right | caf::channel_layout_t::center | caf::channel_layout_t::left_surround | caf::channel_layout_t::right_surround;
        break;
      case 6:
        alo.channel_layout_tag = caf::channel_layout_t::mpeg_5_1_d;
        alo.channel_bitmap     = caf::channel_layout_t::left | caf::channel_layout_t::right | caf::channel_layout_t::center | caf::channel_layout_t::left_surround | caf::channel_layout_t::right_surround | caf::channel_layout_t::lfe_screen;
        break;
      case 7:
        alo.channel_layout_tag = caf::channel_layout_t::aac_6_1;
        alo.channel_bitmap     = caf::channel_layout_t::left | caf::channel_layout_t::right | caf::channel_layout_t::center | caf::channel_layout_t::left_surround
                               | caf::channel_layout_t::right_surround | caf::channel_layout_t::center_surround | caf::channel_layout_t::lfe_screen;
        break;
      case 8:
        alo.channel_layout_tag = caf::channel_layout_t::mpeg_7_1_b;
        alo.channel_bitmap     = caf::channel_layout_t::left | caf::channel_layout_t::right | caf::channel_layout_t::center | caf::channel_layout_t::left_center
                               | caf::channel_layout_t::right_center | caf::channel_layout_t::left_surround | caf::channel_layout_t::right_surround | caf::channel_layout_t::lfe_screen;
        break;
    }

    auto acli = caf::channel_layout_info_t();

    put_uint32_be(&acli.channel_layout_info_size, 24);                         // = sizeof(ALACChannelLayoutInfo)
    put_uint32_be(&acli.channel_layout_info_id,   FOURCC('c', 'h', 'a', 'n')); // = 'chan'
    put_uint32_be(&acli.channel_layout_tag,       alo.channel_layout_tag);
    m_out->write(&acli, sizeof(acli));
  }

  // Terminator atom
  m_out->write_uint32_be(8);        // Channel Layout Info Size
  m_out->write_uint32_be(0);        // Channel Layout Info ID

  if (2 < channels) {
    m_out->write(std::string{"chan"}); // 'chan' chunk immediately following the kuki
    m_out->write_uint64_be(12ULL);     // = sizeof(ALACAudioChannelLayout)

    m_out->write_uint32_be(alo.channel_layout_tag);
    m_out->write_uint32_be(alo.channel_bitmap);
    m_out->write_uint32_be(alo.number_channel_descriptions);
  }

  m_free_chunk_offset = m_out->getFilePointer();    // remember the location of
  m_free_chunk_size   = 16384;

  auto free_chunk = memory_c::alloc(m_free_chunk_size);
  memset(free_chunk->get_buffer(), 0, sizeof(m_free_chunk_size));

  // the 'free' chunk
  m_out->write(std::string{"free"});
  m_out->write_uint64_be(m_free_chunk_size);
  m_out->write(free_chunk);

  m_data_chunk_offset = m_out->getFilePointer();
  m_out->write(std::string{"data"}); // Audio Data Chunk
  m_out->write_uint64_be(-1LL);      // mChunkSize (= -1 if unknown)
  m_out->write_uint32_be(1);         // mEditCount
}
コード例 #6
0
ファイル: xtr_textsubs.cpp プロジェクト: VRDate/mkvtoolnix
void
xtr_usf_c::create_file(xtr_base_c *master,
                       KaxTrackEntry &track) {
  KaxCodecPrivate *priv = FindChild<KaxCodecPrivate>(&track);
  if (!priv)
    mxerror(boost::format(Y("Track %1% with the CodecID '%2%' is missing the \"codec private\" element and cannot be extracted.\n")) % m_tid % m_codec_id);

  init_content_decoder(track);

  memory_cptr new_priv = decode_codec_private(priv);
  m_codec_private.append((const char *)new_priv->get_buffer(), new_priv->get_size());

  KaxTrackLanguage *language = FindChild<KaxTrackLanguage>(&track);
  if (!language)
    m_language = "eng";
  else
    m_language = std::string(*language);

  if (master) {
    xtr_usf_c *usf_master = dynamic_cast<xtr_usf_c *>(master);
    if (!usf_master)
      mxerror(boost::format(Y("Cannot write track %1% with the CodecID '%2%' to the file '%3%' because "
                              "track %4% with the CodecID '%5%' is already being written to the same file.\n"))
              % m_tid % m_codec_id % m_file_name % master->m_tid % master->m_codec_id);

    if (m_codec_private != usf_master->m_codec_private)
      mxerror(boost::format(Y("Cannot write track %1% with the CodecID '%2%' to the file '%3%' because track %4% with the CodecID '%5%' is already "
                              "being written to the same file, and their CodecPrivate data (the USF styles etc) do not match.\n"))
              % m_tid % m_codec_id % m_file_name % master->m_tid % master->m_codec_id);

    m_doc    = usf_master->m_doc;
    m_master = usf_master;

  } else {
    try {
      m_out = mm_file_io_c::open(m_file_name, MODE_CREATE);
      m_doc = std::make_shared<pugi::xml_document>();

      std::stringstream codec_private{m_codec_private};
      auto result = m_doc->load(codec_private, pugi::parse_default | pugi::parse_declaration | pugi::parse_doctype | pugi::parse_pi | pugi::parse_comments);
      if (!result)
        throw mtx::xml::xml_parser_x{result};

      pugi::xml_node doctype_node, declaration_node, stylesheet_node;
      for (auto child : *m_doc)
        if (child.type() == pugi::node_declaration)
          declaration_node = child;

        else if (child.type() == pugi::node_doctype)
          doctype_node = child;

        else if ((child.type() == pugi::node_pi) && (std::string{child.name()} == "xml-stylesheet"))
          stylesheet_node = child;

      if (!declaration_node)
        declaration_node = m_doc->prepend_child(pugi::node_declaration);

      if (!doctype_node)
        doctype_node = m_doc->insert_child_after(pugi::node_doctype, declaration_node);

      if (!stylesheet_node)
        stylesheet_node = m_doc->insert_child_after(pugi::node_pi, declaration_node);

      if (!balg::starts_with(m_simplified_sub_charset, "utf"))
        declaration_node.append_attribute("encoding").set_value(m_sub_charset.c_str());
      doctype_node.set_value("USFSubtitles SYSTEM \"USFV100.dtd\"");
      stylesheet_node.set_name("xml-stylesheet");
      stylesheet_node.append_attribute("type").set_value("text/xsl");
      stylesheet_node.append_attribute("href").set_value("USFV100.xsl");

    } catch (mtx::mm_io::exception &ex) {
      mxerror(boost::format(Y("Failed to create the file '%1%': %2%\n")) % m_file_name % ex);

    } catch (mtx::xml::exception &ex) {
      mxerror(boost::format(Y("Failed to parse the USF codec private data for track %1%: %2%\n")) % m_tid % ex.what());
    }
  }
}