rename namespace mpeg4::p2 to mtx::mpeg4_p2

This commit is contained in:
Moritz Bunkus 2021-02-20 14:12:31 +01:00
parent b656e22ff8
commit 7fe61d48c6
No known key found for this signature in database
GPG Key ID: 74AF00ADF2E32C85
5 changed files with 127 additions and 120 deletions

View File

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

View File

@ -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);
}
}

View File

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

View File

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

View File

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