示例#1
0
void
mpeg4_p10_video_packetizer_c::set_headers() {
  static auto s_debug_fix_bistream_timing_info = debugging_option_c{"fix_bitstream_timing_info"};

  if (m_ti.m_private_data && m_ti.m_private_data->get_size())
    extract_aspect_ratio();

  if (m_ti.m_private_data && m_ti.m_private_data->get_size() && m_ti.m_fix_bitstream_frame_rate) {
    int64_t l_track_default_duration = -1;

    if (m_timestamp_factory)
      l_track_default_duration = m_timestamp_factory->get_default_duration(-1);

    if ((-1 == l_track_default_duration) && m_default_duration_forced)
      l_track_default_duration = m_htrack_default_duration;

    if ((-1 == l_track_default_duration) && (0.0 < m_fps))
      l_track_default_duration = static_cast<int64_t>(1000000000.0 / m_fps);

    if (-1 != l_track_default_duration)
      l_track_default_duration /= 2;

    mxdebug_if(s_debug_fix_bistream_timing_info,
               boost::format("fix_bitstream_timing_info: factory default_duration %1% default_duration_forced? %2% htrack_default_duration %3% fps %4% l_track_default_duration %5%\n")
               % (m_timestamp_factory ? m_timestamp_factory->get_default_duration(-1) : -2)
               % m_default_duration_forced % m_htrack_default_duration
               % m_fps % l_track_default_duration);

    set_codec_private(mpeg4::p10::fix_sps_fps(m_ti.m_private_data, l_track_default_duration));
  }

  generic_video_packetizer_c::set_headers();
}
示例#2
0
void
mpeg1_2_video_packetizer_c::create_private_data() {
  MPEGChunk *raw_seq_hdr = m_parser.GetRealSequenceHeader();
  if (NULL != raw_seq_hdr) {
    set_codec_private(raw_seq_hdr->GetPointer(), raw_seq_hdr->GetSize());
    rerender_track_headers();
  }
}
示例#3
0
void
mpeg4_p2_video_packetizer_c::extract_config_data(packet_cptr &packet) {
    if (m_ti.m_private_data)
        return;

    m_ti.m_private_data = memory_cptr{mpeg4::p2::parse_config_data(packet->data->get_buffer(), packet->data->get_size(), m_config_data)};
    if (!m_ti.m_private_data)
        mxerror_tid(m_ti.m_fname, m_ti.m_id, Y("Could not find the codec configuration data in the first MPEG-4 part 2 video frame. This track cannot be stored in native mode.\n"));

    fix_codec_string();
    set_codec_private(m_ti.m_private_data);
    rerender_track_headers();
}
示例#4
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;
}
示例#5
0
mpeg4_p10_video_packetizer_c::
mpeg4_p10_video_packetizer_c(generic_reader_c *p_reader,
                             track_info_c &p_ti,
                             double fps,
                             int width,
                             int height)
  : generic_video_packetizer_c{p_reader, p_ti, MKV_V_MPEG4_AVC, fps, width, height}
  , m_nalu_size_len_src{}
  , m_nalu_size_len_dst{}
  , m_max_nalu_size{}
{
  m_relaxed_timecode_checking = true;

  setup_nalu_size_len_change();

  set_codec_private(m_ti.m_private_data);
}
示例#6
0
void
mpeg4_p10_video_packetizer_c::extract_aspect_ratio() {
  auto result = mpeg4::p10::extract_par(m_ti.m_private_data);

  set_codec_private(result.new_avcc);

  if (!result.is_valid() || display_dimensions_or_aspect_ratio_set())
    return;

  auto par = static_cast<double>(result.numerator) / static_cast<double>(result.denominator);

  set_video_display_dimensions(1 <= par ? std::llround(m_width * par) : m_width,
                               1 <= par ? m_height                    : std::llround(m_height / par),
                               OPTION_SOURCE_BITSTREAM);

  mxinfo_tid(m_ti.m_fname, m_ti.m_id,
             boost::format(Y("Extracted the aspect ratio information from the MPEG-4 layer 10 (AVC) video data and set the display dimensions to %1%/%2%.\n"))
             % m_ti.m_display_width % m_ti.m_display_height);
}
示例#7
0
void
mpeg4_p10_video_packetizer_c::setup_nalu_size_len_change() {
  if (!m_ti.m_private_data || (5 > m_ti.m_private_data->get_size()))
    return;

  auto private_data   = m_ti.m_private_data->get_buffer();
  m_nalu_size_len_src = (private_data[4] & 0x03) + 1;
  m_nalu_size_len_dst = m_nalu_size_len_src;

  if (!m_ti.m_nalu_size_length || (m_ti.m_nalu_size_length == m_nalu_size_len_src))
    return;

  m_nalu_size_len_dst = m_ti.m_nalu_size_length;
  private_data[4]     = (private_data[4] & 0xfc) | (m_nalu_size_len_dst - 1);
  m_max_nalu_size     = 1ll << (8 * m_nalu_size_len_dst);

  set_codec_private(m_ti.m_private_data);

  mxverb(2, boost::format("mpeg4_p10: Adjusting NALU size length from %1% to %2%\n") % m_nalu_size_len_src % m_nalu_size_len_dst);
}
示例#8
0
void
mpeg4_p2_video_packetizer_c::extract_size(const unsigned char *buffer,
        int size) {
    if (m_size_extracted)
        return;

    if (0 != m_connected_to) {
        m_size_extracted = true;
        return;
    }

    uint32_t xtr_width, xtr_height;

    if (mpeg4::p2::extract_size(buffer, size, xtr_width, xtr_height)) {
        m_size_extracted = true;

        if (!m_reader->m_appending && ((xtr_width != static_cast<uint32_t>(m_hvideo_pixel_width)) || (xtr_height != static_cast<uint32_t>(m_hvideo_pixel_height)))) {
            set_video_pixel_width(xtr_width);
            set_video_pixel_height(xtr_height);

            if (!m_output_is_native && m_ti.m_private_data && (sizeof(alBITMAPINFOHEADER) <= m_ti.m_private_data->get_size())) {
                auto bih = reinterpret_cast<alBITMAPINFOHEADER *>(m_ti.m_private_data->get_buffer());
                put_uint32_le(&bih->bi_width,  xtr_width);
                put_uint32_le(&bih->bi_height, xtr_height);
                set_codec_private(m_ti.m_private_data);
            }

            m_hvideo_display_width  = -1;
            m_hvideo_display_height = -1;

            generic_packetizer_c::set_headers();
            rerender_track_headers();

            mxinfo_tid(m_ti.m_fname, m_ti.m_id,
                       boost::format(Y("The extracted values for video width and height from the MPEG4 layer 2 video data bitstream differ from what the values "
                                       "in the source container. The ones from the video data bitstream (%1%x%2%) will be used.\n")) % xtr_width % xtr_height);
        }

    } else if (50 <= m_frames_output)
        m_aspect_ratio_extracted = true;
}
示例#9
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();
  }
}