mirror of
https://gitlab.com/mbunkus/mkvtoolnix.git
synced 2024-12-24 20:01:53 +00:00
Moved the "unpack RealVideo frames" functions to librmff.
This commit is contained in:
parent
f606c368f2
commit
73d3e05184
@ -575,110 +575,6 @@ create_output_files() {
|
||||
set_rmff_headers();
|
||||
}
|
||||
|
||||
static void
|
||||
unpack_real_video_frames(kax_track_t *track,
|
||||
unsigned char *src,
|
||||
uint32_t size,
|
||||
uint32_t timecode,
|
||||
bool is_key) {
|
||||
unsigned char *src_ptr, *ptr, *dst;
|
||||
int num_subpackets, i, offset, total_len;
|
||||
vector<uint32_t> packet_offsets, packet_lengths;
|
||||
rmff_frame_t *frame;
|
||||
|
||||
track->packetno++;
|
||||
src_ptr = src;
|
||||
num_subpackets = *src_ptr + 1;
|
||||
src_ptr++;
|
||||
if (size < (num_subpackets * 8 + 1)) {
|
||||
mxwarn("RealVideo unpacking failed: frame size too small. Could not "
|
||||
"extract sub packet offsets. Skipping a frame.\n");
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < num_subpackets; i++) {
|
||||
src_ptr += 4;
|
||||
packet_offsets.push_back(get_uint32(src_ptr));
|
||||
src_ptr += 4;
|
||||
}
|
||||
if ((packet_offsets[packet_offsets.size() - 1] + (src_ptr - src)) >= size) {
|
||||
mxwarn("RealVideo unpacking failed: frame size too small. Expected at "
|
||||
"least %u bytes, but the frame contains only %u. Skipping this "
|
||||
"frame.\n", packet_offsets[packet_offsets.size() - 1] +
|
||||
(src_ptr - src), size);
|
||||
return;
|
||||
}
|
||||
total_len = size - (src_ptr - src);
|
||||
for (i = 0; i < (num_subpackets - 1); i++)
|
||||
packet_lengths.push_back(packet_offsets[i + 1] - packet_offsets[i]);
|
||||
packet_lengths.push_back(total_len -
|
||||
packet_offsets[packet_offsets.size() - 1]);
|
||||
|
||||
dst = (unsigned char *)safemalloc(size * 2);
|
||||
for (i = 0; i < num_subpackets; i++) {
|
||||
ptr = dst;
|
||||
if (num_subpackets == 1) {
|
||||
*ptr = 0xc0; // complete frame
|
||||
ptr++;
|
||||
|
||||
} else {
|
||||
*ptr = (num_subpackets >> 1) & 0x7f; // number of subpackets
|
||||
if (i == (num_subpackets - 1)) // last fragment?
|
||||
*ptr |= 0x80;
|
||||
ptr++;
|
||||
|
||||
*ptr = i + 1; // fragment number
|
||||
*ptr |= ((num_subpackets & 0x01) << 7); // number of subpackets
|
||||
ptr++;
|
||||
}
|
||||
|
||||
// total packet length:
|
||||
if (total_len > 0x3fff) {
|
||||
put_uint16_be(ptr, ((total_len & 0x3fff0000) >> 16));
|
||||
ptr += 2;
|
||||
put_uint16_be(ptr, total_len & 0x0000ffff);
|
||||
} else
|
||||
put_uint16_be(ptr, 0x4000 | total_len);
|
||||
ptr += 2;
|
||||
|
||||
// fragment offset from beginning/end:
|
||||
if (num_subpackets == 1)
|
||||
offset = timecode;
|
||||
else if (i < (num_subpackets - 1))
|
||||
offset = packet_offsets[i];
|
||||
else
|
||||
// If it's the last packet then the 'offset' is the fragment's length.
|
||||
offset = packet_lengths[i];
|
||||
|
||||
if (offset > 0x3fff) {
|
||||
put_uint16_be(ptr, ((offset & 0x3fff0000) >> 16));
|
||||
ptr += 2;
|
||||
put_uint16_be(ptr, offset & 0x0000ffff);
|
||||
} else
|
||||
put_uint16_be(ptr, 0x4000 | offset);
|
||||
ptr += 2;
|
||||
|
||||
// sequence number = frame number & 0xff
|
||||
*ptr = (track->packetno - 1) & 0xff;
|
||||
ptr++;
|
||||
|
||||
memcpy(ptr, src_ptr, packet_lengths[i]);
|
||||
src_ptr += packet_lengths[i];
|
||||
ptr += packet_lengths[i];
|
||||
|
||||
frame = rmff_allocate_frame(ptr - dst, dst);
|
||||
if (frame == NULL)
|
||||
mxerror("Memory allocation error: Could not get a rmff_frame_t.\n");
|
||||
frame->timecode = timecode;
|
||||
if (is_key)
|
||||
frame->flags = RMFF_FRAME_FLAG_KEYFRAME;
|
||||
if (rmff_write_frame(track->rmtrack, frame) != RMFF_ERR_OK)
|
||||
mxwarn("Could not write a RealVideo fragment.\n");
|
||||
rmff_release_frame(frame);
|
||||
track->subpacketno++;
|
||||
}
|
||||
safefree(dst);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_data(KaxBlock *block,
|
||||
int64_t block_duration,
|
||||
@ -946,19 +842,17 @@ handle_data(KaxBlock *block,
|
||||
break;
|
||||
|
||||
case TYPEREAL:
|
||||
if (track->track_type == 'v') {
|
||||
unpack_real_video_frames(track, data.Buffer(), data.Size(), start,
|
||||
!has_ref);
|
||||
break;
|
||||
}
|
||||
|
||||
rmf_frame = rmff_allocate_frame(data.Size(), data.Buffer());
|
||||
if (rmf_frame == NULL)
|
||||
mxerror("Could not allocate memory for a RealAudio frame.\n");
|
||||
mxerror("Could not allocate memory for a RealAudio/RealVideo "
|
||||
"frame.\n");
|
||||
rmf_frame->timecode = start;
|
||||
if (!has_ref)
|
||||
rmf_frame->flags = RMFF_FRAME_FLAG_KEYFRAME;
|
||||
rmff_write_frame(track->rmtrack, rmf_frame);
|
||||
if (track->track_type == 'v')
|
||||
rmff_write_packed_video_frame(track->rmtrack, rmf_frame);
|
||||
else
|
||||
rmff_write_frame(track->rmtrack, rmf_frame);
|
||||
rmff_release_frame(rmf_frame);
|
||||
break;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user