mirror of
https://gitlab.com/mbunkus/mkvtoolnix.git
synced 2024-12-25 20:32:33 +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();
|
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
|
static void
|
||||||
handle_data(KaxBlock *block,
|
handle_data(KaxBlock *block,
|
||||||
int64_t block_duration,
|
int64_t block_duration,
|
||||||
@ -946,18 +842,16 @@ handle_data(KaxBlock *block,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case TYPEREAL:
|
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());
|
rmf_frame = rmff_allocate_frame(data.Size(), data.Buffer());
|
||||||
if (rmf_frame == NULL)
|
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;
|
rmf_frame->timecode = start;
|
||||||
if (!has_ref)
|
if (!has_ref)
|
||||||
rmf_frame->flags = RMFF_FRAME_FLAG_KEYFRAME;
|
rmf_frame->flags = RMFF_FRAME_FLAG_KEYFRAME;
|
||||||
|
if (track->track_type == 'v')
|
||||||
|
rmff_write_packed_video_frame(track->rmtrack, rmf_frame);
|
||||||
|
else
|
||||||
rmff_write_frame(track->rmtrack, rmf_frame);
|
rmff_write_frame(track->rmtrack, rmf_frame);
|
||||||
rmff_release_frame(rmf_frame);
|
rmff_release_frame(rmf_frame);
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user