Working MPEG-1 PS to Matroska transmuxing :)

This commit is contained in:
Moritz Bunkus 2004-12-28 21:00:32 +00:00
parent c3ada08d26
commit 04c8fd8c88
2 changed files with 132 additions and 19 deletions

View File

@ -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

View File

@ -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 &timestamp);
virtual bool parse_packet(int id, int64_t &timestamp, 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);