Пример #1
0
void
vc1::es_parser_c::combine_extra_data_with_packet() {
  auto sum_fn     = [](size_t size, const memory_cptr &buffer) { return size + buffer->get_size(); };
  auto extra_size = boost::accumulate(m_pre_frame_extra_data, 0, sum_fn) + boost::accumulate(m_post_frame_extra_data, 0, sum_fn);

  auto new_packet = memory_c::alloc(extra_size + m_current_frame->data->get_size());
  auto ptr        = new_packet->get_buffer();

  for (const auto &mem : m_pre_frame_extra_data) {
    memcpy(ptr, mem->get_buffer(), mem->get_size());
    ptr += mem->get_size();

    if (VC1_MARKER_SEQHDR == get_uint32_be(mem->get_buffer()))
      m_current_frame->contains_sequence_header = true;
  }

  memcpy(ptr, m_current_frame->data->get_buffer(), m_current_frame->data->get_size());
  ptr += m_current_frame->data->get_size();

  for (const auto &mem : m_post_frame_extra_data) {
    memcpy(ptr, mem->get_buffer(), mem->get_size());
    ptr += mem->get_size();

    if (VC1_MARKER_FIELD == get_uint32_be(mem->get_buffer()))
      m_current_frame->contains_field = true;
  }

  m_pre_frame_extra_data.clear();
  m_post_frame_extra_data.clear();

  m_current_frame->data = new_packet;
}
Пример #2
0
bool
mpeg1_2_video_packetizer_c::put_sequence_headers_into_codec_state(packet_cptr packet) {
  unsigned char *buf  = packet->data->get_buffer();
  size_t  pos         = 4;
  size_t  size        = packet->data->get_size();
  unsigned int marker = get_uint32_be(buf);

  while ((pos < size) && (MPEGVIDEO_SEQUENCE_START_CODE != marker)) {
    marker <<= 8;
    marker  |= buf[pos];
    ++pos;
  }

  if ((MPEGVIDEO_SEQUENCE_START_CODE != marker) || ((pos + 4) >= size))
    return false;

  size_t start  = pos - 4;
  marker        = get_uint32_be(&buf[pos]);
  pos          += 4;

  while ((pos < size) && ((MPEGVIDEO_EXT_START_CODE == marker) || (0x00000100 != (marker & 0xffffff00)))) {
    marker <<= 8;
    marker  |= buf[pos];
    ++pos;
  }

  if (pos >= size)
    return false;

  pos            -= 4;
  size_t sh_size  = pos - start;

  if (NULL == m_hcodec_private) {
    set_codec_private(&buf[start], sh_size);
    rerender_track_headers();
  }

  if (!m_seq_hdr.is_set() || (sh_size != m_seq_hdr->get_size()) || memcmp(&buf[start], m_seq_hdr->get_buffer(), sh_size)) {
    m_seq_hdr           = clone_memory(&buf[start], sh_size);
    packet->codec_state = clone_memory(&buf[start], sh_size);
  }

  if (hack_engaged(ENGAGE_USE_CODEC_STATE_ONLY)) {
    memmove(&buf[start], &buf[pos], size - pos);
    packet->data->set_size(size - sh_size);
  }

  return true;
}
Пример #3
0
void
vc1::es_parser_c::handle_packet(memory_cptr packet) {
  uint32_t marker = get_uint32_be(packet->get_buffer());

  switch (marker) {
    case VC1_MARKER_SEQHDR:
      handle_sequence_header_packet(packet);
      break;

    case VC1_MARKER_ENTRYPOINT:
      handle_entrypoint_packet(packet);
      break;

    case VC1_MARKER_FRAME:
      handle_frame_packet(packet);
      break;

    case VC1_MARKER_SLICE:
      handle_slice_packet(packet);
      break;

    case VC1_MARKER_FIELD:
      handle_field_packet(packet);
      break;

    case VC1_MARKER_ENDOFSEQ:
      handle_end_of_sequence_packet(packet);
      break;

    default:
      handle_unknown_packet(marker, packet);
      break;
  }
}
Пример #4
0
int
aac_adif_reader_c::probe_file(mm_io_c *in,
                              uint64_t size) {
  try {
    if (4 > size)
      return 0;

    unsigned char buf[4];

    in->setFilePointer(0, seek_beginning);
    if (in->read(buf, 4) != 4)
      return 0;
    in->setFilePointer(0, seek_beginning);

    if (FOURCC('A', 'D', 'I', 'F') == get_uint32_be(buf)) {
      id_result_container_unsupported(in->get_file_name(), Y("AAC with ADIF headers"));
      // Never reached:
      return 1;
    }

    return 0;

  } catch (...) {
    return 0;
  }
}
Пример #5
0
/** \brief Extract the FPS from a MPEG video sequence header

   This function looks for a MPEG sequence header in a buffer containing
   a MPEG1 or MPEG2 video frame. If such a header is found its
   FPS index is extracted and returned. This index can be mapped to the
   actual number of frames per second with the function
   ::mpeg_video_get_fps

   \param buffer The buffer to search for the header.
   \param buffer_size The buffer size.

   \return The index or \c -1 if no MPEG sequence header was found or
     if the buffer was too small.
*/
int
mpeg1_2::extract_fps_idx(const unsigned char *buffer,
                         int buffer_size) {
  mxverb(3, boost::format("mpeg_video_fps: start search in %1% bytes\n") % buffer_size);
  if (buffer_size < 8) {
    mxverb(3, "mpeg_video_fps: sequence header too small\n");
    return -1;
  }
  auto marker = get_uint32_be(buffer);
  int idx     = 4;
  while ((idx < buffer_size) && (marker != MPEGVIDEO_SEQUENCE_HEADER_START_CODE)) {
    marker <<= 8;
    marker |= buffer[idx];
    idx++;
  }

  if ((idx + 3) >= buffer_size) {
    mxverb(3, "mpeg_video_fps: no full sequence header start code found\n");
    return -1;
  }

  mxverb(3, boost::format("mpeg_video_fps: found sequence header start code at %1%\n") % (idx - 4));

  return buffer[idx + 3] & 0x0f;
}
Пример #6
0
int
dirac_es_reader_c::probe_file(mm_io_c *in,
                              uint64_t size) {
  try {
    if (PROBESIZE > size)
      return 0;

    in->setFilePointer(0, seek_beginning);

    memory_cptr buf = memory_c::alloc(READ_SIZE);
    int num_read    = in->read(buf->get_buffer(), READ_SIZE);

    if (4 > num_read)
      return 0;

    uint32_t marker = get_uint32_be(buf->get_buffer());
    if (DIRAC_SYNC_WORD != marker)
      return 0;

    dirac::es_parser_c parser;
    parser.add_bytes(buf->get_buffer(), num_read);

    return parser.is_sequence_header_available();

  } catch (...) {
    mxinfo("have an xcptn\n");
  }

  return 0;
}
Пример #7
0
int
vc1_es_reader_c::probe_file(mm_io_c *in,
                            uint64_t size) {
  try {
    if (PROBESIZE > size)
      return 0;

    in->setFilePointer(0, seek_beginning);

    memory_cptr buf = memory_c::alloc(READ_SIZE);
    int num_read    = in->read(buf->get_buffer(), READ_SIZE);

    if (4 > num_read)
      return 0;

    uint32_t marker = get_uint32_be(buf->get_buffer());
    if ((VC1_MARKER_SEQHDR != marker) && (VC1_MARKER_ENTRYPOINT != marker) && (VC1_MARKER_FRAME != marker))
      return 0;

    vc1::es_parser_c parser;
    parser.add_bytes(buf->get_buffer(), num_read);

    return parser.is_sequence_header_available();

  } catch (...) {
    mxinfo(Y("have an xcptn\n"));
  }

  return 0;
}
Пример #8
0
int
asf_reader_c::probe_file(mm_io_c *in,
                         uint64_t size) {
  try {
    if (4 > size)
      return 0;

    unsigned char buf[4];

    in->setFilePointer(0, seek_beginning);
    if (in->read(buf, 4) != 4)
      return 0;
    in->setFilePointer(0, seek_beginning);

    if (MAGIC_ASF_WMV == get_uint32_be(buf)) {
      id_result_container_unsupported(in->get_file_name(), "Windows Media (ASF/WMV)");
      // Never reached:
      return 1;
    }

    return 0;

  } catch (...) {
    return 0;
  }
}
Пример #9
0
void
avi_reader_c::set_avc_nal_size_size(mpeg4_p10_es_video_packetizer_c *ptzr) {
  m_avc_nal_size_size = ptzr->get_nalu_size_length();

  for (size_t i = 0; i < m_max_video_frames; ++i) {
    int size = AVI_frame_size(m_avi, i);
    if (0 == size)
      continue;

    memory_cptr buffer = memory_c::alloc(size);

    AVI_set_video_position(m_avi, i);
    int key = 0;
    size    = AVI_read_frame(m_avi, reinterpret_cast<char *>(buffer->get_buffer()), &key);

    if (   (4 <= size)
        && (   (get_uint32_be(buffer->get_buffer()) == NALU_START_CODE)
            || (get_uint24_be(buffer->get_buffer()) == NALU_START_CODE)))
      m_avc_nal_size_size = -1;

    break;
  }

  AVI_set_video_position(m_avi, 0);
}
Пример #10
0
uint32_t
mm_io_c::read_uint32_be() {
  unsigned char buffer[4];

  if (read(buffer, 4) != 4)
    throw mtx::mm_io::end_of_file_x();

  return get_uint32_be(buffer);
}
Пример #11
0
void
real_reader_c::parse_headers() {

  if (rmff_read_headers(file) != RMFF_ERR_OK)
    return;

  int ndx;
  for (ndx = 0; ndx < file->num_tracks; ndx++) {
    rmff_track_t *track = file->tracks[ndx];

    if ((RMFF_TRACK_TYPE_UNKNOWN == track->type) || (get_uint32_be(&track->mdpr_header.type_specific_size) == 0))
      continue;
    if ((RMFF_TRACK_TYPE_VIDEO == track->type) && !demuxing_requested('v', track->id))
      continue;
    if ((RMFF_TRACK_TYPE_AUDIO == track->type) && !demuxing_requested('a', track->id))
      continue;
    if ((NULL == track->mdpr_header.mime_type)
        ||
        (   strcmp(track->mdpr_header.mime_type, "audio/x-pn-realaudio")
         && strcmp(track->mdpr_header.mime_type, "video/x-pn-realvideo")))
      continue;

    unsigned char *ts_data = track->mdpr_header.type_specific_data;
    uint32_t ts_size       = get_uint32_be(&track->mdpr_header.type_specific_size);

    real_demuxer_cptr dmx(new real_demuxer_t(track));

    if (RMFF_TRACK_TYPE_VIDEO == track->type) {
      dmx->rvp = (real_video_props_t *)track->mdpr_header.type_specific_data;

      memcpy(dmx->fourcc, &dmx->rvp->fourcc2, 4);
      dmx->fourcc[4]    = 0;
      dmx->width        = get_uint16_be(&dmx->rvp->width);
      dmx->height       = get_uint16_be(&dmx->rvp->height);
      uint32_t i        = get_uint32_be(&dmx->rvp->fps);
      dmx->fps          = (float)((i & 0xffff0000) >> 16) + ((float)(i & 0x0000ffff)) / 65536.0;
      dmx->private_data = (unsigned char *)safememdup(ts_data, ts_size);
      dmx->private_size = ts_size;

      demuxers.push_back(dmx);

    } else if (RMFF_TRACK_TYPE_AUDIO == track->type) {
Пример #12
0
void
dirac::es_parser_c::flush() {
  if (m_unparsed_buffer && (4 <= m_unparsed_buffer->get_size())) {
    uint32_t marker = get_uint32_be(m_unparsed_buffer->get_buffer());
    if (DIRAC_SYNC_WORD == marker)
      handle_unit(memory_c::clone(m_unparsed_buffer->get_buffer(), m_unparsed_buffer->get_size()));
  }

  m_unparsed_buffer.reset();

  flush_frame();
}
Пример #13
0
void
vc1::es_parser_c::flush() {
  if (m_unparsed_buffer && (4 <= m_unparsed_buffer->get_size())) {
    uint32_t marker = get_uint32_be(m_unparsed_buffer->get_buffer());
    if (vc1::is_marker(marker))
      handle_packet(memory_c::clone(m_unparsed_buffer->get_buffer(), m_unparsed_buffer->get_size()));
  }

  m_unparsed_buffer.reset();

  flush_frame();
}
Пример #14
0
void
xtr_mpeg1_2_video_c::handle_frame(xtr_frame_t &f) {
  binary *buf = (binary *)f.frame->get_buffer();

  if (f.references_valid)
    f.keyframe = (0 == f.bref);

  if (f.keyframe && m_seq_hdr) {
    bool seq_hdr_found = false;
    size_t size        = f.frame->get_size();

    if (4 <= size) {
      uint32_t marker = get_uint32_be(buf);
      seq_hdr_found   = MPEGVIDEO_SEQUENCE_HEADER_START_CODE == marker;

      if (seq_hdr_found && (8 <= size)) {
        size_t end_pos = 7;
        marker         = get_uint32_be(&buf[4]);
        while (   ((end_pos + 1) < size)
               && (   (0x00000100               != (marker & 0xffffff00))
                   || (MPEGVIDEO_EXT_START_CODE == marker))) {
          ++end_pos;
          marker = (marker << 8) | buf[end_pos];
        }

        size_t seq_size = end_pos - (((end_pos + 1) < size) ? 3 : 4);

        if ((m_seq_hdr->get_size() != seq_size) || memcmp(m_seq_hdr->get_buffer(), buf, seq_size))
          m_seq_hdr = memory_c::clone(buf, seq_size);
      }
    }

    if (!seq_hdr_found)
      m_out->write(m_seq_hdr);
  }

  m_out->write(buf, f.frame->get_size());
}
Пример #15
0
/** \brief Extract the aspect ratio from a MPEG video sequence header

   This function looks for a MPEG sequence header in a buffer containing
   a MPEG1 or MPEG2 video frame. If such a header is found its
   aspect ratio is extracted and returned.

   \param buffer The buffer to search for the header.
   \param buffer_size The buffer size.

   \return \c true if a MPEG sequence header was found and \c false otherwise.
*/
bool
mpeg1_2::extract_ar(const unsigned char *buffer,
                    int buffer_size,
                    float &ar) {
  uint32_t marker;
  int idx;

  mxverb(3, boost::format("mpeg_video_ar: start search in %1% bytes\n") % buffer_size);
  if (buffer_size < 8) {
    mxverb(3, "mpeg_video_ar: sequence header too small\n");
    return false;
  }
  marker = get_uint32_be(buffer);
  idx = 4;
  while ((idx < buffer_size) && (marker != MPEGVIDEO_SEQUENCE_HEADER_START_CODE)) {
    marker <<= 8;
    marker |= buffer[idx];
    idx++;
  }
  if (idx >= buffer_size) {
    mxverb(3, "mpeg_video_ar: no sequence header start code found\n");
    return false;
  }

  mxverb(3, boost::format("mpeg_video_ar: found sequence header start code at %1%\n") % (idx - 4));
  idx += 3;                     // width and height
  if (idx >= buffer_size) {
    mxverb(3, "mpeg_video_ar: sequence header too small\n");
    return false;
  }

  switch (buffer[idx] & 0xf0) {
    case MPEGVIDEO_AR_1_1:
      ar = 1.0f;
      break;
    case MPEGVIDEO_AR_4_3:
      ar = 4.0f / 3.0f;
      break;
    case MPEGVIDEO_AR_16_9:
      ar = 16.0f / 9.0f;
      break;
    case MPEGVIDEO_AR_2_21:
      ar = 2.21f;
      break;
    default:
      ar = -1.0f;
  }
  return true;
}
Пример #16
0
void
avi_reader_c::create_video_packetizer() {
  size_t i;

  mxverb_tid(4, m_ti.m_fname, 0, "frame sizes:\n");

  for (i = 0; i < m_max_video_frames; i++) {
    m_bytes_to_process += AVI_frame_size(m_avi, i);
    mxverb(4, boost::format("  %1%: %2%\n") % i % AVI_frame_size(m_avi, i));
  }

  if (m_avi->bitmap_info_header) {
    m_ti.m_private_data = memory_c::clone(m_avi->bitmap_info_header, get_uint32_le(&m_avi->bitmap_info_header->bi_size));

    mxverb(4, boost::format("track extra data size: %1%\n") % (m_ti.m_private_data->get_size() - sizeof(alBITMAPINFOHEADER)));

    if (sizeof(alBITMAPINFOHEADER) < m_ti.m_private_data->get_size())
      mxverb(4, boost::format("  %1%\n") % to_hex(m_ti.m_private_data->get_buffer() + sizeof(alBITMAPINFOHEADER), m_ti.m_private_data->get_size() - sizeof(alBITMAPINFOHEADER)));
  }

  const char *codec = AVI_video_compressor(m_avi);
  if (mpeg4::p2::is_v3_fourcc(codec))
    m_divx_type = DIVX_TYPE_V3;
  else if (mpeg4::p2::is_fourcc(codec))
    m_divx_type = DIVX_TYPE_MPEG4;

  if (map_has_key(m_ti.m_default_durations, 0))
    m_fps = 1000000000.0 / m_ti.m_default_durations[0];

  else if (map_has_key(m_ti.m_default_durations, -1))
    m_fps = 1000000000.0 / m_ti.m_default_durations[-1];

  m_ti.m_id = 0;                 // ID for the video track.
  if (DIVX_TYPE_MPEG4 == m_divx_type)
    create_mpeg4_p2_packetizer();

  else if (mpeg4::p10::is_avc_fourcc(codec) && !hack_engaged(ENGAGE_ALLOW_AVC_IN_VFW_MODE))
    create_mpeg4_p10_packetizer();

  else if (mpeg1_2::is_fourcc(get_uint32_le(codec)))
    create_mpeg1_2_packetizer();

  else if (FOURCC('V', 'P', '8', '0') == get_uint32_be(codec))
    create_vp8_packetizer();

  else
    create_standard_video_packetizer();
}
Пример #17
0
bool
cdxa_reader_c::probe_file(mm_io_c *in,
                          uint64_t size) {
  try {
    if (12 > size)
      return false;

    unsigned char buffer[12];

    in->setFilePointer(0, seek_beginning);
    if (in->read(buffer, 12) != 12)
      return false;

    if ((FOURCC('R', 'I', 'F', 'F') == get_uint32_be(&buffer[0])) && (FOURCC('C', 'D', 'X', 'A') == get_uint32_be(&buffer[8]))) {
      id_result_container_unsupported(in->get_file_name(), "RIFF CDXA");
      // Never reached:
      return true;
    }

  } catch (...) {
  }

  return false;
}
Пример #18
0
void
mpeg1_2_video_packetizer_c::remove_stuffing_bytes_and_handle_sequence_headers(packet_cptr packet) {
  mxdebug_if(m_debug_stuffing_removal, boost::format("Starting stuff removal, frame size %1%\n") % packet->data->get_size());

  auto buf              = packet->data->get_buffer();
  auto size             = packet->data->get_size();
  size_t pos            = 4;
  size_t start_code_pos = 0;
  size_t stuffing_start = 0;
  auto marker           = get_uint32_be(buf);
  uint32_t chunk_type   = 0;
  bool seq_hdr_found    = false;

  auto mid_remover      = [this, &stuffing_start, &pos, &size, &buf]() {
    if (!stuffing_start || (stuffing_start >= (pos - 4)))
      return;

    auto num_stuffing_bytes       = pos - 4 - stuffing_start;
    m_num_removed_stuffing_bytes += num_stuffing_bytes;

    ::memmove(&buf[stuffing_start], &buf[pos - 4], size - pos + 4);

    pos  -= num_stuffing_bytes;
    size -= num_stuffing_bytes;

    mxdebug_if(m_debug_stuffing_removal, boost::format("    Stuffing in the middle: %1%\n") % num_stuffing_bytes);
  };

  memory_cptr new_seq_hdr;
  auto seq_hdr_copier = [this, &chunk_type, &seq_hdr_found, &buf, &start_code_pos, &pos, &new_seq_hdr, &size](bool at_end) {
    if ((MPEGVIDEO_SEQUENCE_HEADER_START_CODE != chunk_type) && (MPEGVIDEO_EXT_START_CODE != chunk_type))
      return;

    if (MPEGVIDEO_SEQUENCE_HEADER_START_CODE == chunk_type)
      seq_hdr_found = true;

    else if (!seq_hdr_found)
      return;

    auto bytes_to_copy = at_end ? pos - start_code_pos : pos - 4 - start_code_pos;

    if (!new_seq_hdr)
      new_seq_hdr = memory_c::clone(&buf[start_code_pos], bytes_to_copy);

    else
      new_seq_hdr->add(&buf[start_code_pos], bytes_to_copy);

    if (!hack_engaged(ENGAGE_USE_CODEC_STATE_ONLY))
      return;

    memmove(&buf[start_code_pos], &buf[pos - 4], size - pos + 4);
    pos  -= bytes_to_copy;
    size -= bytes_to_copy;
  };

  while (pos < size) {
    if ((MPEGVIDEO_SLICE_START_CODE_LOWER <= marker) && (MPEGVIDEO_SLICE_START_CODE_UPPER >= marker)) {
      mxdebug_if(m_debug_stuffing_removal, boost::format("  Slice start code at %1%\n") % (pos - 4));

      mid_remover();
      seq_hdr_copier(false);

      chunk_type     = MPEGVIDEO_SLICE_START_CODE_LOWER;
      stuffing_start = 0;
      start_code_pos = pos - 4;

    } else if ((marker & 0xffffff00) == 0x00000100) {
      mxdebug_if(m_debug_stuffing_removal, boost::format("  Non-slice start code at %1%\n") % (pos - 4));

      mid_remover();
      seq_hdr_copier(false);

      chunk_type     = marker;
      stuffing_start = 0;
      start_code_pos = pos - 4;

    } else if ((MPEGVIDEO_SLICE_START_CODE_LOWER == chunk_type) && !stuffing_start && (marker == 0x00000000)) {
      mxdebug_if(m_debug_stuffing_removal, boost::format("    Start at %1%\n") % (pos - 3));

      stuffing_start = pos - 3;
    }

    marker <<= 8;
    marker  |= buf[pos];
    ++pos;
  }

  if ((marker & 0xffffff00) == 0x00000100) {
    seq_hdr_copier(false);
    mid_remover();

  } else if (stuffing_start && (stuffing_start < size)) {
    mxdebug_if(m_debug_stuffing_removal, boost::format("    Stuffing at the end: chunk_type 0x%|1$08x| stuffing_start %2% stuffing_size %3%\n") % chunk_type % stuffing_start % (stuffing_start ? size - stuffing_start : 0));

    m_num_removed_stuffing_bytes += size - stuffing_start;
    size                          = stuffing_start;
  }

  packet->data->set_size(size);

  if (!new_seq_hdr)
    return;

  if (!m_hcodec_private) {
    set_codec_private(new_seq_hdr);
    rerender_track_headers();
  }

  if (!m_seq_hdr || (*new_seq_hdr != *m_seq_hdr)) {
    m_seq_hdr           = new_seq_hdr;
    packet->codec_state = new_seq_hdr->clone();
  }
}
Пример #19
0
/*
   The page is the beginning of a new stream. Check the contents for known
   stream headers. If it is a known stream and the user has requested that
   it should be extracted then allocate a new packetizer based on the
   stream type and store the needed data in a new ogm_demuxer_c.
*/
void
ogm_reader_c::handle_new_stream(ogg_page *og) {
  ogg_stream_state os;
  ogg_packet op;

  if (ogg_stream_init(&os, ogg_page_serialno(og))) {
    mxwarn_fn(m_ti.m_fname, boost::format(Y("ogg_stream_init for stream number %1% failed. Will try to continue and ignore this stream.\n")) % sdemuxers.size());
    return;
  }

  // Read the first page and get its first packet.
  ogg_stream_pagein(&os, og);
  ogg_stream_packetout(&os, &op);

  ogm_demuxer_c *dmx = nullptr;

  /*
   * Check the contents for known stream headers. This one is the
   * standard Vorbis header.
   */
  if ((7 <= op.bytes) && !strncmp((char *)&op.packet[1], "vorbis", 6))
    dmx = new ogm_a_vorbis_demuxer_c(this);

  else if ((7 <= op.bytes) && !strncmp((char *)&op.packet[1], "theora", 6))
    dmx = new ogm_v_theora_demuxer_c(this);

  else if ((8 <= op.bytes) && !memcmp(&op.packet[1], "kate\0\0\0", 7))
    dmx = new ogm_s_kate_demuxer_c(this);

  // FLAC
  else if (   ((4 <= op.bytes) && !strncmp(reinterpret_cast<char *>(&op.packet[0]), "fLaC", 4))
           || ((5 <= op.bytes) && !strncmp(reinterpret_cast<char *>(&op.packet[1]), "FLAC", 4) && (0x7f == op.packet[0]))) {
#if !defined(HAVE_FLAC_FORMAT_H)
    if (demuxing_requested('a', sdemuxers.size()))
      mxerror_fn(m_ti.m_fname, Y("mkvmerge has not been compiled with FLAC support but handling of this stream has been requested.\n"));

    else {
      dmx         = new ogm_demuxer_c(this);
      dmx->stype  = OGM_STREAM_TYPE_A_FLAC;
      dmx->in_use = true;
    }

#else
    dmx = new ogm_a_flac_demuxer_c(this, 0x7f == op.packet[0] ? ofm_post_1_1_1 : ofm_pre_1_1_1);
#endif

  } else if ((static_cast<size_t>(op.bytes) >= sizeof(vp8_ogg_header_t)) && (0x4f == op.packet[0]) && (get_uint32_be(&op.packet[1]) == 0x56503830))
    dmx = new ogm_v_vp8_demuxer_c(this, op);

  else if (((*op.packet & PACKET_TYPE_BITS ) == PACKET_TYPE_HEADER) && (op.bytes >= ((int)sizeof(stream_header) + 1))) {
    // The new stream headers introduced by OggDS (see ogmstreams.h).

    stream_header *sth = (stream_header *)(op.packet + 1);
    char buf[5];
    buf[4] = 0;

    if (!strncmp(sth->streamtype, "video", 5)) {
      memcpy(buf, (char *)sth->subtype, 4);

      if (mpeg4::p10::is_avc_fourcc(buf) && !hack_engaged(ENGAGE_ALLOW_AVC_IN_VFW_MODE))
        dmx = new ogm_v_avc_demuxer_c(this);
      else
        dmx = new ogm_v_mscomp_demuxer_c(this);

    } else if (!strncmp(sth->streamtype, "audio", 5)) {
      memcpy(buf, (char *)sth->subtype, 4);

      uint32_t codec_id = strtol(buf, (char **)nullptr, 16);

      if (0x0001 == codec_id)
        dmx = new ogm_a_pcm_demuxer_c(this);

      else if ((0x0050 == codec_id) || (0x0055 == codec_id))
        dmx = new ogm_a_mp3_demuxer_c(this);

      else if (0x2000 == codec_id)
        dmx = new ogm_a_ac3_demuxer_c(this);

      else if (0x00ff == codec_id)
        dmx = new ogm_a_aac_demuxer_c(this);

      else
        mxwarn_fn(m_ti.m_fname, boost::format(Y("Unknown audio stream type 0x%|1$04x|. Stream ID %2% will be ignored.\n")) % codec_id % sdemuxers.size());

    } else if (!strncmp(sth->streamtype, "text", 4))
      dmx = new ogm_s_text_demuxer_c(this);
  }

  /*
   * The old OggDS headers (see MPlayer's source, libmpdemux/demux_ogg.c)
   * are not supported.
   */

  if (!dmx)
    dmx = new ogm_demuxer_c(this);

  std::string type = dmx->get_type();

  dmx->serialno    = ogg_page_serialno(og);
  dmx->track_id    = sdemuxers.size();
  dmx->in_use      = (type != "unknown") && demuxing_requested(type[0], dmx->track_id);

  dmx->packet_data.push_back(memory_cptr(new memory_c((unsigned char *)safememdup(op.packet, op.bytes), op.bytes, true)));

  memcpy(&dmx->os, &os, sizeof(ogg_stream_state));

  sdemuxers.push_back(ogm_demuxer_cptr(dmx));

  dmx->initialize();
}
Пример #20
0
int
mpeg_ts_reader_c::parse_pat(unsigned char *pat) {
  if (!pat) {
    mxdebug_if(m_debug_pat_pmt, "mpeg_ts:parse_pat: Invalid parameters!\n");
    return -1;
  }

  mpeg_ts_pat_t *pat_header = (mpeg_ts_pat_t *)pat;

  if (pat_header->table_id != 0x00) {
    mxdebug_if(m_debug_pat_pmt, "mpeg_ts:parse_pat: Invalid PAT table_id!\n");
    return -1;
  }

  if (pat_header->get_section_syntax_indicator() != 1 || pat_header->get_current_next_indicator() == 0) {
    mxdebug_if(m_debug_pat_pmt, "mpeg_ts:parse_pat: Invalid PAT section_syntax_indicator/current_next_indicator!\n");
    return -1;
  }

  if (pat_header->section_number != 0 || pat_header->last_section_number != 0) {
    mxdebug_if(m_debug_pat_pmt, "mpeg_ts:parse_pat: Unsupported multiple section PAT!\n");
    return -1;
  }

  unsigned short pat_section_length = pat_header->get_section_length();
  uint32_t elapsed_CRC              = crc_calc_mpeg2(pat, 3 + pat_section_length - 4/*CRC32*/);
  uint32_t read_CRC                 = get_uint32_be(pat + 3 + pat_section_length - 4);

  if (elapsed_CRC != read_CRC) {
    mxdebug_if(m_debug_pat_pmt, boost::format("mpeg_ts:parse_pat: Wrong PAT CRC !!! Elapsed = 0x%|1$08x|, read 0x%|2$08x|\n") % elapsed_CRC % read_CRC);
    return -1;
  }

  if (pat_section_length < 13 || pat_section_length > 1021) {
    mxdebug_if(m_debug_pat_pmt, boost::format("mpeg_ts:parse_pat: Wrong PAT section_length (= %1%)\n") % pat_section_length);
    return -1;
  }

  unsigned int prog_count = (pat_section_length - 5 - 4/*CRC32*/) / 4;

  unsigned int i                     = 0;
  mpeg_ts_pat_section_t *pat_section = (mpeg_ts_pat_section_t *)(pat + sizeof(mpeg_ts_pat_t));
  for (; i < prog_count; i++, pat_section++) {
    unsigned short local_program_number = pat_section->get_program_number();
    uint16_t tmp_pid                    = pat_section->get_pid();

    mxdebug_if(m_debug_pat_pmt, boost::format("mpeg_ts:parse_pat: program_number: %1%; %2%_pid: %3%\n")
               % local_program_number
               % (0 == local_program_number ? "nit" : "pmt")
               % tmp_pid);

    if (0 != local_program_number) {
      PAT_found = true;

      bool skip = false;
      for (uint16_t i = 0; i < tracks.size(); i++) {
        if (tracks[i]->pid == tmp_pid) {
          skip = true;
          break;
        }
      }

      if (skip == true)
        continue;

      mpeg_ts_track_ptr PMT(new mpeg_ts_track_c(*this));
      PMT->type       = PMT_TYPE;
      PMT->processed  = false;
      PMT->data_ready = false;
      es_to_process   = 0;

      PMT->set_pid(tmp_pid);

      tracks.push_back(PMT);
    }
  }

  return 0;
}
Пример #21
0
int
mpeg_ts_reader_c::parse_pmt(unsigned char *pmt) {
  if (!pmt) {
    mxdebug_if(m_debug_pat_pmt, "mpeg_ts:parse_pmt: Invalid parameters!\n");
    return -1;
  }

  mpeg_ts_pmt_t *pmt_header = (mpeg_ts_pmt_t *)pmt;

  if (pmt_header->table_id != 0x02) {
    mxdebug_if(m_debug_pat_pmt, "mpeg_ts:parse_pmt: Invalid PMT table_id!\n");
    return -1;
  }

  if (pmt_header->get_section_syntax_indicator() != 1 || pmt_header->get_current_next_indicator() == 0) {
    mxdebug_if(m_debug_pat_pmt, "mpeg_ts:parse_pmt: Invalid PMT section_syntax_indicator/current_next_indicator!\n");
    return -1;
  }

  if (pmt_header->section_number != 0 || pmt_header->last_section_number != 0) {
    mxdebug_if(m_debug_pat_pmt, "mpeg_ts:parse_pmt: Unsupported multiple section PMT!\n");
    return -1;
  }

  unsigned short pmt_section_length = pmt_header->get_section_length();
  uint32_t elapsed_CRC              = crc_calc_mpeg2(pmt, 3 + pmt_section_length - 4/*CRC32*/);
  uint32_t read_CRC                 = get_uint32_be(pmt + 3 + pmt_section_length - 4);

  if (elapsed_CRC != read_CRC) {
    mxdebug_if(m_debug_pat_pmt, boost::format("mpeg_ts:parse_pmt: Wrong PMT CRC !!! Elapsed = 0x%|1$08x|, read 0x%|2$08x|\n") % elapsed_CRC % read_CRC);
    return -1;
  }

  if (pmt_section_length < 13 || pmt_section_length > 1021) {
    mxdebug_if(m_debug_pat_pmt, boost::format("mpeg_ts:parse_pmt: Wrong PMT section_length (=%1%)\n") % pmt_section_length);
    return -1;
  }

  mpeg_ts_pmt_descriptor_t *pmt_descriptor = (mpeg_ts_pmt_descriptor_t *)(pmt + sizeof(mpeg_ts_pmt_t));
  unsigned short program_info_length       = pmt_header->get_program_info_length();

  while (pmt_descriptor < (mpeg_ts_pmt_descriptor_t *)(pmt + sizeof(mpeg_ts_pmt_t) + program_info_length))
    pmt_descriptor = (mpeg_ts_pmt_descriptor_t *)((unsigned char *)pmt_descriptor + sizeof(mpeg_ts_pmt_descriptor_t) + pmt_descriptor->length);

  mpeg_ts_pmt_pid_info_t *pmt_pid_info = (mpeg_ts_pmt_pid_info_t *)pmt_descriptor;

  // Calculate pids_count
  size_t pids_found = 0;
  while (pmt_pid_info < (mpeg_ts_pmt_pid_info_t *)(pmt + 3 + pmt_section_length - 4/*CRC32*/)) {
    pids_found++;
    pmt_pid_info = (mpeg_ts_pmt_pid_info_t *)((unsigned char *)pmt_pid_info + sizeof(mpeg_ts_pmt_pid_info_t) + pmt_pid_info->get_es_info_length());
  }

  mxdebug_if(m_debug_pat_pmt, boost::format("mpeg_ts:parse_pmt: program number     (%1%)\n") % pmt_header->get_program_number());
  mxdebug_if(m_debug_pat_pmt, boost::format("mpeg_ts:parse_pmt: pcr pid            (%1%)\n") % pmt_header->get_pcr_pid());

  if (pids_found == 0) {
    mxdebug_if(m_debug_pat_pmt, "mpeg_ts:parse_pmt: There's no information about elementary PIDs\n");
    return 0;
  }

  pmt_pid_info = (mpeg_ts_pmt_pid_info_t *)pmt_descriptor;

  // Extract pid_info
  while (pmt_pid_info < (mpeg_ts_pmt_pid_info_t *)(pmt + 3 + pmt_section_length - 4/*CRC32*/)) {
    mpeg_ts_track_ptr track(new mpeg_ts_track_c(*this));
    unsigned short es_info_length = pmt_pid_info->get_es_info_length();
    track->type                   = ES_UNKNOWN;

    track->set_pid(pmt_pid_info->get_pid());

    switch(pmt_pid_info->stream_type) {
      case ISO_11172_VIDEO:
        track->type   = ES_VIDEO_TYPE;
        track->fourcc = FOURCC('M', 'P', 'G', '1');
        break;
      case ISO_13818_VIDEO:
        track->type   = ES_VIDEO_TYPE;
        track->fourcc = FOURCC('M', 'P', 'G', '2');
        break;
      case ISO_14496_PART2_VIDEO:
        track->type   = ES_VIDEO_TYPE;
        track->fourcc = FOURCC('M', 'P', 'G', '4');
        break;
      case ISO_14496_PART10_VIDEO:
        track->type   = ES_VIDEO_TYPE;
        track->fourcc = FOURCC('A', 'V', 'C', '1');
        break;
      case STREAM_VIDEO_VC1:
        track->type   = ES_VIDEO_TYPE;
        track->fourcc = FOURCC('W', 'V', 'C', '1');
        break;
      case ISO_11172_AUDIO:
      case ISO_13818_AUDIO:
        track->type   = ES_AUDIO_TYPE;
        track->fourcc = FOURCC('M', 'P', '2', ' ');
        break;
      case ISO_13818_PART7_AUDIO:
        track->type   = ES_AUDIO_TYPE;
        track->fourcc = FOURCC('A', 'A', 'C', ' ');
        break;
      case ISO_14496_PART3_AUDIO:
        track->type   = ES_AUDIO_TYPE;
        track->fourcc = FOURCC('A', 'A', 'C', ' ');
        break;
      case STREAM_AUDIO_AC3:
      case STREAM_AUDIO_AC3_PLUS: // EAC3
        track->type   = ES_AUDIO_TYPE;
        track->fourcc = FOURCC('A', 'C', '3', ' ');
        break;
      case STREAM_AUDIO_AC3_LOSSLESS:
        track->type   = ES_AUDIO_TYPE;
        track->fourcc = FOURCC('T', 'R', 'H', 'D');
        break;
      case STREAM_AUDIO_DTS:
      case STREAM_AUDIO_DTS_HD:
      case STREAM_AUDIO_DTS_HD_MA:
        track->type   = ES_AUDIO_TYPE;
        track->fourcc = FOURCC('D', 'T', 'S', ' ');
        break;
      case STREAM_SUBTITLES_HDMV_PGS:
        track->type      = ES_SUBT_TYPE;
        track->fourcc    = FOURCC('P', 'G', 'S', ' ');
        track->probed_ok = true;
        break;
      case ISO_13818_PES_PRIVATE:
        break;
      default:
        mxdebug_if(m_debug_pat_pmt, boost::format("mpeg_ts:parse_pmt: Unknown stream type: %1%\n") % (int)pmt_pid_info->stream_type);
        track->type   = ES_UNKNOWN;
        break;
    }

    pmt_descriptor  = (mpeg_ts_pmt_descriptor_t *)((unsigned char *)pmt_pid_info + sizeof(mpeg_ts_pmt_pid_info_t));
    bool type_known = false;

    while (pmt_descriptor < (mpeg_ts_pmt_descriptor_t *)((unsigned char *)pmt_pid_info + sizeof(mpeg_ts_pmt_pid_info_t) + es_info_length)) {
      mxdebug_if(m_debug_pat_pmt, boost::format("mpeg_ts:parse_pmt: PMT descriptor tag 0x%|1$02x| length %2%\n") % static_cast<unsigned int>(pmt_descriptor->tag) % static_cast<unsigned int>(pmt_descriptor->length));

      switch(pmt_descriptor->tag) {
        case 0x56: // Teletext descriptor
          if (pmt_pid_info->stream_type == ISO_13818_PES_PRIVATE) { // PES containig private data
            track->type   = ES_UNKNOWN;
            type_known    = true;
            mxdebug_if(m_debug_pat_pmt, "mpeg_ts:parse_pmt: Teletext found but not handled !!\n");
          }
          break;
        case 0x59: // Subtitles descriptor
          if (pmt_pid_info->stream_type == ISO_13818_PES_PRIVATE) { // PES containig private data
            track->type   = ES_SUBT_TYPE;
            track->fourcc = FOURCC('V', 'S', 'U', 'B');
            type_known    = true;
          }
          break;
        case 0x6A: // AC3 descriptor
        case 0x7A: // EAC3 descriptor
          if (pmt_pid_info->stream_type == ISO_13818_PES_PRIVATE) { // PES containig private data
            track->type   = ES_AUDIO_TYPE;
            track->fourcc = FOURCC('A', 'C', '3', ' ');
            type_known    = true;
          }
          break;
        case 0x7b: // DTS descriptor
          if (pmt_pid_info->stream_type == ISO_13818_PES_PRIVATE) { // PES containig private data
            track->type   = ES_AUDIO_TYPE;
            track->fourcc = FOURCC('D', 'T', 'S', ' ');
            type_known    = true;
          }
          break;
        case 0x0a: // ISO 639 language descriptor
          if (3 <= pmt_descriptor->length) {
            int language_idx = map_to_iso639_2_code(std::string(reinterpret_cast<char *>(pmt_descriptor + 1), 3).c_str());
            if (-1 != language_idx)
              track->language = iso639_languages[language_idx].iso639_2_code;
          }
          break;
      }

      pmt_descriptor = (mpeg_ts_pmt_descriptor_t *)((unsigned char *)pmt_descriptor + sizeof(mpeg_ts_pmt_descriptor_t) + pmt_descriptor->length);
    }

    // Default to AC3 if it's a PES private stream type that's missing
    // a known/more concrete descriptor tag.
    if ((pmt_pid_info->stream_type == ISO_13818_PES_PRIVATE) && !type_known) {
      track->type   = ES_AUDIO_TYPE;
      track->fourcc = FOURCC('A', 'C', '3', ' ');
    }

    pmt_pid_info = (mpeg_ts_pmt_pid_info_t *)((unsigned char *)pmt_pid_info + sizeof(mpeg_ts_pmt_pid_info_t) + es_info_length);
    if (track->type != ES_UNKNOWN) {
      PMT_found         = true;
      track->pid        = track->pid;
      track->processed  = false;
      track->data_ready = false;
      tracks.push_back(track);
      es_to_process++;
      uint32_t fourcc = get_uint32_be(&track->fourcc);
      mxdebug_if(m_debug_pat_pmt, boost::format("mpeg_ts:parse_pmt: PID %1% has type: 0x%|2$08x| (%3%)\n") % track->pid % fourcc % std::string(reinterpret_cast<char *>(&fourcc), 4));
    }
  }

  return 0;
}
Пример #22
0
  int32_t  get_int32_be(uint8_t *buffer)
 {
 	return((int32_t)get_uint32_be(buffer));
 }
Пример #23
0
uint32_t
fourcc_c::read(void const *mem,
               fourcc_c::byte_order_t byte_order) {
  return val(get_uint32_be(mem), byte_order);
}
Пример #24
0
int
mpeg_es_reader_c::probe_file(mm_io_c *in,
                             uint64_t size) {
  if (PROBESIZE > size)
    return 0;

  try {
    memory_cptr af_buf = memory_c::alloc(READ_SIZE);
    unsigned char *buf = af_buf->get_buffer();
    in->setFilePointer(0, seek_beginning);
    int num_read = in->read(buf, READ_SIZE);

    if (4 > num_read)
      return 0;

    in->setFilePointer(0, seek_beginning);

    // MPEG TS starts with 0x47.
    if (0x47 == buf[0])
      return 0;

    // MPEG PS starts with 0x000001ba.
    uint32_t value = get_uint32_be(buf);
    if (MPEGVIDEO_PACKET_START_CODE == value)
      return 0;

    // Due to type detection woes mkvmerge requires
    // the stream to start with a MPEG start code.
    if (!mpeg_is_start_code(value))
      return 0;

    bool gop_start_code_found      = false;
    bool sequence_start_code_found = false;
    bool ext_start_code_found      = false;
    bool picture_start_code_found  = false;
    bool slice_start_code_found    = false;

    bool ok                        = false;

    // Let's look for a MPEG ES start code inside the first 1 MB.
    int i;
    for (i = 4; i < num_read - 1; i++) {
      if (mpeg_is_start_code(value)) {
        mxverb(3, boost::format("mpeg_es_detection: start code found; fourth byte: 0x%|1$02x|\n") % (value & 0xff));

        if (MPEGVIDEO_SEQUENCE_HEADER_START_CODE == value)
          sequence_start_code_found = true;

        else if (MPEGVIDEO_PICTURE_START_CODE == value)
          picture_start_code_found  = true;

        else if (MPEGVIDEO_GROUP_OF_PICTURES_START_CODE   == value)
          gop_start_code_found      = true;

        else if (MPEGVIDEO_EXT_START_CODE     == value)
          gop_start_code_found      = true;

        else if ((MPEGVIDEO_FIRST_SLICE_START_CODE >= value) && (MPEGVIDEO_LAST_SLICE_START_CODE <= value))
          slice_start_code_found    = true;

        ok = sequence_start_code_found && picture_start_code_found && (gop_start_code_found || ext_start_code_found || slice_start_code_found);
        if (ok)
          break;
      }

      value <<= 8;
      value  |= buf[i];
    }

    mxverb(3,
           boost::format("mpeg_es_detection: sequence %1% picture %2% gop %3% ext %4% slice %5%\n")
           % sequence_start_code_found % picture_start_code_found % gop_start_code_found % ext_start_code_found % slice_start_code_found);

    if (!ok)
      return 0;

    // Let's try to read one frame.
    M2VParser parser;
    parser.SetProbeMode();
    if (!read_frame(parser, *in, READ_SIZE))
      return 0;

  } catch (...) {
    return 0;
  }

  return 1;
}
Пример #25
0
void
dirac::es_parser_c::add_bytes(unsigned char *buffer,
                              size_t size) {
  memory_slice_cursor_c cursor;

  bool previous_found         = false;
  size_t previous_pos         = 0;
  int64_t previous_stream_pos = m_stream_pos;

  if (m_unparsed_buffer && (0 != m_unparsed_buffer->get_size()))
    cursor.add_slice(m_unparsed_buffer);
  cursor.add_slice(buffer, size);

  if (3 <= cursor.get_remaining_size()) {
    uint32_t marker = (1 << 24) | ((unsigned int)cursor.get_char() << 16) | ((unsigned int)cursor.get_char() << 8) | (unsigned int)cursor.get_char();

    while (1) {
      if (DIRAC_SYNC_WORD == marker) {
        if (!previous_found) {
          previous_found = true;
          previous_pos   = cursor.get_position() - 4;
          m_stream_pos   = previous_stream_pos + previous_pos;

          if (!cursor.char_available())
            break;

          marker <<= 8;
          marker  |= (unsigned int)cursor.get_char();

          continue;
        }

        unsigned char offset_buffer[4];
        cursor.copy(offset_buffer, previous_pos + 4 + 1, 4);
        uint32_t next_offset = get_uint32_be(offset_buffer);

        if ((0 == next_offset) || ((previous_pos + next_offset) <= (cursor.get_position() - 4))) {
          int new_size = cursor.get_position() - 4 - previous_pos;

          memory_cptr packet = memory_c::alloc(new_size);
          cursor.copy(packet->get_buffer(), previous_pos, new_size);

          handle_unit(packet);

          previous_pos = cursor.get_position() - 4;
          m_stream_pos = previous_stream_pos + previous_pos;
        }
      }

      if (!cursor.char_available())
        break;

      marker <<= 8;
      marker  |= (unsigned int)cursor.get_char();
    }
  }

  unsigned int new_size = cursor.get_size() - previous_pos;
  if (0 != new_size) {
    memory_cptr new_unparsed_buffer = memory_c::alloc(new_size);
    cursor.copy(new_unparsed_buffer->get_buffer(), previous_pos, new_size);
    m_unparsed_buffer = new_unparsed_buffer;

  } else
    m_unparsed_buffer.reset();
}