Changed all extractors' handle_block() function to take a memory_cptr for the memory buffer, a couple of boolean flags and only handle one frame each (and not a complete block group). This is a preparation for easier simpleblock support.

This commit is contained in:
Moritz Bunkus 2005-10-19 16:52:55 +00:00
parent a3b0ee0816
commit 4987608d83
21 changed files with 377 additions and 353 deletions

View File

@ -195,8 +195,8 @@ handle_blockgroup(KaxBlockGroup &blockgroup,
kadditions = FINDFIRST(&blockgroup, KaxBlockAdditions);
// Pass the block to the extractor.
extractor->handle_block(*block, kadditions, block->GlobalTimecode(),
duration, bref, fref);
extractor->handle_block_v1(*block, kadditions, block->GlobalTimecode(),
duration, bref, fref);
}
static void

View File

@ -82,70 +82,69 @@ xtr_aac_c::create_file(xtr_base_c *_master,
}
void
xtr_aac_c::handle_block(KaxBlock &block,
xtr_aac_c::handle_frame(memory_cptr &frame,
KaxBlockAdditions *additions,
int64_t timecode,
int64_t duration,
int64_t bref,
int64_t fref) {
int64_t fref,
bool keyframe,
bool discardable,
bool references_valid) {
char adts[56 / 8];
int i, len;
int len;
for (i = 0; i < block.NumberFrames(); i++) {
DataBuffer &data = block.GetBuffer(i);
// Recreate the ADTS headers. What a fun. Like runing headlong into
// a solid wall. But less painful. Well such is life, you know.
// But then again I've just seen a beautiful girl walking by my
// window, and suddenly the world is a bright place. Everything's
// a matter of perspective. And if I didn't enjoy writing even this
// code then I wouldn't do it at all. So let's get to it!
// Recreate the ADTS headers. What a fun. Like runing headlong into
// a solid wall. But less painful. Well such is life, you know.
// But then again I've just seen a beautiful girl walking by my
// window, and suddenly the world is a bright place. Everything's
// a matter of perspective. And if I didn't enjoy writing even this
// code then I wouldn't do it at all. So let's get to it!
// sync word, 12 bits
adts[0] = 0xff;
adts[1] = 0xf0;
// sync word, 12 bits
adts[0] = 0xff;
adts[1] = 0xf0;
// ID, 1 bit
adts[1] |= id << 3;
// layer: 2 bits = 00
// ID, 1 bit
adts[1] |= id << 3;
// layer: 2 bits = 00
// protection absent: 1 bit = 1 (ASSUMPTION!)
adts[1] |= 1;
// protection absent: 1 bit = 1 (ASSUMPTION!)
adts[1] |= 1;
// profile, 2 bits
adts[2] = profile << 6;
// profile, 2 bits
adts[2] = profile << 6;
// sampling frequency index, 4 bits
adts[2] |= srate_idx << 2;
// sampling frequency index, 4 bits
adts[2] |= srate_idx << 2;
// private, 1 bit = 0 (ASSUMPTION!)
// private, 1 bit = 0 (ASSUMPTION!)
// channels, 3 bits
adts[2] |= (channels & 4) >> 2;
adts[3] = (channels & 3) << 6;
// channels, 3 bits
adts[2] |= (channels & 4) >> 2;
adts[3] = (channels & 3) << 6;
// original/copy, 1 bit = 0(ASSUMPTION!)
// original/copy, 1 bit = 0(ASSUMPTION!)
// home, 1 bit = 0 (ASSUMPTION!)
// home, 1 bit = 0 (ASSUMPTION!)
// copyright id bit, 1 bit = 0 (ASSUMPTION!)
// copyright id bit, 1 bit = 0 (ASSUMPTION!)
// copyright id start, 1 bit = 0 (ASSUMPTION!)
// copyright id start, 1 bit = 0 (ASSUMPTION!)
// frame length, 13 bits
len = frame->get_size() + 7;
adts[3] |= len >> 11;
adts[4] = (len >> 3) & 0xff;
adts[5] = (len & 7) << 5;
// frame length, 13 bits
len = data.Size() + 7;
adts[3] |= len >> 11;
adts[4] = (len >> 3) & 0xff;
adts[5] = (len & 7) << 5;
// adts buffer fullness, 11 bits, 0x7ff = VBR (ASSUMPTION!)
adts[5] |= 0x1f;
adts[6] = 0xfc;
// adts buffer fullness, 11 bits, 0x7ff = VBR (ASSUMPTION!)
adts[5] |= 0x1f;
adts[6] = 0xfc;
// number of raw frames, 2 bits, 0 (meaning 1 frame) (ASSUMPTION!)
// number of raw frames, 2 bits, 0 (meaning 1 frame) (ASSUMPTION!)
// Write the ADTS header and the data itself.
out->write(adts, 56 / 8);
out->write(data.Buffer(), data.Size());
}
// Write the ADTS header and the data itself.
out->write(adts, 56 / 8);
out->write(frame->get(), frame->get_size());
}

View File

@ -27,9 +27,10 @@ public:
xtr_aac_c(const string &_codec_id, int64_t _tid, track_spec_t &tspec);
virtual void create_file(xtr_base_c *_master, KaxTrackEntry &track);
virtual void handle_block(KaxBlock &block, KaxBlockAdditions *additions,
virtual void handle_frame(memory_cptr &frame, KaxBlockAdditions *additions,
int64_t timecode, int64_t duration, int64_t bref,
int64_t fref);
int64_t fref, bool keyframe, bool discardable,
bool references_valid);
};
#endif

View File

@ -77,18 +77,19 @@ xtr_avc_c::create_file(xtr_base_c *_master,
}
void
xtr_avc_c::handle_block(KaxBlock &block,
xtr_avc_c::handle_frame(memory_cptr &frame,
KaxBlockAdditions *additions,
int64_t timecode,
int64_t duration,
int64_t bref,
int64_t fref) {
int i, pos;
int64_t fref,
bool keyframe,
bool discardable,
bool references_valid) {
int pos;
binary *buf = (binary *)frame->get();
for (i = pos = 0; block.NumberFrames() > i; i++) {
DataBuffer &data = block.GetBuffer(i);
binary *buf = data.Buffer();
while (data.Size() > pos)
write_nal(buf, pos, data.Size(), nal_size_size);
}
pos = 0;
while (frame->get_size() > pos)
write_nal(buf, pos, frame->get_size(), nal_size_size);
}

View File

@ -27,9 +27,10 @@ public:
xtr_avc_c(const string &_codec_id, int64_t _tid, track_spec_t &tspec);
virtual void create_file(xtr_base_c *_master, KaxTrackEntry &track);
virtual void handle_block(KaxBlock &block, KaxBlockAdditions *additions,
virtual void handle_frame(memory_cptr &frame, KaxBlockAdditions *additions,
int64_t timecode, int64_t duration, int64_t bref,
int64_t fref);
int64_t fref, bool keyframe, bool discardable,
bool references_valid);
void write_nal(const binary *data, int &pos, int data_size,
int nal_size_size);
};

View File

@ -73,29 +73,26 @@ xtr_avi_c::create_file(xtr_base_c *_master,
}
void
xtr_avi_c::handle_block(KaxBlock &block,
xtr_avi_c::handle_frame(memory_cptr &frame,
KaxBlockAdditions *additions,
int64_t timecode,
int64_t duration,
int64_t bref,
int64_t fref) {
int i;
int64_t fref,
bool keyframe,
bool discardable,
bool references_valid) {
if (references_valid)
keyframe = bref == 0;
if (0 >= duration)
duration = default_duration;
AVI_write_frame(avi, (char *)frame->get(), frame->get_size(), keyframe);
for (i = 0; i < block.NumberFrames(); i++) {
DataBuffer &data = block.GetBuffer(i);
if (((double)duration / 1000000.0 - (1000.0 / fps)) >= 1.5) {
int k, nfr;
AVI_write_frame(avi, (char *)data.Buffer(), data.Size(),
bref != 0 ? 0 : 1);
if (((double)duration / 1000000.0 - (1000.0 / fps)) >= 1.5) {
int k, nfr;
nfr = irnd((double)duration / 1000000.0 * fps / 1000.0);
for (k = 2; k <= nfr; k++)
AVI_write_frame(avi, "", 0, 0);
}
nfr = irnd((double)duration / 1000000.0 * fps / 1000.0);
for (k = 2; k <= nfr; k++)
AVI_write_frame(avi, "", 0, 0);
}
}

View File

@ -33,9 +33,10 @@ public:
xtr_avi_c(const string &_codec_id, int64_t _tid, track_spec_t &tspec);
virtual void create_file(xtr_base_c *_master, KaxTrackEntry &track);
virtual void handle_block(KaxBlock &block, KaxBlockAdditions *additions,
virtual void handle_frame(memory_cptr &frame, KaxBlockAdditions *additions,
int64_t timecode, int64_t duration, int64_t bref,
int64_t fref);
int64_t fref, bool keyframe, bool discardable,
bool references_valid);
virtual void finish_file();
};

View File

@ -69,19 +69,50 @@ xtr_base_c::create_file(xtr_base_c *_master,
}
void
xtr_base_c::handle_block(KaxBlock &block,
xtr_base_c::handle_block_v1(KaxBlock &block,
KaxBlockAdditions *additions,
int64_t timecode,
int64_t duration,
int64_t bref,
int64_t fref) {
int i;
if (0 == block.NumberFrames())
return;
if (0 > duration)
duration = default_duration * block.NumberFrames();
for (i = 0; i < block.NumberFrames(); i++) {
int64_t this_timecode, this_duration;
if (0 > duration) {
this_timecode = timecode;
this_duration = duration;
} else {
this_timecode = timecode + i * duration / block.NumberFrames();
this_duration = duration / block.NumberFrames();
}
DataBuffer &data = block.GetBuffer(i);
memory_cptr frame(new memory_c(data.Buffer(), data.Size(), false));
handle_frame(frame, additions, this_timecode, this_duration, bref, fref,
false, false, true);
}
}
void
xtr_base_c::handle_frame(memory_cptr &frame,
KaxBlockAdditions *additions,
int64_t timecode,
int64_t duration,
int64_t bref,
int64_t fref) {
int i;
for (i = 0; i < block.NumberFrames(); i++) {
DataBuffer &data = block.GetBuffer(i);
out->write(data.Buffer(), data.Size());
bytes_written += data.Size();
}
int64_t fref,
bool keyframe,
bool discardable,
bool references_valid) {
out->write(frame->get(), frame->get_size());
bytes_written += frame->get_size();
}
void

View File

@ -45,9 +45,13 @@ public:
virtual ~xtr_base_c();
virtual void create_file(xtr_base_c *_master, KaxTrackEntry &track);
virtual void handle_block(KaxBlock &block, KaxBlockAdditions *additions,
virtual void handle_block_v1(KaxBlock &block, KaxBlockAdditions *additions,
int64_t timecode, int64_t duration, int64_t bref,
int64_t fref);
virtual void handle_frame(memory_cptr &frame, KaxBlockAdditions *additions,
int64_t timecode, int64_t duration, int64_t bref,
int64_t fref);
int64_t fref, bool keyframe, bool discardable,
bool references_valid);
virtual void finish_track();
virtual void finish_file();

View File

@ -50,7 +50,7 @@ xtr_oggbase_c::xtr_oggbase_c(const string &_codec_id,
int64_t _tid,
track_spec_t &tspec):
xtr_base_c(_codec_id, _tid, tspec),
packetno(2), buffered_data(NULL), buffered_size(0), previous_end(0) {
packetno(2), previous_end(0) {
}
void
@ -67,40 +67,31 @@ xtr_oggbase_c::create_file(xtr_base_c *_master,
}
void
xtr_oggbase_c::handle_block(KaxBlock &block,
xtr_oggbase_c::handle_frame(memory_cptr &frame,
KaxBlockAdditions *additions,
int64_t timecode,
int64_t duration,
int64_t bref,
int64_t fref) {
int i;
int64_t fref,
bool keyframe,
bool discardable,
bool references_valid) {
if (NULL != buffered_data.get()) {
ogg_packet op;
if (-1 == duration)
duration = default_duration * block.NumberFrames();
op.b_o_s = 0;
op.e_o_s = 0;
op.packetno = packetno;
op.packet = buffered_data->get();
op.bytes = buffered_data->get_size();
op.granulepos = timecode * sfreq / 1000000000;
ogg_stream_packetin(&os, &op);
write_pages();
for (i = 0; i < block.NumberFrames(); i++) {
DataBuffer &data = block.GetBuffer(i);
if (NULL != buffered_data) {
ogg_packet op;
op.b_o_s = 0;
op.e_o_s = 0;
op.packetno = packetno;
op.packet = buffered_data;
op.bytes = buffered_size;
// op.granulepos = (timecode / 1000000) * sfreq / 1000;
op.granulepos = (timecode + i * duration / block.NumberFrames()) *
sfreq / 1000000000;
ogg_stream_packetin(&os, &op);
write_pages();
safefree(buffered_data);
packetno++;
}
buffered_data = (unsigned char *)safememdup(data.Buffer(), data.Size());
buffered_size = data.Size();
packetno++;
}
buffered_data = memory_cptr(frame->clone());
previous_end = timecode + duration;
}
@ -108,7 +99,7 @@ void
xtr_oggbase_c::finish_file() {
ogg_packet op;
if (NULL == buffered_data)
if (NULL == buffered_data.get())
return;
// Set the "end of stream" marker on the last packet, handle it
@ -116,12 +107,11 @@ xtr_oggbase_c::finish_file() {
op.b_o_s = 0;
op.e_o_s = 1;
op.packetno = packetno;
op.packet = buffered_data;
op.bytes = buffered_size;
op.packet = buffered_data->get();
op.bytes = buffered_data->get_size();
// op.granulepos = (previous_end / 1000000) * sfreq / 1000;
op.granulepos = previous_end * sfreq / 1000000000;
ogg_stream_packetin(&os, &op);
safefree(buffered_data);
flush_pages();
ogg_stream_clear(&os);
}

View File

@ -32,8 +32,7 @@ class xtr_oggbase_c: public xtr_base_c {
public:
ogg_stream_state os;
int packetno;
unsigned char *buffered_data;
int buffered_size;
memory_cptr buffered_data;
int sfreq;
int64_t previous_end;
@ -41,9 +40,10 @@ public:
xtr_oggbase_c(const string &_codec_id, int64_t _tid, track_spec_t &tspec);
virtual void create_file(xtr_base_c *_master, KaxTrackEntry &track);
virtual void handle_block(KaxBlock &block, KaxBlockAdditions *additions,
virtual void handle_frame(memory_cptr &frame, KaxBlockAdditions *additions,
int64_t timecode, int64_t duration, int64_t bref,
int64_t fref);
int64_t fref, bool keyframe, bool discardable,
bool references_valid);
virtual void finish_file();
virtual void write_pages();

View File

@ -61,31 +61,31 @@ xtr_rmff_c::create_file(xtr_base_c *_master,
}
void
xtr_rmff_c::handle_block(KaxBlock &block,
xtr_rmff_c::handle_frame(memory_cptr &frame,
KaxBlockAdditions *additions,
int64_t timecode,
int64_t duration,
int64_t bref,
int64_t fref) {
int i;
rmff_frame_t *frame;
int64_t fref,
bool keyframe,
bool discardable,
bool references_valid) {
rmff_frame_t *rmff_frame;
for (i = 0; i < block.NumberFrames(); i++) {
DataBuffer &data = block.GetBuffer(i);
frame = rmff_allocate_frame(data.Size(), data.Buffer());
if (frame == NULL)
mxerror("Memory for a RealAudio/RealVideo frame could not be "
"allocated.\n");
frame->timecode = timecode / 1000000;
if (0 == bref)
frame->flags = RMFF_FRAME_FLAG_KEYFRAME;
if ('V' == codec_id[0])
rmff_write_packed_video_frame(rmtrack, frame);
else
rmff_write_frame(rmtrack, frame);
rmff_release_frame(frame);
}
rmff_frame = rmff_allocate_frame(frame->get_size(), frame->get());
if (rmff_frame == NULL)
mxerror("Memory for a RealAudio/RealVideo frame could not be "
"allocated.\n");
rmff_frame->timecode = timecode / 1000000;
if (references_valid)
keyframe = 0 == bref;
if (keyframe)
rmff_frame->flags = RMFF_FRAME_FLAG_KEYFRAME;
if ('V' == codec_id[0])
rmff_write_packed_video_frame(rmtrack, rmff_frame);
else
rmff_write_frame(rmtrack, rmff_frame);
rmff_release_frame(rmff_frame);
}
void

View File

@ -30,9 +30,10 @@ public:
xtr_rmff_c(const string &_codec_id, int64_t _tid, track_spec_t &tspec);
virtual void create_file(xtr_base_c *_master, KaxTrackEntry &track);
virtual void handle_block(KaxBlock &block, KaxBlockAdditions *additions,
virtual void handle_frame(memory_cptr &frame, KaxBlockAdditions *additions,
int64_t timecode, int64_t duration, int64_t bref,
int64_t fref);
int64_t fref, bool keyframe, bool discardable,
bool references_valid);
virtual void finish_file();
virtual void headers_done();
};

View File

@ -44,12 +44,15 @@ xtr_srt_c::create_file(xtr_base_c *_master,
#define LLD03 "%03" PRId64
void
xtr_srt_c::handle_block(KaxBlock &block,
xtr_srt_c::handle_frame(memory_cptr &frame,
KaxBlockAdditions *additions,
int64_t timecode,
int64_t duration,
int64_t bref,
int64_t fref) {
int64_t fref,
bool keyframe,
bool discardable,
bool references_valid) {
char *text;
int64_t start, end;
string buffer;
@ -60,15 +63,13 @@ xtr_srt_c::handle_block(KaxBlock &block,
duration = 1000000000;
}
DataBuffer &data = block.GetBuffer(0);
start = timecode / 1000000;
end = start + duration / 1000000;
++num_entries;
text = new char[data.Size() + 1];
memcpy(text, data.Buffer(), data.Size());
text[data.Size()] = 0;
text = new char[frame->get_size() + 1];
memcpy(text, frame->get(), frame->get_size());
text[frame->get_size()] = 0;
buffer = mxsprintf("%d\n"
LLD02 ":" LLD02 ":" LLD02 "," LLD03 " --> "
LLD02 ":" LLD02 ":" LLD02 "," LLD03 "\n"
@ -177,12 +178,15 @@ xtr_ssa_c::create_file(xtr_base_c *_master,
}
void
xtr_ssa_c::handle_block(KaxBlock &block,
xtr_ssa_c::handle_frame(memory_cptr &frame,
KaxBlockAdditions *additions,
int64_t timecode,
int64_t duration,
int64_t bref,
int64_t fref) {
int64_t fref,
bool keyframe,
bool discardable,
bool references_valid) {
int i, k, num;
char *s;
vector<string> fields;
@ -199,11 +203,10 @@ xtr_ssa_c::handle_block(KaxBlock &block,
start = timecode / 1000000;
end = start + duration / 1000000;
DataBuffer &data = block.GetBuffer(0);
s = (char *)safemalloc(data.Size() + 1);
s = (char *)safemalloc(frame->get_size() + 1);
memory_c af_s((unsigned char *)s, 0, true);
memcpy(s, data.Buffer(), data.Size());
s[data.Size()] = 0;
memcpy(s, frame->get(), frame->get_size());
s[frame->get_size()] = 0;
// Split the line into the fields.
// Specs say that the following fields are to put into the block:
@ -374,21 +377,18 @@ xtr_usf_c::create_file(xtr_base_c *_master,
}
void
xtr_usf_c::handle_block(KaxBlock &block,
xtr_usf_c::handle_frame(memory_cptr &frame,
KaxBlockAdditions *additions,
int64_t timecode,
int64_t duration,
int64_t bref,
int64_t fref) {
if (0 == block.NumberFrames())
return;
DataBuffer &data_buffer = block.GetBuffer(0);
int64_t fref,
bool keyframe,
bool discardable,
bool references_valid) {
usf_entry_t entry("", timecode, timecode + duration);
memory_cptr data(new memory_c(data_buffer.Buffer(), data_buffer.Size(),
false));
content_decoder.reverse(data, CONTENT_ENCODING_SCOPE_BLOCK);
entry.m_text.append((const char *)data->get(), data->get_size());
content_decoder.reverse(frame, CONTENT_ENCODING_SCOPE_BLOCK);
entry.m_text.append((const char *)frame->get(), frame->get_size());
m_entries.push_back(entry);
}

View File

@ -36,9 +36,10 @@ public:
xtr_srt_c(const string &_codec_id, int64_t _tid, track_spec_t &tspec);
virtual void create_file(xtr_base_c *_master, KaxTrackEntry &track);
virtual void handle_block(KaxBlock &block, KaxBlockAdditions *additions,
virtual void handle_frame(memory_cptr &frame, KaxBlockAdditions *additions,
int64_t timecode, int64_t duration, int64_t bref,
int64_t fref);
int64_t fref, bool keyframe, bool discardable,
bool references_valid);
};
class xtr_ssa_c: public xtr_base_c {
@ -65,9 +66,10 @@ public:
xtr_ssa_c(const string &_codec_id, int64_t _tid, track_spec_t &tspec);
virtual void create_file(xtr_base_c *_master, KaxTrackEntry &track);
virtual void handle_block(KaxBlock &block, KaxBlockAdditions *additions,
virtual void handle_frame(memory_cptr &frame, KaxBlockAdditions *additions,
int64_t timecode, int64_t duration, int64_t bref,
int64_t fref);
int64_t fref, bool keyframe, bool discardable,
bool references_valid);
virtual void finish_file();
};
@ -89,9 +91,10 @@ public:
xtr_usf_c(const string &_codec_id, int64_t _tid, track_spec_t &tspec);
virtual void create_file(xtr_base_c *_master, KaxTrackEntry &track);
virtual void handle_block(KaxBlock &block, KaxBlockAdditions *additions,
virtual void handle_frame(memory_cptr &frame, KaxBlockAdditions *additions,
int64_t timecode, int64_t duration, int64_t bref,
int64_t fref);
int64_t fref, bool keyframe, bool discardable,
bool references_valid);
virtual void finish_track();
virtual void finish_file();
};

View File

@ -48,20 +48,17 @@ xtr_tta_c::create_file(xtr_base_c *_master,
}
void
xtr_tta_c::handle_block(KaxBlock &block,
xtr_tta_c::handle_frame(memory_cptr &frame,
KaxBlockAdditions *additions,
int64_t timecode,
int64_t duration,
int64_t bref,
int64_t fref) {
int i;
for (i = 0; i < block.NumberFrames(); i++) {
DataBuffer &data = block.GetBuffer(i);
frame_sizes.push_back(data.Size());
out->write(data.Buffer(), data.Size());
}
int64_t fref,
bool keyframe,
bool discardable,
bool references_valid) {
frame_sizes.push_back(frame->get_size());
out->write(frame->get(), frame->get_size());
if (0 < duration)
last_duration = duration;

View File

@ -32,9 +32,10 @@ public:
xtr_tta_c(const string &_codec_id, int64_t _tid, track_spec_t &tspec);
virtual void create_file(xtr_base_c *_master, KaxTrackEntry &track);
virtual void handle_block(KaxBlock &block, KaxBlockAdditions *additions,
virtual void handle_frame(memory_cptr &frame, KaxBlockAdditions *additions,
int64_t timecode, int64_t duration, int64_t bref,
int64_t fref);
int64_t fref, bool keyframe, bool discardable,
bool references_valid);
virtual void finish_file();
};

View File

@ -115,122 +115,118 @@ xtr_vobsub_c::create_file(xtr_base_c *_master,
}
void
xtr_vobsub_c::handle_block(KaxBlock &block,
xtr_vobsub_c::handle_frame(memory_cptr &frame,
KaxBlockAdditions *additions,
int64_t timecode,
int64_t duration,
int64_t bref,
int64_t fref) {
int64_t fref,
bool keyframe,
bool discardable,
bool references_valid) {
static unsigned char padding_data[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff};
mpeg_es_header_t es;
mpeg_ps_header_t ps;
uint64_t c;
int i;
uint32_t size, padding, first;
xtr_vobsub_c *vmaster;
unsigned char *data;
if (NULL == master)
vmaster = this;
else
vmaster = static_cast<xtr_vobsub_c *>(master);
for (i = 0; i < block.NumberFrames(); i++) {
uint32_t size, padding, first;
DataBuffer &data_buffer = block.GetBuffer(i);
memory_cptr data_m(new memory_c(data_buffer.Buffer(), data_buffer.Size(),
false));
unsigned char *data;
content_decoder.reverse(frame, CONTENT_ENCODING_SCOPE_BLOCK);
data = frame->get();
size = frame->get_size();
content_decoder.reverse(data_m, CONTENT_ENCODING_SCOPE_BLOCK);
data = data_m->get();
size = data_m->get_size();
positions.push_back(vmaster->out->getFilePointer());
timecodes.push_back(timecode);
positions.push_back(vmaster->out->getFilePointer());
timecodes.push_back(timecode);
padding = (2048 - (size + sizeof(mpeg_ps_header_t) +
sizeof(mpeg_es_header_t))) & 2047;
first = size + sizeof(mpeg_ps_header_t) +
sizeof(mpeg_es_header_t) > 2048 ?
2048 - sizeof(mpeg_ps_header_t) - sizeof(mpeg_es_header_t) : size;
padding = (2048 - (size + sizeof(mpeg_ps_header_t) +
sizeof(mpeg_es_header_t))) & 2047;
first = size + sizeof(mpeg_ps_header_t) +
sizeof(mpeg_es_header_t) > 2048 ?
2048 - sizeof(mpeg_ps_header_t) - sizeof(mpeg_es_header_t) : size;
memset(&ps, 0, sizeof(mpeg_ps_header_t));
memset(&ps, 0, sizeof(mpeg_ps_header_t));
ps.pfx[2] = 0x01;
ps.pfx[3] = 0xba;
c = timecode * 9 / 100000;
ps.pfx[2] = 0x01;
ps.pfx[3] = 0xba;
c = timecode * 9 / 100000;
ps.scr[0] = 0x40 | ((uint8_t)(c >> 27) & 0x38) | 0x04 |
((uint8_t)(c >> 28) & 0x03);
ps.scr[1] = (uint8_t)(c >> 20);
ps.scr[2] = ((uint8_t)(c >> 12) & 0xf8) | 0x04 |
((uint8_t)(c >> 13) & 0x03);
ps.scr[3] = (uint8_t)(c >> 5);
ps.scr[4] = ((uint8_t)(c << 3) & 0xf8) | 0x04;
ps.scr[5] = 1;
ps.muxr[0] = 1;
ps.muxr[1] = 0x89;
ps.muxr[2] = 0xc3; // just some value
ps.stlen = 0xf8;
if ((padding < 8) && (first == size))
ps.stlen |= (uint8_t)padding;
memset(&es, 0, sizeof(mpeg_es_header_t));
es.pfx[2] = 1;
es.stream_id = 0xbd;
es.len[0] = (uint8_t)((first + 9) >> 8);
es.len[1] = (uint8_t)(first + 9);
es.flags[0] = 0x81;
es.flags[1] = 0x80;
es.hlen = 5;
es.pts[0] = 0x20 | ((uint8_t)(c >> 29) & 0x0e) | 0x01;
es.pts[1] = (uint8_t)(c >> 22);
es.pts[2] = ((uint8_t)(c >> 14) & 0xfe) | 0x01;
es.pts[3] = (uint8_t)(c >> 7);
es.pts[4] = (uint8_t)(c << 1) | 0x01;
if (NULL == master)
es.lidx = 0x20;
else
es.lidx = stream_id;
vmaster->out->write(&ps, sizeof(mpeg_ps_header_t));
if ((padding > 0) && (padding < 8) && (first == size))
vmaster->out->write(padding_data, padding);
vmaster->out->write(&es, sizeof(mpeg_es_header_t));
vmaster->out->write(data, first);
while (first < size) {
size -= first;
data += first;
padding = (2048 - (size + 10 + sizeof(mpeg_ps_header_t))) & 2047;
first = size + 10 + sizeof(mpeg_ps_header_t) > 2048 ?
2048 - 10 - sizeof(mpeg_ps_header_t) : size;
ps.scr[0] = 0x40 | ((uint8_t)(c >> 27) & 0x38) | 0x04 |
((uint8_t)(c >> 28) & 0x03);
ps.scr[1] = (uint8_t)(c >> 20);
ps.scr[2] = ((uint8_t)(c >> 12) & 0xf8) | 0x04 |
((uint8_t)(c >> 13) & 0x03);
ps.scr[3] = (uint8_t)(c >> 5);
ps.scr[4] = ((uint8_t)(c << 3) & 0xf8) | 0x04;
ps.scr[5] = 1;
ps.muxr[0] = 1;
ps.muxr[1] = 0x89;
ps.muxr[2] = 0xc3; // just some value
ps.stlen = 0xf8;
if ((padding < 8) && (first == size))
ps.stlen |= (uint8_t)padding;
memset(&es, 0, sizeof(mpeg_es_header_t));
es.pfx[2] = 1;
es.stream_id = 0xbd;
es.len[0] = (uint8_t)((first + 9) >> 8);
es.len[1] = (uint8_t)(first + 9);
es.flags[0] = 0x81;
es.flags[1] = 0x80;
es.hlen = 5;
es.pts[0] = 0x20 | ((uint8_t)(c >> 29) & 0x0e) | 0x01;
es.pts[1] = (uint8_t)(c >> 22);
es.pts[2] = ((uint8_t)(c >> 14) & 0xfe) | 0x01;
es.pts[3] = (uint8_t)(c >> 7);
es.pts[4] = (uint8_t)(c << 1) | 0x01;
if (NULL == master)
es.lidx = 0x20;
else
es.lidx = stream_id;
es.len[0] = (uint8_t)((first + 4) >> 8);
es.len[1] = (uint8_t)(first + 4);
es.flags[1] = 0;
es.hlen = 0;
es.pts[0] = es.lidx;
vmaster->out->write(&ps, sizeof(mpeg_ps_header_t));
if ((padding > 0) && (padding < 8) && (first == size))
vmaster->out->write(padding_data, padding);
vmaster->out->write(&es, sizeof(mpeg_es_header_t));
vmaster->out->write(&es, 10);
vmaster->out->write(data, first);
while (first < size) {
size -= first;
data += first;
padding = (2048 - (size + 10 + sizeof(mpeg_ps_header_t))) & 2047;
first = size + 10 + sizeof(mpeg_ps_header_t) > 2048 ?
2048 - 10 - sizeof(mpeg_ps_header_t) : size;
if ((padding < 8) && (first == size))
ps.stlen |= (uint8_t)padding;
es.len[0] = (uint8_t)((first + 4) >> 8);
es.len[1] = (uint8_t)(first + 4);
es.flags[1] = 0;
es.hlen = 0;
es.pts[0] = es.lidx;
vmaster->out->write(&ps, sizeof(mpeg_ps_header_t));
if ((padding > 0) && (padding < 8) && (first == size))
vmaster->out->write(padding_data, padding);
vmaster->out->write(&es, 10);
vmaster->out->write(data, first);
}
if (8 <= padding) {
padding -= 6;
es.stream_id = 0xbe;
es.len[0] = (uint8_t)(padding >> 8);
es.len[1] = (uint8_t)padding;
vmaster->out->write(&es, 6); // XXX
while (0 < padding) {
uint32_t todo = padding > 8 ? 8 : padding;
vmaster->out->write(padding_data, todo);
padding -= todo;
}
}
if (8 <= padding) {
padding -= 6;
es.stream_id = 0xbe;
es.len[0] = (uint8_t)(padding >> 8);
es.len[1] = (uint8_t)padding;
vmaster->out->write(&es, 6); // XXX
while (0 < padding) {
uint32_t todo = padding > 8 ? 8 : padding;
vmaster->out->write(padding_data, todo);
padding -= todo;
}
}
}

View File

@ -33,9 +33,10 @@ public:
xtr_vobsub_c(const string &_codec_id, int64_t _tid, track_spec_t &tspec);
virtual void create_file(xtr_base_c *_master, KaxTrackEntry &track);
virtual void handle_block(KaxBlock &block, KaxBlockAdditions *additions,
virtual void handle_frame(memory_cptr &frame, KaxBlockAdditions *additions,
int64_t timecode, int64_t duration, int64_t bref,
int64_t fref);
int64_t fref, bool keyframe, bool discardable,
bool references_valid);
virtual void finish_file();
virtual void write_idx(mm_io_c &idx, int index);
};

View File

@ -110,102 +110,101 @@ xtr_wavpack4_c::create_file(xtr_base_c *_master,
}
void
xtr_wavpack4_c::handle_block(KaxBlock &block,
xtr_wavpack4_c::handle_frame(memory_cptr &frame,
KaxBlockAdditions *additions,
int64_t timecode,
int64_t duration,
int64_t bref,
int64_t fref) {
int64_t fref,
bool keyframe,
bool discardable,
bool references_valid) {
binary wv_header[32], *mybuffer;
int i, data_size;
int data_size;
vector<uint32_t> flags;
for (i = 0; i < block.NumberFrames(); i++) {
DataBuffer &data = block.GetBuffer(i);
// build the main header
// build the main header
wv_header[0] = 'w';
wv_header[1] = 'v';
wv_header[2] = 'p';
wv_header[3] = 'k';
memcpy(&wv_header[8], version, 2); // version
wv_header[10] = 0; // track_no
wv_header[11] = 0; // index_no
wv_header[12] = 0xFF; // total_samples is unknown
wv_header[13] = 0xFF;
wv_header[14] = 0xFF;
wv_header[15] = 0xFF;
put_uint32_le(&wv_header[16], number_of_samples); // block_index
mybuffer = frame->get();
data_size = frame->get_size();
number_of_samples += get_uint32_le(mybuffer);
wv_header[0] = 'w';
wv_header[1] = 'v';
wv_header[2] = 'p';
wv_header[3] = 'k';
memcpy(&wv_header[8], version, 2); // version
wv_header[10] = 0; // track_no
wv_header[11] = 0; // index_no
wv_header[12] = 0xFF; // total_samples is unknown
wv_header[13] = 0xFF;
wv_header[14] = 0xFF;
wv_header[15] = 0xFF;
put_uint32_le(&wv_header[16], number_of_samples); // block_index
mybuffer = data.Buffer();
data_size = data.Size();
number_of_samples += get_uint32_le(mybuffer);
// rest of the header:
memcpy(&wv_header[20], mybuffer, 3 * sizeof(uint32_t));
// support multi-track files
if (channels > 2) {
uint32_t block_size = get_uint32_le(&mybuffer[12]);
// rest of the header:
memcpy(&wv_header[20], mybuffer, 3 * sizeof(uint32_t));
// support multi-track files
if (channels > 2) {
uint32_t block_size = get_uint32_le(&mybuffer[12]);
flags.clear();
put_uint32_le(&wv_header[4], block_size + 24); // ck_size
flags.clear();
put_uint32_le(&wv_header[4], block_size + 24); // ck_size
out->write(wv_header, 32);
flags.push_back(*(uint32_t *)&mybuffer[4]);
mybuffer += 16;
out->write(mybuffer, block_size);
mybuffer += block_size;
data_size -= block_size + 16;
while (data_size > 0) {
block_size = get_uint32_le(&mybuffer[8]);
memcpy(&wv_header[24], mybuffer, 8);
put_uint32_le(&wv_header[4], block_size + 24);
out->write(wv_header, 32);
flags.push_back(*(uint32_t *)&mybuffer[4]);
mybuffer += 16;
flags.push_back(*(uint32_t *)mybuffer);
mybuffer += 12;
out->write(mybuffer, block_size);
mybuffer += block_size;
data_size -= block_size + 16;
while (data_size > 0) {
block_size = get_uint32_le(&mybuffer[8]);
memcpy(&wv_header[24], mybuffer, 8);
put_uint32_le(&wv_header[4], block_size + 24);
out->write(wv_header, 32);
flags.push_back(*(uint32_t *)mybuffer);
mybuffer += 12;
out->write(mybuffer, block_size);
mybuffer += block_size;
data_size -= block_size + 12;
}
} else {
put_uint32_le(&wv_header[4], data_size + 12); // ck_size
out->write(wv_header, 32);
out->write(&mybuffer[12], data_size - 12); // the rest of the
data_size -= block_size + 12;
}
} else {
put_uint32_le(&wv_header[4], data_size + 12); // ck_size
out->write(wv_header, 32);
out->write(&mybuffer[12], data_size - 12); // the rest of the
}
// support hybrid mode data
if ((NULL != corr_out) && (NULL != additions)) {
KaxBlockMore *block_more = FINDFIRST(additions, KaxBlockMore);
// support hybrid mode data
if ((NULL != corr_out) && (NULL != additions)) {
KaxBlockMore *block_more = FINDFIRST(additions, KaxBlockMore);
if (block_more == NULL)
break;
KaxBlockAdditional *block_addition =
FINDFIRST(block_more, KaxBlockAdditional);
if (block_addition == NULL)
break;
if (block_more == NULL)
return;
KaxBlockAdditional *block_addition =
FINDFIRST(block_more, KaxBlockAdditional);
if (block_addition == NULL)
return;
data_size = block_addition->GetSize();
mybuffer = block_addition->GetBuffer();
if (channels > 2) {
size_t flags_index = 0;
data_size = block_addition->GetSize();
mybuffer = block_addition->GetBuffer();
if (channels > 2) {
size_t flags_index = 0;
while (data_size > 0) {
uint32_t block_size = get_uint32_le(&mybuffer[4]);
while (data_size > 0) {
uint32_t block_size = get_uint32_le(&mybuffer[4]);
put_uint32_le(&wv_header[4], block_size + 24); // ck_size
memcpy(&wv_header[24], &flags[flags_index++], 4); // flags
memcpy(&wv_header[28], mybuffer, 4); // crc
corr_out->write(wv_header, 32);
mybuffer += 8;
corr_out->write(mybuffer, block_size);
mybuffer += block_size;
data_size -= 8 + block_size;
}
} else {
put_uint32_le(&wv_header[4], data_size + 20); // ck_size
put_uint32_le(&wv_header[4], block_size + 24); // ck_size
memcpy(&wv_header[24], &flags[flags_index++], 4); // flags
memcpy(&wv_header[28], mybuffer, 4); // crc
corr_out->write(wv_header, 32);
corr_out->write(&mybuffer[4], data_size - 4);
mybuffer += 8;
corr_out->write(mybuffer, block_size);
mybuffer += block_size;
data_size -= 8 + block_size;
}
} else {
put_uint32_le(&wv_header[4], data_size + 20); // ck_size
memcpy(&wv_header[28], mybuffer, 4); // crc
corr_out->write(wv_header, 32);
corr_out->write(&mybuffer[4], data_size - 4);
}
}
}

View File

@ -42,9 +42,10 @@ public:
xtr_wavpack4_c(const string &_codec_id, int64_t _tid, track_spec_t &tspec);
virtual void create_file(xtr_base_c *_master, KaxTrackEntry &track);
virtual void handle_block(KaxBlock &block, KaxBlockAdditions *additions,
virtual void handle_frame(memory_cptr &frame, KaxBlockAdditions *additions,
int64_t timecode, int64_t duration, int64_t bref,
int64_t fref);
int64_t fref, bool keyframe, bool discardable,
bool references_valid);
virtual void finish_file();
};