diff --git a/src/input/r_mpeg.cpp b/src/input/r_mpeg.cpp index e6434896f..2623a8d30 100644 --- a/src/input/r_mpeg.cpp +++ b/src/input/r_mpeg.cpp @@ -27,6 +27,8 @@ #include "mp3_common.h" #include "r_mpeg.h" #include "smart_pointers.h" +#include "p_ac3.h" +#include "p_mp3.h" #include "p_video.h" #define PROBESIZE 4 @@ -146,7 +148,7 @@ mpeg_es_reader_c::create_packetizer(int64_t) { (int)(height * aspect_ratio), height, ti)); - mxinfo(FMT_TID "Using the MPEG 1/2 video output module.\n", + mxinfo(FMT_TID "Using the MPEG-1/2 video output module.\n", ti->fname.c_str(), (int64_t)0); } @@ -156,8 +158,8 @@ mpeg_es_reader_c::read(generic_packetizer_c *, unsigned char *chunk; int num_read; - chunk = (unsigned char *)safemalloc(20000); - num_read = mm_io->read(chunk, 20000); + chunk = (unsigned char *)safemalloc(6022); + num_read = mm_io->read(chunk, 6022); if (num_read <= 0) { safefree(chunk); return FILE_STATUS_DONE; @@ -351,6 +353,8 @@ mpeg_ps_reader_c::mpeg_ps_reader_c(track_info_c *nti) mxverb(3, "%02x ", i); mxverb(3, "\n"); + mm_io->setFilePointer(0, seek_beginning); + } catch (exception &ex) { throw error_c("mpeg_ps_reader: Could not open the file."); } @@ -454,6 +458,7 @@ mpeg_ps_reader_c::found_new_stream(int id) { throw false; mpeg_ps_track_ptr track(new mpeg_ps_track_t); + track->first_timecode = timecode; if (id < 0xe0) { track->type = 'a'; @@ -537,6 +542,7 @@ mpeg_ps_reader_c::found_new_stream(int id) { throw "Error parsing the first AC3 audio frame."; track->a_channels = header.channels; track->a_sample_rate = header.sample_rate; + track->a_bsid = header.bsid; // } else if (track->fourcc == FOURCC('D', 'T', 'S', ' ')) { @@ -563,14 +569,13 @@ mpeg_ps_reader_c::found_new_stream(int id) { } bool -mpeg_ps_reader_c::find_next_packet_for_id(int id) { +mpeg_ps_reader_c::find_next_packet(int &id) { try { uint32_t header; header = mm_io->read_uint32_be(); while (1) { - uint8_t stream_id, byte; - uint16_t pes_packet_length; + uint8_t byte; switch (header) { case MPEGVIDEO_PACKET_START_CODE: @@ -610,14 +615,8 @@ mpeg_ps_reader_c::find_next_packet_for_id(int id) { if (!mpeg_is_start_code(header)) return false; - stream_id = header & 0xff; - if (stream_id == id) - return true; - - pes_packet_length = mm_io->read_uint16_be(); - mm_io->skip(pes_packet_length); - - header = mm_io->read_uint32_be(); + id = header & 0xff; + return true; break; } @@ -627,19 +626,129 @@ mpeg_ps_reader_c::find_next_packet_for_id(int id) { } } +bool +mpeg_ps_reader_c::find_next_packet_for_id(int id) { + int new_id; + + try { + while (find_next_packet(new_id)) { + if (id == new_id) + return true; + mm_io->skip(mm_io->read_uint16_be()); + } + } catch(...) { + } + return false; +} + void -mpeg_ps_reader_c::create_packetizer(int64_t) { +mpeg_ps_reader_c::create_packetizer(int64_t id) { + if ((id < 0) || (id >= tracks.size())) + return; + if (tracks[id]->ptzr >= 0) + return; + if (!demuxing_requested(tracks[id]->type, id)) + return; + + mpeg_ps_track_ptr &track = tracks[id]; + if (track->type == 'a') { + if ((track->fourcc == FOURCC('M', 'P', '1', ' ')) || + (track->fourcc == FOURCC('M', 'P', '2', ' ')) || + (track->fourcc == FOURCC('M', 'P', '3', ' '))) { + track->ptzr = + add_packetizer(new mp3_packetizer_c(this, track->a_sample_rate, + track->a_channels, true, ti)); + if (verbose) + mxinfo(FMT_TID "Using the MPEG audio output module.\n", + ti->fname.c_str(), id); + + } else if (track->fourcc == FOURCC('A', 'C', '3', ' ')) { + track->ptzr = + add_packetizer(new ac3_packetizer_c(this, track->a_sample_rate, + track->a_channels, + track->a_bsid, ti)); + if (verbose) + mxinfo(FMT_TID "Using the AC3 output module.\n", + ti->fname.c_str(), id); + + } else + mxerror("mpeg_ps_reader: Should not have happened #1. %s", BUGMSG); + + } else { // if (track->type == 'a') + if ((track->fourcc == FOURCC('m', 'p', 'g', '1')) || + (track->fourcc == FOURCC('m', 'p', 'g', '2'))) { + mpeg_12_video_packetizer_c *ptzr; + + ti->private_data = track->raw_seq_hdr; + ti->private_size = track->raw_seq_hdr_size; + ptzr = + new mpeg_12_video_packetizer_c(this, track->v_version, + track->v_frame_rate, + track->v_width, track->v_height, + (int)(track->v_height * + track->v_aspect_ratio), + track->v_height, ti); + track->ptzr = add_packetizer(ptzr); + ti->private_data = NULL; + ti->private_size = 0; + + if (verbose) + mxinfo(FMT_TID "Using the MPEG-1/2 video output module.\n", + ti->fname.c_str(), id); + + } else + mxerror("mpeg_ps_reader: Should not have happened #2. %s", BUGMSG); + } +} + +void +mpeg_ps_reader_c::create_packetizers() { + int i; + + for (i = 0; i < tracks.size(); i++) + create_packetizer(i); } file_status_e mpeg_ps_reader_c::read(generic_packetizer_c *, bool) { + int64_t timecode, packet_pos; + int new_id, length; + unsigned char *buf; + + try { + while (find_next_packet(new_id)) { + if ((id2idx[new_id] == -1) || + (tracks[id2idx[new_id]]->ptzr == -1)) { + mm_io->skip(mm_io->read_uint16_be()); + continue; + } + packet_pos = mm_io->getFilePointer() - 4; + if (!parse_packet(new_id, timecode, length)) + return FILE_STATUS_DONE; + + mxverb(2, "mpeg_ps: packet for %d length %d at %lld\n", new_id, length, + packet_pos); + + buf = (unsigned char *)safemalloc(length); + if (mm_io->read(buf, length) != length) { + safefree(buf); + return FILE_STATUS_DONE; + } + + memory_c mem(buf, length, true); + PTZR(tracks[id2idx[new_id]]->ptzr)->process(mem); + + return FILE_STATUS_MOREDATA; + } + } catch(...) { + } return FILE_STATUS_DONE; } int mpeg_ps_reader_c::get_progress() { - return 100 * bytes_processed / size; + return 100 * mm_io->getFilePointer() / size; } void diff --git a/src/input/r_mpeg.h b/src/input/r_mpeg.h index f08868716..cc19110b7 100644 --- a/src/input/r_mpeg.h +++ b/src/input/r_mpeg.h @@ -56,19 +56,21 @@ struct mpeg_ps_track_t { char type; // 'v' for video, 'a' for audio, 's' for subs uint32_t fourcc; + int64_t first_timecode; + int v_version, v_width, v_height; double v_frame_rate, v_aspect_ratio; unsigned char *raw_seq_hdr; int raw_seq_hdr_size; - int a_channels, a_sample_rate, a_bits_per_sample; + int a_channels, a_sample_rate, a_bits_per_sample, a_bsid; mpeg_ps_track_t(): - ptzr(0), type(0), fourcc(0), + ptzr(-1), type(0), fourcc(0), v_version(0), v_width(0), v_height(0), v_frame_rate(0), v_aspect_ratio(0), raw_seq_hdr(NULL), raw_seq_hdr_size(0), - a_channels(0), a_sample_rate(0), a_bits_per_sample(0) { + a_channels(0), a_sample_rate(0), a_bits_per_sample(0), a_bsid(0) { }; ~mpeg_ps_track_t() { safefree(raw_seq_hdr); @@ -95,11 +97,13 @@ public: virtual int get_progress(); virtual void identify(); virtual void create_packetizer(int64_t id); + virtual void create_packetizers(); virtual void found_new_stream(int id); virtual bool read_timestamp(int c, int64_t ×tamp); virtual bool parse_packet(int id, int64_t ×tamp, int &size); + virtual bool find_next_packet(int &id); virtual bool find_next_packet_for_id(int id); static int probe_file(mm_io_c *mm_io, int64_t size);