Ejemplo n.º 1
0
void
timecode_factory_v2_c::parse(mm_io_c &in) {
  std::string line;
  std::map<int64_t, int64_t> dur_map;

  int64_t dur_sum          = 0;
  int line_no              = 0;
  double previous_timecode = 0;

  while (in.getline2(line)) {
    line_no++;
    strip(line);
    if ((line.length() == 0) || (line[0] == '#'))
      continue;

    double timecode;
    if (!parse_double(line.c_str(), timecode))
      mxerror(boost::format(Y("The line %1% of the timecode file '%2%' does not contain a valid floating point number.\n")) % line_no % m_file_name);

    if ((2 == m_version) && (timecode < previous_timecode))
      mxerror(boost::format(Y("The timecode v2 file '%1%' contains timecodes that are not ordered. "
                              "Due to a bug in mkvmerge versions up to and including v1.5.0 this was necessary "
                              "if the track to which the timecode file was applied contained B frames. "
                              "Starting with v1.5.1 mkvmerge now handles this correctly, and the timecodes in the timecode file must be ordered normally. "
                              "For example, the frame sequence 'IPBBP...' at 25 FPS requires a timecode file with "
                              "the first timecodes being '0', '40', '80', '120' etc and not '0', '120', '40', '80' etc.\n\n"
                              "If you really have to specify non-sorted timecodes then use the timecode format v4. "
                              "It is identical to format v2 but allows non-sorted timecodes.\n"))
              % in.get_file_name());

    previous_timecode = timecode;
    m_timecodes.push_back((int64_t)(timecode * 1000000));
    if (m_timecodes.size() > 1) {
      int64_t duration = m_timecodes[m_timecodes.size() - 1] - m_timecodes[m_timecodes.size() - 2];
      if (dur_map.find(duration) == dur_map.end())
        dur_map[duration] = 1;
      else
        dur_map[duration] = dur_map[duration] + 1;
      dur_sum += duration;
      m_durations.push_back(duration);
    }
  }

  if (m_timecodes.empty())
    mxerror(boost::format(Y("The timecode file '%1%' does not contain any valid entry.\n")) % m_file_name);

  dur_sum = -1;
  std::pair<int64_t, int64_t> entry;
  for (auto entry : dur_map) {
    if ((0 > dur_sum) || (dur_map[dur_sum] < entry.second))
      dur_sum = entry.first;
    mxverb(4, boost::format("ext_m_timecodes v2 dur_map %1% = %2%\n") % entry.first % entry.second);
  }
  mxverb(4, boost::format("ext_m_timecodes v2 max is %1% = %2%\n") % dur_sum % dur_map[dur_sum]);

  if (0 < dur_sum)
    m_default_fps = (double)1000000000.0 / dur_sum;

  m_durations.push_back(dur_sum);
}
Ejemplo n.º 2
0
void
flac_reader_c::flac_metadata_cb(const FLAC__StreamMetadata *metadata) {
  switch (metadata->type) {
    case FLAC__METADATA_TYPE_STREAMINFO:
      memcpy(&stream_info, &metadata->data.stream_info, sizeof(FLAC__StreamMetadata_StreamInfo));
      sample_rate     = metadata->data.stream_info.sample_rate;
      metadata_parsed = true;

      mxverb(2, boost::format("flac_reader: STREAMINFO block (%1% bytes):\n") % metadata->length);
      mxverb(2, boost::format("flac_reader:   sample_rate: %1% Hz\n")         % metadata->data.stream_info.sample_rate);
      mxverb(2, boost::format("flac_reader:   channels: %1%\n")               % metadata->data.stream_info.channels);
      mxverb(2, boost::format("flac_reader:   bits_per_sample: %1%\n")        % metadata->data.stream_info.bits_per_sample);

      break;
    default:
      mxverb(2,
             boost::format("%1% (%2%) block (%3% bytes)\n")
             % (  metadata->type == FLAC__METADATA_TYPE_PADDING        ? "PADDING"
                : metadata->type == FLAC__METADATA_TYPE_APPLICATION    ? "APPLICATION"
                : metadata->type == FLAC__METADATA_TYPE_SEEKTABLE      ? "SEEKTABLE"
                : metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT ? "VORBIS COMMENT"
                : metadata->type == FLAC__METADATA_TYPE_CUESHEET       ? "CUESHEET"
                :                                                        "UNDEFINED")
             % metadata->type % metadata->length);
      break;
  }
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
0
void
mpeg_ts_reader_c::read_headers() {
  try {
    size_t size_to_probe   = std::min(m_size, static_cast<uint64_t>(TS_PIDS_DETECT_SIZE));
    auto probe_buffer      = memory_c::alloc(size_to_probe);

    m_detected_packet_size = detect_packet_size(m_in.get(), size_to_probe);
    m_in->setFilePointer(0);

    mxverb(3, boost::format("mpeg_ts: Starting to build PID list. (packet size: %1%)\n") % m_detected_packet_size);

    mpeg_ts_track_ptr PAT(new mpeg_ts_track_c(*this));
    PAT->type = PAT_TYPE;
    tracks.push_back(PAT);

    unsigned char buf[TS_MAX_PACKET_SIZE]; // maximum TS packet size + 1

    bool done = m_in->eof();
    while (!done) {
      if (m_in->read(buf, m_detected_packet_size) != static_cast<unsigned int>(m_detected_packet_size))
        break;

      if (buf[0] != 0x47) {
        if (resync(m_in->getFilePointer() - m_detected_packet_size))
          continue;
        break;
      }

      parse_packet(buf);
      done  = PAT_found && PMT_found && (0 == es_to_process);
      done |= m_in->eof() || (m_in->getFilePointer() >= TS_PIDS_DETECT_SIZE);
    }
  } catch (...) {
  }
  mxverb(3, boost::format("mpeg_ts: Detection done on %1% bytes\n") % m_in->getFilePointer());

  m_in->setFilePointer(0, seek_beginning); // rewind file for later remux

  for (auto &track : tracks) {
    track->pes_payload->remove(track->pes_payload->get_size());
    track->processed        = false;
    track->data_ready       = false;
    track->pes_payload_size = 0;
    // track->timecode_offset = -1;
  }

  parse_clip_info_file();
  process_chapter_entries();

  show_demuxer_info();
}
Ejemplo n.º 5
0
bool
flac_header_extractor_c::extract() {
  mxverb(2, "flac_header_extraction: extract\n");
  if (!read_page()) {
    mxverb(2, "flac_header_extraction: read_page() failed.\n");
    return false;
  }

  int result = (int)FLAC__stream_decoder_process_until_end_of_stream(decoder);

  mxverb(2, boost::format("flac_header_extraction: extract, result: %1%, mdp: %2%, num_header_packets: %3%\n") % result % metadata_parsed % num_header_packets);

  return metadata_parsed;
}
Ejemplo n.º 6
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;
}
Ejemplo n.º 7
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();
}
Ejemplo n.º 8
0
file_status_e
ivf_reader_c::read(generic_packetizer_c *,
                   bool) {
  size_t remaining_bytes = m_size - m_in->getFilePointer();

  ivf::frame_header_t header;
  if ((sizeof(ivf::frame_header_t) > remaining_bytes) || (m_in->read(&header, sizeof(ivf::frame_header_t)) != sizeof(ivf::frame_header_t)))
    return flush_packetizers();

  remaining_bytes     -= sizeof(ivf::frame_header_t);
  uint32_t frame_size  = get_uint32_le(&header.frame_size);

  if (remaining_bytes < frame_size) {
    m_in->setFilePointer(0, seek_end);
    return flush_packetizers();
  }

  memory_cptr buffer = memory_c::alloc(frame_size);
  if (m_in->read(buffer->get_buffer(), frame_size) < frame_size) {
    m_in->setFilePointer(0, seek_end);
    return flush_packetizers();
  }

  int64_t timestamp = get_uint64_le(&header.timestamp) * 1000000000ull * m_frame_rate_den / m_frame_rate_num;

  mxverb(3, boost::format("r_ivf.cpp: key %5% header.ts %1% num %2% den %3% res %4%\n") % get_uint64_le(&header.timestamp) % m_frame_rate_num % m_frame_rate_den % timestamp % ivf::is_keyframe(buffer));

  PTZR0->process(new packet_t(buffer, timestamp));

  return FILE_STATUS_MOREDATA;
}
Ejemplo n.º 9
0
void
xtr_ivf_c::handle_frame(memory_cptr &frame,
                        KaxBlockAdditions *,
                        int64_t timecode,
                        int64_t,
                        int64_t,
                        int64_t,
                        bool,
                        bool,
                        bool) {
  m_content_decoder.reverse(frame, CONTENT_ENCODING_SCOPE_BLOCK);

  uint64_t frame_number = timecode * m_frame_rate_num / m_frame_rate_den / 1000000000ull;

  mxverb(2, boost::format("timecode %1% num %2% den %3% frame_number %4% calculated back %5%\n")
         % timecode % m_frame_rate_num % m_frame_rate_den % frame_number
         % (frame_number * 1000000000ull * m_frame_rate_den / m_frame_rate_num));

  ivf::frame_header_t frame_header;
  put_uint32_le(&frame_header.frame_size, frame->get_size());
  put_uint32_le(&frame_header.timestamp,  frame_number);

  m_out->write(&frame_header,       sizeof(frame_header));
  m_out->write(frame->get_buffer(), frame->get_size());

  ++m_frame_count;
}
Ejemplo n.º 10
0
static void
fhe_error_cb(const FLAC__StreamDecoder *,
             FLAC__StreamDecoderErrorStatus status,
             void *client_data) {
  ((flac_header_extractor_c *)client_data)->done = true;
  mxverb(2, boost::format("flac_header_extraction: error (%1%)\n") % (int)status);
}
Ejemplo n.º 11
0
bool
timecode_factory_v3_c::get_next(packet_cptr &packet) {
  bool result = false;

  if (m_durations[m_current_duration].is_gap) {
    // find the next non-gap
    size_t duration_index = m_current_duration;
    while (m_durations[duration_index].is_gap || (0 == m_durations[duration_index].duration)) {
      m_current_offset += m_durations[duration_index].duration;
      duration_index++;
    }
    m_current_duration = duration_index;
    result             = true;
    // yes, there is a gap before this frame
  }

  packet->assigned_timecode = m_current_offset + m_current_timecode;
  // If default_fps is 0 then the duration is unchanged, usefull for audio.
  if (m_durations[m_current_duration].fps && (!m_preserve_duration || (0 >= packet->duration)))
    packet->duration = (int64_t)(1000000000.0 / m_durations[m_current_duration].fps);

  packet->duration   /= packet->time_factor;
  m_current_timecode += packet->duration;

  if (m_current_timecode >= m_durations[m_current_duration].duration) {
    m_current_offset   += m_durations[m_current_duration].duration;
    m_current_timecode  = 0;
    m_current_duration++;
  }

  mxverb(3, boost::format("ext_timecodes v3: tc %1% dur %2%\n") % packet->assigned_timecode % packet->duration);

  return result;
}
Ejemplo n.º 12
0
int
mpeg_ts_track_c::new_stream_a_truehd() {
  if (!m_truehd_parser)
    m_truehd_parser = truehd_parser_cptr(new truehd_parser_c);

  static int added = 0;
  added += pes_payload->get_size();

  m_truehd_parser->add_data(pes_payload->get_buffer(), pes_payload->get_size());
  pes_payload->remove(pes_payload->get_size());

  while (m_truehd_parser->frame_available()) {
    truehd_frame_cptr frame = m_truehd_parser->get_next_frame();
    if (truehd_frame_t::sync != frame->m_type)
      continue;

    mxverb(2,
           boost::format("first TrueHD header channels %1% sampling_rate %2% samples_per_frame %3%\n")
           % frame->m_channels % frame->m_sampling_rate % frame->m_samples_per_frame);

    a_channels    = frame->m_channels;
    a_sample_rate = frame->m_sampling_rate;

    return 0;
  }

  return FILE_STATUS_MOREDATA;
}
Ejemplo n.º 13
0
int64_t
vc1::es_parser_c::get_next_timecode() {
  int64_t next_timecode = m_previous_timecode
                        + (m_num_timecodes + m_num_repeated_fields) * m_default_duration
                        - m_num_repeated_fields                     * m_default_duration / 2;

  if (is_timecode_available()) {
    mxverb(3,
           boost::format("\nvc1::es_parser_c::get_next_timecode(): provided timecode available; original next %1%, provided %2%\n")
           % format_timecode(next_timecode) % format_timecode(m_timecodes.front()));

    next_timecode         = m_timecodes.front();
    m_previous_timecode   = m_timecodes.front();
    m_num_timecodes       = 0;
    m_num_repeated_fields = 0;

    m_timecodes.pop_front();
    m_timecode_positions.pop_front();
  }

  m_num_timecodes += 1 + m_current_frame->header.repeat_frame;
  if (m_seqhdr.interlace_flag && m_current_frame->header.repeat_first_field_flag && !m_current_frame->contains_field)
    ++m_num_repeated_fields;

  return next_timecode;
}
Ejemplo n.º 14
0
static FLAC__StreamDecoderReadStatus
fhe_read_cb(const FLAC__StreamDecoder *,
            FLAC__byte buffer[],
            size_t *bytes,
            void *client_data) {
  ogg_packet op;

  flac_header_extractor_c *fhe = (flac_header_extractor_c *)client_data;
  if (fhe->done)
    return FLAC__STREAM_DECODER_READ_STATUS_ABORT;

  if (ogg_stream_packetout(&fhe->os, &op) != 1)
    if (!fhe->read_page() || (ogg_stream_packetout(&fhe->os, &op) != 1))
      return FLAC__STREAM_DECODER_READ_STATUS_ABORT;

  if (*bytes < static_cast<size_t>(op.bytes))
    mxerror(boost::format(Y("flac_header_extraction: bytes (%1%) < op.bytes (%2%). Could not read the FLAC headers.\n")) % *bytes % op.bytes);

  int offset = 0;

  if ((0 == fhe->num_packets) && (ofm_post_1_1_1 == fhe->mode) && (13 < op.bytes))
    offset = 9;

  memcpy(buffer, &op.packet[offset], op.bytes - offset);
  *bytes = op.bytes - offset;

  fhe->num_packets++;
  mxverb(2, boost::format("flac_header_extraction: read packet number %1% with %2% bytes and offset %3%\n") % fhe->num_packets % op.bytes % offset);

  return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
}
Ejemplo n.º 15
0
int
mpeg_ts_track_c::new_stream_v_avc() {
  if (!m_avc_parser) {
    m_avc_parser = mpeg4::p10::avc_es_parser_cptr(new mpeg4::p10::avc_es_parser_c);
    m_avc_parser->ignore_nalu_size_length_errors();

    if (map_has_key(reader.m_ti.m_nalu_size_lengths, reader.tracks.size()))
      m_avc_parser->set_nalu_size_length(reader.m_ti.m_nalu_size_lengths[0]);
    else if (map_has_key(reader.m_ti.m_nalu_size_lengths, -1))
      m_avc_parser->set_nalu_size_length(reader.m_ti.m_nalu_size_lengths[-1]);
  }

  mxverb(3, boost::format("new_stream_v_avc: packet size: %1%\n") % pes_payload->get_size());

  m_avc_parser->add_bytes(pes_payload->get_buffer(), pes_payload->get_size());

  if (!m_avc_parser->headers_parsed())
    return FILE_STATUS_MOREDATA;

  fourcc   = FOURCC('A', 'V', 'C', '1');
  v_width  = m_avc_parser->get_width();
  v_height = m_avc_parser->get_height();

  if (m_avc_parser->has_par_been_found()) {
    auto dimensions = m_avc_parser->get_display_dimensions();
    v_dwidth        = dimensions.first;
    v_dheight       = dimensions.second;
  }

  return 0;
}
Ejemplo n.º 16
0
static void
write_changes(options_cptr &options,
              kax_analyzer_c *analyzer) {
  std::vector<EbmlId> ids_to_write;
  ids_to_write.push_back(KaxInfo::ClassInfos.GlobalId);
  ids_to_write.push_back(KaxTracks::ClassInfos.GlobalId);
  ids_to_write.push_back(KaxTags::ClassInfos.GlobalId);
  ids_to_write.push_back(KaxChapters::ClassInfos.GlobalId);
  ids_to_write.push_back(KaxAttachments::ClassInfos.GlobalId);

  for (auto &id_to_write : ids_to_write) {
    for (auto &target : options->m_targets) {
      if (!target->get_level1_element())
        continue;

      EbmlMaster &l1_element = *target->get_level1_element();

      if (id_to_write != l1_element.Generic().GlobalId)
        continue;

      mxverb(2, boost::format(Y("Element %1% is written.\n")) % l1_element.Generic().DebugName);

      kax_analyzer_c::update_element_result_e result = l1_element.ListSize() ? analyzer->update_element(&l1_element, true) : analyzer->remove_elements(EbmlId(l1_element));
      if (kax_analyzer_c::uer_success != result)
        display_update_element_result(l1_element.Generic(), result);

      break;
    }
  }
}
Ejemplo n.º 17
0
int
mpeg_ts_track_c::new_stream_v_mpeg_1_2() {
  if (!m_m2v_parser) {
    m_m2v_parser = std::shared_ptr<M2VParser>(new M2VParser);
    m_m2v_parser->SetProbeMode();
  }

  m_m2v_parser->WriteData(pes_payload->get_buffer(), pes_payload->get_size());

  int state = m_m2v_parser->GetState();
  if (state != MPV_PARSER_STATE_FRAME) {
    mxverb(3, boost::format("new_stream_v_mpeg_1_2: no valid frame in %1% bytes\n") % pes_payload->get_size());
    return FILE_STATUS_MOREDATA;
  }

  MPEG2SequenceHeader seq_hdr = m_m2v_parser->GetSequenceHeader();
  std::shared_ptr<MPEGFrame> frame(m_m2v_parser->ReadFrame());
  if (!frame)
    return FILE_STATUS_MOREDATA;

  fourcc         = FOURCC('M', 'P', 'G', '0' + m_m2v_parser->GetMPEGVersion());
  v_interlaced   = !seq_hdr.progressiveSequence;
  v_version      = m_m2v_parser->GetMPEGVersion();
  v_width        = seq_hdr.width;
  v_height       = seq_hdr.height;
  v_frame_rate   = seq_hdr.frameOrFieldRate;
  v_aspect_ratio = seq_hdr.aspectRatio;

  if ((0 >= v_aspect_ratio) || (1 == v_aspect_ratio))
    v_dwidth = v_width;
  else
    v_dwidth = (int)(v_height * v_aspect_ratio);
  v_dheight  = v_height;

  MPEGChunk *raw_seq_hdr_chunk = m_m2v_parser->GetRealSequenceHeader();
  if (raw_seq_hdr_chunk) {
    mxverb(3, boost::format("new_stream_v_mpeg_1_2: sequence header size: %1%\n") % raw_seq_hdr_chunk->GetSize());
    raw_seq_hdr = memory_c::clone(raw_seq_hdr_chunk->GetPointer(), raw_seq_hdr_chunk->GetSize());
  }

  mxverb(3, boost::format("new_stream_v_mpeg_1_2: width: %1%, height: %2%\n") % v_width % v_height);
  if (v_width == 0 || v_height == 0)
    return FILE_STATUS_MOREDATA;

  return 0;
}
Ejemplo n.º 18
0
static FLAC__StreamDecoderWriteStatus
fhe_write_cb(const FLAC__StreamDecoder *,
             const FLAC__Frame *,
             const FLAC__int32 * const [],
             void *client_data) {
  mxverb(2, "flac_header_extraction: write cb\n");

  ((flac_header_extractor_c *)client_data)->done = true;
  return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
}
Ejemplo n.º 19
0
void
mm_write_cache_io_c::flush_cache() {
  if (0 == m_cache_pos)
    return;

  size_t bytes_written = mm_proxy_io_c::_write(m_cache, m_cache_pos);
  mxverb(2, boost::format("mm_write_cache_io_c::flush_cache(): requested %1% written %2%\n") % m_cache_pos % bytes_written);
  if (bytes_written != m_cache_pos)
    throw mtx::mm_io::insufficient_space_x();

  m_cache_pos = 0;
}
Ejemplo n.º 20
0
bool
timecode_factory_v1_c::get_next(packet_cptr &packet) {
  packet->assigned_timecode = get_at(m_frameno);
  if (!m_preserve_duration || (0 >= packet->duration))
    packet->duration = get_at(m_frameno + 1) - packet->assigned_timecode;

  m_frameno++;
  if ((m_frameno > m_ranges[m_current_range].end_frame) && (m_current_range < (m_ranges.size() - 1)))
    m_current_range++;

  mxverb(4, boost::format("ext_timecodes v1: tc %1% dur %2% for %3%\n") % packet->assigned_timecode % packet->duration % (m_frameno - 1));

  return false;
}
Ejemplo n.º 21
0
/** \brief Handle frame sequences in which too few timecodes are available

   This function gets called if mkvmerge wants to flush its frame queue
   but it doesn't have enough timecodes and/or durations available for
   each queued frame. This can happen in two cases:

   1. A picture sequence is found that mkvmerge does not support. An
      example: Two frames have been read. The first contained a
      P and a B frame (that's OK so far), but the second one contained
      another P or I frame without an intermediate dummy frame.

   2. The end of the file has been reached but the frame queue contains
      more frames than the timecode queue. For example: The last frame
      contained two frames, a P and a B frame. Right afterwards the
      end of the file is reached. In this case a dummy frame is missing.

   Both cases can be solved if the source file provides a FPS for this
   track. The other case is not supported.
*/
void
mpeg4_p2_video_packetizer_c::generate_timecode_and_duration() {
    if (0.0 >= m_fps) {
        // TODO: error
        mxexit(1);
    }

    if (m_available_timecodes.empty()) {
        m_previous_timecode = (int64_t)(m_previous_timecode + 1000000000.0 / m_fps);
        m_available_timecodes.push_back(timecode_duration_t(m_previous_timecode, (int64_t)(1000000000.0 / m_fps)));

        mxverb(3, boost::format("mpeg4_p2::flush_frames(): Needed new timecode %1%\n") % m_previous_timecode);
        ++m_statistics.m_num_generated_timecodes;
    }
}
Ejemplo n.º 22
0
int
mpeg_ts_track_c::new_stream_a_mpeg() {
  add_pes_payload_to_probe_data();

  mp3_header_t header;

  int offset = find_mp3_header(m_probe_data->get_buffer(), m_probe_data->get_size());
  if (-1 == offset)
    return FILE_STATUS_MOREDATA;

  decode_mp3_header(m_probe_data->get_buffer() + offset, &header);
  a_channels    = header.channels;
  a_sample_rate = header.sampling_frequency;
  fourcc        = FOURCC('M', 'P', '0' + header.layer, ' ');

  mxverb(3, boost::format("new_stream_a_mpeg: Channels: %1%, sample rate: %2%\n") %a_channels % a_sample_rate);
  return 0;
}
Ejemplo n.º 23
0
void
tta_reader_c::read_headers() {
  if (g_identifying)
    return;

  try {
    int tag_size = skip_id3v2_tag(*m_in);
    if (0 > tag_size)
      mxerror_fn(m_ti.m_fname, boost::format(Y("tta_reader: tag_size < 0 in the c'tor. %1%\n")) % BUGMSG);
    m_size -= tag_size;

    if (m_in->read(&header, sizeof(tta_file_header_t)) != sizeof(tta_file_header_t))
      mxerror_fn(m_ti.m_fname, Y("The file header is too short.\n"));

    uint64_t seek_sum  = m_in->getFilePointer() + 4 - tag_size;
    m_size            -= id3_tag_present_at_end(*m_in);

    uint32_t seek_point;

    do {
      seek_point  = m_in->read_uint32_le();
      seek_sum   += seek_point + 4;
      seek_points.push_back(seek_point);
    } while (seek_sum < m_size);

    mxverb(2,
           boost::format("tta: ch %1% bps %2% sr %3% dl %4% seek_sum %5% size %6% num %7%\n")
           % get_uint16_le(&header.channels)    % get_uint16_le(&header.bits_per_sample)
           % get_uint32_le(&header.sample_rate) % get_uint32_le(&header.data_length)
           % seek_sum      % m_size             % seek_points.size());

    if (seek_sum != m_size)
      mxerror_fn(m_ti.m_fname, Y("The seek table in this TTA file seems to be broken.\n"));

    m_in->skip(4);

    pos             = 0;
    m_ti.m_id       = 0;        // ID for this track.

  } catch (...) {
    throw mtx::input::open_x();
  }
  show_demuxer_info();
}
Ejemplo n.º 24
0
void
generic_packetizer_c::apply_factory_once(packet_cptr &packet) {
  if (!m_timestamp_factory) {
    packet->assigned_timecode = packet->timecode;
    packet->gap_following     = false;
  } else
    packet->gap_following     = m_timestamp_factory->get_next(packet);

  packet->factory_applied     = true;

  mxverb(4,
         boost::format("apply_factory_once(): source %1% t %2% tbf %3% at %4%\n")
         % packet->source->get_source_track_num() % packet->timecode % packet->timecode_before_factory % packet->assigned_timecode);

  m_max_timecode_seen           = std::max(m_max_timecode_seen, packet->assigned_timecode + packet->duration);
  m_reader->m_max_timecode_seen = std::max(m_max_timecode_seen, m_reader->m_max_timecode_seen);

  ++m_next_packet_wo_assigned_timecode;
}
Ejemplo n.º 25
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);
}
Ejemplo n.º 26
0
void
vc1::es_parser_c::handle_frame_packet(memory_cptr packet) {
  flush_frame();

  vc1::frame_header_t frame_header;
  if (!m_seqhdr_found || !vc1::parse_frame_header(packet->get_buffer(), packet->get_size(), frame_header, m_seqhdr))
    return;

  m_current_frame        = frame_cptr(new frame_t);
  m_current_frame->data  = packet;
  m_current_frame->data->grab();

  memcpy(&m_current_frame->header, &frame_header, sizeof(frame_header_t));

  if (!m_timecodes.empty())
    mxverb(2,
           boost::format("vc1::es_parser_c::handle_frame_packet: next provided timecode %1% next calculated timecode %2%\n")
           % format_timecode(m_timecodes.front()) % format_timecode(peek_next_calculated_timecode()));

}
Ejemplo n.º 27
0
bool
wav_dts_demuxer_c::probe(mm_io_cptr &io) {
  io->save_pos();
  int len = io->read(m_buf[m_cur_buf]->get_buffer(), DTS_READ_SIZE);
  io->restore_pos();

  if (detect_dts(m_buf[m_cur_buf]->get_buffer(), len, m_pack_14_16, m_swap_bytes)) {
    len     = decode_buffer(len);
    int pos = find_consecutive_dts_headers(m_buf[m_cur_buf]->get_buffer(), len, 5);
    if (0 <= pos) {
      if (0 > find_dts_header(m_buf[m_cur_buf]->get_buffer() + pos, len - pos, &m_dtsheader))
        return false;

      mxverb(3, boost::format("DTSinWAV: 14->16 %1% swap %2%\n") % m_pack_14_16 % m_swap_bytes);
      return true;
    }
  }

  return false;
}
Ejemplo n.º 28
0
int
mpeg_ts_track_c::new_stream_a_ac3() {
  add_pes_payload_to_probe_data();

  ac3::parser_c parser;
  parser.add_bytes(m_probe_data->get_buffer(), m_probe_data->get_size());
  if (!parser.frame_available())
    return FILE_STATUS_MOREDATA;

  ac3::frame_c header = parser.get_frame();

  mxverb(2,
         boost::format("first ac3 header bsid %1% channels %2% sample_rate %3% bytes %4% samples %5%\n")
         % header.m_bs_id % header.m_channels % header.m_sample_rate % header.m_bytes % header.m_samples);

  a_channels    = header.m_channels;
  a_sample_rate = header.m_sample_rate;
  a_bsid        = header.m_bs_id;

  return 0;
}
Ejemplo n.º 29
0
void
mpeg_es_reader_c::read_headers() {
  try {
    M2VParser parser;

    // Let's find the first frame. We need its information like
    // resolution, MPEG version etc.
    parser.SetProbeMode();
    if (!read_frame(parser, *m_in, 1024 * 1024))
      throw mtx::input::header_parsing_x();

    m_in->setFilePointer(0);

    MPEG2SequenceHeader seq_hdr = parser.GetSequenceHeader();
    version                     = parser.GetMPEGVersion();
    interlaced                  = !seq_hdr.progressiveSequence;
    width                       = seq_hdr.width;
    height                      = seq_hdr.height;
    frame_rate                  = seq_hdr.progressiveSequence ? seq_hdr.frameOrFieldRate : seq_hdr.frameOrFieldRate * 2.0f;
    aspect_ratio                = seq_hdr.aspectRatio;

    if ((0 >= aspect_ratio) || (1 == aspect_ratio))
      dwidth = width;
    else
      dwidth = (int)(height * aspect_ratio);
    dheight = height;

    MPEGChunk *raw_seq_hdr = parser.GetRealSequenceHeader();
    if (raw_seq_hdr) {
      m_ti.m_private_data = (unsigned char *)safememdup(raw_seq_hdr->GetPointer(), raw_seq_hdr->GetSize());
      m_ti.m_private_size = raw_seq_hdr->GetSize();
    }

    mxverb(2, boost::format("mpeg_es_reader: version %1% width %2% height %3% FPS %4% AR %5%\n") % version % width % height % frame_rate % aspect_ratio);

  } catch (mtx::mm_io::exception &) {
    throw mtx::input::open_x();
  }
  show_demuxer_info();
}
Ejemplo n.º 30
0
file_status_e
tta_reader_c::read(generic_packetizer_c *,
                   bool) {
  if (seek_points.size() <= pos)
    return flush_packetizers();

  unsigned char *buf = (unsigned char *)safemalloc(seek_points[pos]);
  int nread          = m_in->read(buf, seek_points[pos]);

  if (0 >= nread)
    return flush_packetizers();
  pos++;

  memory_cptr mem(new memory_c(buf, nread, true));
  if (seek_points.size() <= pos) {
    double samples_left = (double)get_uint32_le(&header.data_length) - (seek_points.size() - 1) * TTA_FRAME_TIME * get_uint32_le(&header.sample_rate);
    mxverb(2, boost::format("tta: samples_left %1%\n") % samples_left);

    PTZR0->process(new packet_t(mem, -1, irnd(samples_left * 1000000000.0l / get_uint32_le(&header.sample_rate))));
  } else
    PTZR0->process(new packet_t(mem));

  return seek_points.size() <= pos ? flush_packetizers() : FILE_STATUS_MOREDATA;
}