mirror of
https://gitlab.com/mbunkus/mkvtoolnix.git
synced 2024-12-25 04:11:44 +00:00
rename namespace mpeg4::p2 to mtx::mpeg4_p2
This commit is contained in:
parent
b656e22ff8
commit
7fe61d48c6
@ -15,31 +15,26 @@
|
||||
#include "common/common_pch.h"
|
||||
|
||||
#include "common/bit_reader.h"
|
||||
#include "common/debugging.h"
|
||||
#include "common/endian.h"
|
||||
#include "common/math.h"
|
||||
#include "common/mm_io.h"
|
||||
#include "common/mm_mem_io.h"
|
||||
#include "common/mpeg4_p2.h"
|
||||
|
||||
namespace mpeg4 {
|
||||
namespace p2 {
|
||||
static bool find_vol_header(mtx::bits::reader_c &bits);
|
||||
static bool parse_vol_header(const unsigned char *buffer, int buffer_size, config_data_t &config_data);
|
||||
static bool extract_par_internal(const unsigned char *buffer, int buffer_size, uint32_t &par_num, uint32_t &par_den);
|
||||
static void parse_frame(video_frame_t &frame, const unsigned char *buffer, const mpeg4::p2::config_data_t &config_data);
|
||||
}
|
||||
}
|
||||
namespace mtx::mpeg4_p2 {
|
||||
|
||||
mpeg4::p2::config_data_t::config_data_t()
|
||||
: m_time_increment_bits(0)
|
||||
, m_width(0)
|
||||
, m_height(0)
|
||||
, m_width_height_found(false)
|
||||
{
|
||||
}
|
||||
namespace {
|
||||
|
||||
static bool
|
||||
mpeg4::p2::find_vol_header(mtx::bits::reader_c &bits) {
|
||||
debugging_option_c s_debug{"mpeg4_p2"};
|
||||
|
||||
bool find_vol_header(mtx::bits::reader_c &bits);
|
||||
bool parse_vol_header(const unsigned char *buffer, int buffer_size, config_data_t &config_data);
|
||||
bool extract_par_internal(const unsigned char *buffer, int buffer_size, uint32_t &par_num, uint32_t &par_den);
|
||||
void parse_frame(video_frame_t &frame, const unsigned char *buffer, const config_data_t &config_data);
|
||||
|
||||
bool
|
||||
find_vol_header(mtx::bits::reader_c &bits) {
|
||||
uint32_t marker;
|
||||
|
||||
while (!bits.eof()) {
|
||||
@ -62,10 +57,10 @@ mpeg4::p2::find_vol_header(mtx::bits::reader_c &bits) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
mpeg4::p2::parse_vol_header(const unsigned char *buffer,
|
||||
int buffer_size,
|
||||
mpeg4::p2::config_data_t &config_data) {
|
||||
bool
|
||||
parse_vol_header(unsigned char const *buffer,
|
||||
int buffer_size,
|
||||
config_data_t &config_data) {
|
||||
mtx::bits::reader_c bits(buffer, buffer_size);
|
||||
|
||||
if (!find_vol_header(bits))
|
||||
@ -129,43 +124,11 @@ mpeg4::p2::parse_vol_header(const unsigned char *buffer,
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Extract the widht and height from a MPEG4 video frame
|
||||
|
||||
This function searches a buffer containing a MPEG4 video frame
|
||||
for the width and height.
|
||||
|
||||
\param buffer The buffer containing the MPEG4 video frame.
|
||||
\param buffer_size The size of the buffer in bytes.
|
||||
\param width The width, if found, is stored in this variable.
|
||||
\param height The height, if found, is stored in this variable.
|
||||
|
||||
\return \c true if width and height were found and \c false
|
||||
otherwise.
|
||||
*/
|
||||
bool
|
||||
mpeg4::p2::extract_size(const unsigned char *buffer,
|
||||
int buffer_size,
|
||||
uint32_t &width,
|
||||
uint32_t &height) {
|
||||
try {
|
||||
mpeg4::p2::config_data_t config_data;
|
||||
if (!parse_vol_header(buffer, buffer_size, config_data) || !config_data.m_width_height_found)
|
||||
return false;
|
||||
|
||||
width = config_data.m_width;
|
||||
height = config_data.m_height;
|
||||
|
||||
return true;
|
||||
} catch (...) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
mpeg4::p2::extract_par_internal(const unsigned char *buffer,
|
||||
int buffer_size,
|
||||
uint32_t &par_num,
|
||||
uint32_t &par_den) {
|
||||
extract_par_internal(unsigned char const *buffer,
|
||||
int buffer_size,
|
||||
uint32_t &par_num,
|
||||
uint32_t &par_den) {
|
||||
const uint32_t ar_nums[16] = {0, 1, 12, 10, 16, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
const uint32_t ar_dens[16] = {1, 1, 11, 11, 11, 33, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
|
||||
uint32_t aspect_ratio_info, num, den;
|
||||
@ -205,6 +168,65 @@ mpeg4::p2::extract_par_internal(const unsigned char *buffer,
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
parse_frame(video_frame_t &frame,
|
||||
unsigned char const *buffer,
|
||||
config_data_t const &config_data) {
|
||||
static const frame_type_e s_frame_type_map[4] = { FRAME_TYPE_I, FRAME_TYPE_P, FRAME_TYPE_B, FRAME_TYPE_P };
|
||||
|
||||
mtx::bits::reader_c bc(&buffer[ frame.pos + 4 ], frame.size);
|
||||
|
||||
frame.type = s_frame_type_map[ bc.get_bits(2) ];
|
||||
|
||||
while (bc.get_bit())
|
||||
; // modulo time base
|
||||
bc.skip_bits(1 + config_data.m_time_increment_bits + 1); // marker, vop time increment, marker
|
||||
|
||||
frame.is_coded = bc.get_bit();
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
config_data_t::config_data_t()
|
||||
: m_time_increment_bits(0)
|
||||
, m_width(0)
|
||||
, m_height(0)
|
||||
, m_width_height_found(false)
|
||||
{
|
||||
}
|
||||
|
||||
/** Extract the widht and height from a MPEG4 video frame
|
||||
|
||||
This function searches a buffer containing a MPEG4 video frame
|
||||
for the width and height.
|
||||
|
||||
\param buffer The buffer containing the MPEG4 video frame.
|
||||
\param buffer_size The size of the buffer in bytes.
|
||||
\param width The width, if found, is stored in this variable.
|
||||
\param height The height, if found, is stored in this variable.
|
||||
|
||||
\return \c true if width and height were found and \c false
|
||||
otherwise.
|
||||
*/
|
||||
bool
|
||||
extract_size(unsigned char const *buffer,
|
||||
int buffer_size,
|
||||
uint32_t &width,
|
||||
uint32_t &height) {
|
||||
try {
|
||||
config_data_t config_data;
|
||||
if (!parse_vol_header(buffer, buffer_size, config_data) || !config_data.m_width_height_found)
|
||||
return false;
|
||||
|
||||
width = config_data.m_width;
|
||||
height = config_data.m_height;
|
||||
|
||||
return true;
|
||||
} catch (...) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** Extract the pixel aspect ratio from a MPEG4 video frame
|
||||
|
||||
This function searches a buffer containing a MPEG4 video frame
|
||||
@ -220,10 +242,10 @@ mpeg4::p2::extract_par_internal(const unsigned char *buffer,
|
||||
otherwise.
|
||||
*/
|
||||
bool
|
||||
mpeg4::p2::extract_par(const unsigned char *buffer,
|
||||
int buffer_size,
|
||||
uint32_t &par_num,
|
||||
uint32_t &par_den) {
|
||||
extract_par(unsigned char const *buffer,
|
||||
int buffer_size,
|
||||
uint32_t &par_num,
|
||||
uint32_t &par_den) {
|
||||
try {
|
||||
return extract_par_internal(buffer, buffer_size, par_num, par_den);
|
||||
} catch (...) {
|
||||
@ -231,23 +253,6 @@ mpeg4::p2::extract_par(const unsigned char *buffer,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mpeg4::p2::parse_frame(video_frame_t &frame,
|
||||
const unsigned char *buffer,
|
||||
const mpeg4::p2::config_data_t &config_data) {
|
||||
static const frame_type_e s_frame_type_map[4] = { FRAME_TYPE_I, FRAME_TYPE_P, FRAME_TYPE_B, FRAME_TYPE_P };
|
||||
|
||||
mtx::bits::reader_c bc(&buffer[ frame.pos + 4 ], frame.size);
|
||||
|
||||
frame.type = s_frame_type_map[ bc.get_bits(2) ];
|
||||
|
||||
while (bc.get_bit())
|
||||
; // modulo time base
|
||||
bc.skip_bits(1 + config_data.m_time_increment_bits + 1); // marker, vop time increment, marker
|
||||
|
||||
frame.is_coded = bc.get_bit();
|
||||
}
|
||||
|
||||
/** Find frame boundaries and frame types in a packed video frame
|
||||
|
||||
This function searches a buffer containing one or more MPEG4 video frames
|
||||
@ -263,10 +268,10 @@ mpeg4::p2::parse_frame(video_frame_t &frame,
|
||||
a dummy frame) then \a frames will contain no elements.
|
||||
*/
|
||||
void
|
||||
mpeg4::p2::find_frame_types(const unsigned char *buffer,
|
||||
int buffer_size,
|
||||
std::vector<video_frame_t> &frames,
|
||||
const mpeg4::p2::config_data_t &config_data) {
|
||||
find_frame_types(unsigned char const *buffer,
|
||||
int buffer_size,
|
||||
std::vector<video_frame_t> &frames,
|
||||
config_data_t const &config_data) {
|
||||
frames.clear();
|
||||
mxdebug_if(s_debug, fmt::format("\nmpeg4_frames: start search in {0} bytes\n", buffer_size));
|
||||
|
||||
@ -339,9 +344,9 @@ mpeg4::p2::find_frame_types(const unsigned char *buffer,
|
||||
a memory_c object otherwise. This object has to be deleted manually.
|
||||
*/
|
||||
memory_cptr
|
||||
mpeg4::p2::parse_config_data(const unsigned char *buffer,
|
||||
int buffer_size,
|
||||
mpeg4::p2::config_data_t &config_data) {
|
||||
parse_config_data(unsigned char const *buffer,
|
||||
int buffer_size,
|
||||
config_data_t &config_data) {
|
||||
if (5 > buffer_size)
|
||||
return nullptr;
|
||||
|
||||
@ -378,7 +383,7 @@ mpeg4::p2::parse_config_data(const unsigned char *buffer,
|
||||
|
||||
if (-1 != vol_offset)
|
||||
try {
|
||||
mpeg4::p2::config_data_t cfg_data;
|
||||
config_data_t cfg_data;
|
||||
if (parse_vol_header(&buffer[ vol_offset ], buffer_size - vol_offset, cfg_data))
|
||||
config_data.m_time_increment_bits = cfg_data.m_time_increment_bits;
|
||||
|
||||
@ -417,7 +422,7 @@ mpeg4::p2::parse_config_data(const unsigned char *buffer,
|
||||
\return true if the FourCC refers to a MPEG-4 part 2 video codec.
|
||||
*/
|
||||
bool
|
||||
mpeg4::p2::is_fourcc(const void *fourcc) {
|
||||
is_fourcc(void const *fourcc) {
|
||||
static const char *mpeg4_p2_fourccs[] = {
|
||||
"MP42", "DIV2", "DIVX", "XVID", "DX50", "FMP4", "DXGM",
|
||||
nullptr
|
||||
@ -438,7 +443,7 @@ mpeg4::p2::is_fourcc(const void *fourcc) {
|
||||
\return true if the FourCC refers to a MPEG-4 part 2 video codec.
|
||||
*/
|
||||
bool
|
||||
mpeg4::p2::is_v3_fourcc(const void *fourcc) {
|
||||
is_v3_fourcc(void const *fourcc) {
|
||||
static const char *mpeg4_p2_v3_fourccs[] = {
|
||||
"DIV3", "MPG3", "MP43",
|
||||
"AP41", // Angel Potion
|
||||
@ -451,3 +456,5 @@ mpeg4::p2::is_v3_fourcc(const void *fourcc) {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace mtx::mpeg4_p2
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
#include "common/common_pch.h"
|
||||
|
||||
namespace mtx::mpeg4_p2 {
|
||||
|
||||
/** Start code for a MPEG-4 part 2 (?) video object plain */
|
||||
#define MPEGVIDEO_VOP_START_CODE 0x000001b6
|
||||
#define MPEGVIDEO_VOL_START_CODE 0x00000120
|
||||
@ -115,22 +117,20 @@ struct video_frame_t {
|
||||
}
|
||||
};
|
||||
|
||||
namespace mpeg4 {
|
||||
namespace p2 {
|
||||
struct config_data_t {
|
||||
int m_time_increment_bits;
|
||||
int m_width, m_height;
|
||||
bool m_width_height_found;
|
||||
struct config_data_t {
|
||||
int m_time_increment_bits;
|
||||
int m_width, m_height;
|
||||
bool m_width_height_found;
|
||||
|
||||
config_data_t();
|
||||
};
|
||||
config_data_t();
|
||||
};
|
||||
|
||||
bool is_fourcc(const void *fourcc);
|
||||
bool is_v3_fourcc(const void *fourcc);
|
||||
bool is_fourcc(const void *fourcc);
|
||||
bool is_v3_fourcc(const void *fourcc);
|
||||
|
||||
bool extract_par(const unsigned char *buffer, int buffer_size, uint32_t &par_num, uint32_t &par_den);
|
||||
bool extract_size(const unsigned char *buffer, int buffer_size, uint32_t &width, uint32_t &height);
|
||||
void find_frame_types(const unsigned char *buffer, int buffer_size, std::vector<video_frame_t> &frames, const config_data_t &config_data);
|
||||
memory_cptr parse_config_data(const unsigned char *buffer, int buffer_size, config_data_t &config_data);
|
||||
|
||||
bool extract_par(const unsigned char *buffer, int buffer_size, uint32_t &par_num, uint32_t &par_den);
|
||||
bool extract_size(const unsigned char *buffer, int buffer_size, uint32_t &width, uint32_t &height);
|
||||
void find_frame_types(const unsigned char *buffer, int buffer_size, std::vector<video_frame_t> &frames, const config_data_t &config_data);
|
||||
memory_cptr parse_config_data(const unsigned char *buffer, int buffer_size, config_data_t &config_data);
|
||||
}
|
||||
}
|
||||
|
@ -110,8 +110,8 @@ mpeg4_p2_video_packetizer_c::process_non_native(packet_cptr packet) {
|
||||
mxerror_tid(m_ti.m_fname, m_ti.m_id, Y("Cannot convert non-native MPEG4 video frames into native ones if the source container "
|
||||
"provides neither timestamps nor a number of frames per second.\n"));
|
||||
|
||||
std::vector<video_frame_t> frames;
|
||||
mpeg4::p2::find_frame_types(packet->data->get_buffer(), packet->data->get_size(), frames, m_config_data);
|
||||
std::vector<mtx::mpeg4_p2::video_frame_t> frames;
|
||||
mtx::mpeg4_p2::find_frame_types(packet->data->get_buffer(), packet->data->get_size(), frames, m_config_data);
|
||||
|
||||
for (auto &frame : frames) {
|
||||
if (!frame.is_coded) {
|
||||
@ -138,22 +138,22 @@ mpeg4_p2_video_packetizer_c::process_non_native(packet_cptr packet) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (FRAME_TYPE_I == frame.type)
|
||||
if (mtx::mpeg4_p2::FRAME_TYPE_I == frame.type)
|
||||
++m_statistics.m_num_i_frames;
|
||||
else if (FRAME_TYPE_P == frame.type)
|
||||
else if (mtx::mpeg4_p2::FRAME_TYPE_P == frame.type)
|
||||
++m_statistics.m_num_p_frames;
|
||||
else
|
||||
++m_statistics.m_num_b_frames;
|
||||
|
||||
// Maybe we can flush queued frames now. But only if we don't have
|
||||
// a B frame.
|
||||
if (FRAME_TYPE_B != frame.type)
|
||||
if (mtx::mpeg4_p2::FRAME_TYPE_B != frame.type)
|
||||
flush_frames(false);
|
||||
|
||||
frame.data = (unsigned char *)safememdup(packet->data->get_buffer() + frame.pos, frame.size);
|
||||
frame.timestamp = -1;
|
||||
|
||||
if (FRAME_TYPE_B == frame.type)
|
||||
if (mtx::mpeg4_p2::FRAME_TYPE_B == frame.type)
|
||||
m_b_frames.push_back(frame);
|
||||
else
|
||||
m_ref_frames.push_back(frame);
|
||||
@ -169,7 +169,7 @@ mpeg4_p2_video_packetizer_c::extract_config_data(packet_cptr &packet) {
|
||||
if (m_ti.m_private_data)
|
||||
return;
|
||||
|
||||
m_ti.m_private_data = memory_cptr{mpeg4::p2::parse_config_data(packet->data->get_buffer(), packet->data->get_size(), m_config_data)};
|
||||
m_ti.m_private_data = memory_cptr{mtx::mpeg4_p2::parse_config_data(packet->data->get_buffer(), packet->data->get_size(), m_config_data)};
|
||||
if (!m_ti.m_private_data)
|
||||
mxerror_tid(m_ti.m_fname, m_ti.m_id, Y("Could not find the codec configuration data in the first MPEG-4 part 2 video frame. This track cannot be stored in native mode.\n"));
|
||||
|
||||
@ -270,7 +270,7 @@ mpeg4_p2_video_packetizer_c::flush_frames(bool end_of_file) {
|
||||
return;
|
||||
|
||||
if (m_ref_frames.size() == 1) {
|
||||
video_frame_t &frame = m_ref_frames.front();
|
||||
auto &frame = m_ref_frames.front();
|
||||
|
||||
// The first frame in the file. Only apply the timestamp, nothing else.
|
||||
if (-1 == frame.timestamp) {
|
||||
@ -280,14 +280,14 @@ mpeg4_p2_video_packetizer_c::flush_frames(bool end_of_file) {
|
||||
return;
|
||||
}
|
||||
|
||||
video_frame_t &bref_frame = m_ref_frames.front();
|
||||
video_frame_t &fref_frame = m_ref_frames.back();
|
||||
auto &bref_frame = m_ref_frames.front();
|
||||
auto &fref_frame = m_ref_frames.back();
|
||||
|
||||
for (auto &frame : m_b_frames)
|
||||
get_next_timestamp_and_duration(frame.timestamp, frame.duration);
|
||||
get_next_timestamp_and_duration(fref_frame.timestamp, fref_frame.duration);
|
||||
|
||||
add_packet(new packet_t(memory_c::take_ownership(fref_frame.data, fref_frame.size), fref_frame.timestamp, fref_frame.duration, FRAME_TYPE_P == fref_frame.type ? bref_frame.timestamp : VFT_IFRAME));
|
||||
add_packet(new packet_t(memory_c::take_ownership(fref_frame.data, fref_frame.size), fref_frame.timestamp, fref_frame.duration, mtx::mpeg4_p2::FRAME_TYPE_P == fref_frame.type ? bref_frame.timestamp : VFT_IFRAME));
|
||||
for (auto &frame : m_b_frames)
|
||||
add_packet(new packet_t(memory_c::take_ownership(frame.data, frame.size), frame.timestamp, frame.duration, bref_frame.timestamp, fref_frame.timestamp));
|
||||
|
||||
@ -315,7 +315,7 @@ mpeg4_p2_video_packetizer_c::extract_aspect_ratio(const unsigned char *buffer,
|
||||
}
|
||||
|
||||
uint32_t num, den;
|
||||
if (mpeg4::p2::extract_par(buffer, size, num, den)) {
|
||||
if (mtx::mpeg4_p2::extract_par(buffer, size, num, den)) {
|
||||
m_aspect_ratio_extracted = true;
|
||||
set_video_aspect_ratio((double)m_hvideo_pixel_width / (double)m_hvideo_pixel_height * (double)num / (double)den, false, OPTION_SOURCE_BITSTREAM);
|
||||
|
||||
@ -342,7 +342,7 @@ mpeg4_p2_video_packetizer_c::extract_size(const unsigned char *buffer,
|
||||
|
||||
uint32_t xtr_width, xtr_height;
|
||||
|
||||
if (mpeg4::p2::extract_size(buffer, size, xtr_width, xtr_height)) {
|
||||
if (mtx::mpeg4_p2::extract_size(buffer, size, xtr_width, xtr_height)) {
|
||||
m_size_extracted = true;
|
||||
|
||||
if (!m_reader->m_appending && ((xtr_width != static_cast<uint32_t>(m_hvideo_pixel_width)) || (xtr_height != static_cast<uint32_t>(m_hvideo_pixel_height)))) {
|
||||
|
@ -46,12 +46,12 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
std::deque<video_frame_t> m_ref_frames, m_b_frames;
|
||||
std::deque<mtx::mpeg4_p2::video_frame_t> m_ref_frames, m_b_frames;
|
||||
std::deque<timestamp_duration_t> m_available_timestamps;
|
||||
int64_t m_timestamps_generated, m_previous_timestamp;
|
||||
bool m_aspect_ratio_extracted, m_input_is_native, m_output_is_native;
|
||||
bool m_size_extracted;
|
||||
mpeg4::p2::config_data_t m_config_data;
|
||||
mtx::mpeg4_p2::config_data_t m_config_data;
|
||||
statistics_t m_statistics;
|
||||
|
||||
public:
|
||||
|
@ -53,10 +53,10 @@ video_for_windows_packetizer_c::check_fourcc() {
|
||||
memcpy(fourcc, &reinterpret_cast<alBITMAPINFOHEADER *>(m_ti.m_private_data->get_buffer())->bi_compression, 4);
|
||||
fourcc[4] = 0;
|
||||
|
||||
if (mpeg4::p2::is_v3_fourcc(fourcc))
|
||||
if (mtx::mpeg4_p2::is_v3_fourcc(fourcc))
|
||||
m_codec_type = video_for_windows_packetizer_c::ct_div3;
|
||||
|
||||
else if (mpeg4::p2::is_fourcc(fourcc))
|
||||
else if (mtx::mpeg4_p2::is_fourcc(fourcc))
|
||||
m_codec_type = video_for_windows_packetizer_c::ct_mpeg4_p2;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user