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(); }
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; }