mirror of
https://gitlab.com/mbunkus/mkvtoolnix.git
synced 2024-12-24 11:54:01 +00:00
Moved the MPEG-4 handling from the video_packetizer_c into two new packetizers for MPEG-4 layer 2 and MPEG-4 layer 10. Added functions to the MPEG-1/-2 packetizer to extract the aspect ratio and to create the codec private data in case the reader does not supply those (like the Qt/MP4 reader).
This commit is contained in:
parent
8e10873a44
commit
3e33089390
@ -383,6 +383,68 @@ mpeg1_2_extract_fps_idx(const unsigned char *buffer,
|
||||
return buffer[idx] & 0x0f;
|
||||
}
|
||||
|
||||
/** \brief Extract the aspect ratio from a MPEG video sequence header
|
||||
|
||||
This function looks for a MPEG sequence header in a buffer containing
|
||||
a MPEG1 or MPEG2 video frame. If such a header is found its
|
||||
aspect ratio is extracted and returned.
|
||||
|
||||
\param buffer The buffer to search for the header.
|
||||
\param size The buffer size.
|
||||
|
||||
\return \c true if a MPEG sequence header was found and \c false otherwise.
|
||||
*/
|
||||
bool
|
||||
mpeg1_2_extract_ar(const unsigned char *buffer,
|
||||
int size,
|
||||
float &ar) {
|
||||
uint32_t marker;
|
||||
int idx;
|
||||
|
||||
mxverb(3, "mpeg_video_ar: start search in %d bytes\n", size);
|
||||
if (size < 8) {
|
||||
mxverb(3, "mpeg_video_ar: sequence header too small\n");
|
||||
return -1;
|
||||
}
|
||||
marker = get_uint32_be(buffer);
|
||||
idx = 4;
|
||||
while ((idx < size) && (marker != MPEGVIDEO_SEQUENCE_START_CODE)) {
|
||||
marker <<= 8;
|
||||
marker |= buffer[idx];
|
||||
idx++;
|
||||
}
|
||||
if (idx >= size) {
|
||||
mxverb(3, "mpeg_video_ar: no sequence header start code found\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mxverb(3, "mpeg_video_ar: found sequence header start code at %d\n",
|
||||
idx - 4);
|
||||
idx += 3; // width and height
|
||||
if (idx >= size) {
|
||||
mxverb(3, "mpeg_video_ar: sequence header too small\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (buffer[idx] & 0xf0) {
|
||||
case MPEGVIDEO_AR_1_1:
|
||||
ar = 1.0f;
|
||||
break;
|
||||
case MPEGVIDEO_AR_4_3:
|
||||
ar = 4.0f / 3.0f;
|
||||
break;
|
||||
case MPEGVIDEO_AR_16_9:
|
||||
ar = 16.0f / 9.0f;
|
||||
break;
|
||||
case MPEGVIDEO_AR_2_21:
|
||||
ar = 2.21f;
|
||||
break;
|
||||
default:
|
||||
ar = -1.0f;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** \brief Get the number of frames per second
|
||||
|
||||
Converts the index returned by ::mpeg_video_extract_fps_idx to a number.
|
||||
|
@ -56,6 +56,22 @@
|
||||
/** MPEG-1/-2 frame rate: 60 frames per second */
|
||||
#define MPEGVIDEO_FPS_60 0x08
|
||||
|
||||
/** MPEG-1/-2 aspect ratio 1:1 */
|
||||
#define MPEGVIDEO_AR_1_1 0x10
|
||||
/** MPEG-1/-2 aspect ratio 4:3 */
|
||||
#define MPEGVIDEO_AR_4_3 0x20
|
||||
/** MPEG-1/-2 aspect ratio 16:9 */
|
||||
#define MPEGVIDEO_AR_16_9 0x30
|
||||
/** MPEG-1/-2 aspect ratio 2.21 */
|
||||
#define MPEGVIDEO_AR_2_21 0x40
|
||||
|
||||
#define IS_MPEG4_L2_FOURCC(s) \
|
||||
(!strncasecmp((s), "DIVX", 4) || !strncasecmp((s), "XVID", 4) || \
|
||||
!strncasecmp((s), "DX5", 3))
|
||||
#define IS_MPEG4_L2_CODECID(s) \
|
||||
(((s) == MKV_V_MPEG4_SP) || ((s) == MKV_V_MPEG4_AP) || \
|
||||
((s) == MKV_V_MPEG4_ASP))
|
||||
|
||||
enum mpeg_video_type_e {
|
||||
MPEG_VIDEO_NONE = 0,
|
||||
MPEG_VIDEO_V1,
|
||||
@ -73,7 +89,7 @@ enum mpeg_video_type_e {
|
||||
such packed frames can be analyzed. The results are stored in these
|
||||
structures: one structure for one frame in the analyzed chunk.
|
||||
*/
|
||||
typedef struct {
|
||||
struct video_frame_t {
|
||||
/** The beginning of the frame data. This is a pointer into an existing
|
||||
buffer handed over to ::mpeg4_find_frame_types. */
|
||||
unsigned char *data;
|
||||
@ -97,7 +113,11 @@ typedef struct {
|
||||
\link video_frame_t::timecode timecode \endlink.
|
||||
This value is only set for B frames. */
|
||||
int64_t fref;
|
||||
} video_frame_t;
|
||||
|
||||
video_frame_t():
|
||||
data(NULL), size(0), pos(0), type('?'), priv(NULL),
|
||||
timecode(0), duration(0), bref(0), fref(0) {};
|
||||
};
|
||||
|
||||
bool MTX_DLL_API mpeg4_extract_par(const unsigned char *buffer, int size,
|
||||
uint32_t &par_num, uint32_t &par_den);
|
||||
@ -110,5 +130,7 @@ bool MTX_DLL_API mpeg4_l10_extract_par(const uint8_t *buffer, int buf_size,
|
||||
int MTX_DLL_API mpeg1_2_extract_fps_idx(const unsigned char *buffer,
|
||||
int size);
|
||||
double MTX_DLL_API mpeg1_2_get_fps(int idx);
|
||||
bool MTX_DLL_API mpeg1_2_extract_ar(const unsigned char *buffer, int size,
|
||||
float &ar);
|
||||
|
||||
#endif /* __MPEG4_COMMON_H */
|
||||
|
@ -172,14 +172,27 @@ avi_reader_c::create_packetizer(int64_t tid) {
|
||||
if (ti->private_data != NULL)
|
||||
ti->private_size = get_uint32_le(&avi->bitmap_info_header->bi_size);
|
||||
ti->id = 0; // ID for the video track.
|
||||
vptzr = add_packetizer(new video_packetizer_c(this, NULL,
|
||||
AVI_frame_rate(avi),
|
||||
AVI_video_width(avi),
|
||||
AVI_video_height(avi),
|
||||
false, ti));
|
||||
if (verbose)
|
||||
mxinfo(FMT_TID "Using the video output module for the video track.\n",
|
||||
ti->fname.c_str(), (int64_t)0);
|
||||
if (is_divx == RAVI_MPEG4) {
|
||||
vptzr =
|
||||
add_packetizer(new mpeg4_l2_video_packetizer_c(this,
|
||||
AVI_frame_rate(avi),
|
||||
AVI_video_width(avi),
|
||||
AVI_video_height(avi),
|
||||
false,
|
||||
ti));
|
||||
if (verbose)
|
||||
mxinfo(FMT_TID "Using the MPEG-4 layer 2 video output module for "
|
||||
"this track.\n", ti->fname.c_str(), (int64_t)0);
|
||||
} else {
|
||||
vptzr = add_packetizer(new video_packetizer_c(this, NULL,
|
||||
AVI_frame_rate(avi),
|
||||
AVI_video_width(avi),
|
||||
AVI_video_height(avi),
|
||||
ti));
|
||||
if (verbose)
|
||||
mxinfo(FMT_TID "Using the video output module for the video track.\n",
|
||||
ti->fname.c_str(), (int64_t)0);
|
||||
}
|
||||
}
|
||||
if (tid == 0)
|
||||
return;
|
||||
|
@ -1591,15 +1591,72 @@ kax_reader_c::create_packetizer(int64_t tid) {
|
||||
if (starts_with(t->codec_id, "V_MPEG4", 7) ||
|
||||
(t->codec_id == MKV_V_MSCOMP) ||
|
||||
starts_with(t->codec_id, "V_REAL", 6) ||
|
||||
(t->codec_id == MKV_V_QUICKTIME)) {
|
||||
mxinfo(FMT_TID "Using the video output module.\n", ti->fname.c_str(),
|
||||
(int64_t)t->tnum);
|
||||
t->ptzr = add_packetizer(new video_packetizer_c(this,
|
||||
t->codec_id.c_str(),
|
||||
t->v_frate,
|
||||
t->v_width,
|
||||
t->v_height,
|
||||
t->v_bframes, nti));
|
||||
(t->codec_id == MKV_V_QUICKTIME) ||
|
||||
(t->codec_id == MKV_V_MPEG1) ||
|
||||
(t->codec_id == MKV_V_MPEG2)) {
|
||||
const char *fourcc;
|
||||
|
||||
if ((t->codec_id == MKV_V_MSCOMP) &&
|
||||
(t->private_data != NULL) &&
|
||||
(t->private_size >= sizeof(alBITMAPINFOHEADER)))
|
||||
fourcc = (const char *)
|
||||
&((alBITMAPINFOHEADER *)t->private_data)->bi_compression;
|
||||
else
|
||||
fourcc = NULL;
|
||||
|
||||
if ((t->codec_id == MKV_V_MPEG1) || (t->codec_id == MKV_V_MPEG2)) {
|
||||
int version;
|
||||
|
||||
version = t->codec_id[6] - '0';
|
||||
mxinfo(FMT_TID "Using the MPEG-%d video output module.\n",
|
||||
ti->fname.c_str(), (int64_t)t->tnum, version);
|
||||
t->ptzr =
|
||||
add_packetizer(new mpeg1_2_video_packetizer_c(this,
|
||||
version,
|
||||
t->v_frate,
|
||||
t->v_width,
|
||||
t->v_height,
|
||||
t->v_dwidth,
|
||||
t->v_dheight,
|
||||
true, nti));
|
||||
|
||||
} else if (IS_MPEG4_L2_CODECID(t->codec_id) ||
|
||||
((fourcc != NULL) && IS_MPEG4_L2_FOURCC(fourcc))) {
|
||||
bool is_native;
|
||||
|
||||
mxinfo(FMT_TID "Using the MPEG-4 layer 2 video output module.\n",
|
||||
ti->fname.c_str(), (int64_t)t->tnum);
|
||||
is_native = IS_MPEG4_L2_CODECID(t->codec_id);
|
||||
t->ptzr =
|
||||
add_packetizer(new mpeg4_l2_video_packetizer_c(this,
|
||||
t->v_frate,
|
||||
t->v_width,
|
||||
t->v_height,
|
||||
is_native,
|
||||
nti));
|
||||
|
||||
} else if (t->codec_id == MKV_V_MPEG4_AVC) {
|
||||
mxinfo(FMT_TID "Using the MPEG-4 layer 10 (AVC) video output "
|
||||
"module.\n", ti->fname.c_str(), (int64_t)t->tnum);
|
||||
t->ptzr =
|
||||
add_packetizer(new mpeg4_l10_video_packetizer_c(this,
|
||||
t->v_frate,
|
||||
t->v_width,
|
||||
t->v_height,
|
||||
nti));
|
||||
|
||||
} else {
|
||||
mxinfo(FMT_TID "Using the video output module.\n",
|
||||
ti->fname.c_str(), (int64_t)t->tnum);
|
||||
t->ptzr =
|
||||
add_packetizer(new video_packetizer_c(this,
|
||||
t->codec_id.c_str(),
|
||||
t->v_frate,
|
||||
t->v_width,
|
||||
t->v_height,
|
||||
nti));
|
||||
}
|
||||
|
||||
if (!PTZR(t->ptzr)->ti->aspect_ratio_given) {
|
||||
// The user hasn't set it.
|
||||
if (t->v_dwidth != 0)
|
||||
|
@ -149,9 +149,9 @@ mpeg_es_reader_c::create_packetizer(int64_t) {
|
||||
if (NPTZR() != 0)
|
||||
return;
|
||||
|
||||
add_packetizer(new mpeg_12_video_packetizer_c(this, version, frame_rate,
|
||||
add_packetizer(new mpeg1_2_video_packetizer_c(this, version, frame_rate,
|
||||
width, height, dwidth, dheight,
|
||||
ti));
|
||||
false, ti));
|
||||
|
||||
mxinfo(FMT_TID "Using the MPEG-1/2 video output module.\n",
|
||||
ti->fname.c_str(), (int64_t)0);
|
||||
@ -801,15 +801,16 @@ mpeg_ps_reader_c::create_packetizer(int64_t id) {
|
||||
} else { // if (track->type == 'a')
|
||||
if ((track->fourcc == FOURCC('m', 'p', 'g', '1')) ||
|
||||
(track->fourcc == FOURCC('m', 'p', 'g', '2'))) {
|
||||
mpeg_12_video_packetizer_c *ptzr;
|
||||
mpeg1_2_video_packetizer_c *ptzr;
|
||||
|
||||
ti->private_data = track->raw_seq_hdr;
|
||||
ti->private_size = track->raw_seq_hdr_size;
|
||||
ptzr =
|
||||
new mpeg_12_video_packetizer_c(this, track->v_version,
|
||||
new mpeg1_2_video_packetizer_c(this, track->v_version,
|
||||
track->v_frame_rate,
|
||||
track->v_width, track->v_height,
|
||||
track->v_dwidth, track->v_dheight, ti);
|
||||
track->v_dwidth, track->v_dheight,
|
||||
false, ti);
|
||||
track->ptzr = add_packetizer(ptzr);
|
||||
ti->private_data = NULL;
|
||||
ti->private_size = 0;
|
||||
|
@ -429,7 +429,7 @@ ogm_reader_c::create_packetizer(int64_t tid) {
|
||||
get_uint64_le(&sth->time_unit),
|
||||
get_uint32_le(&sth->sh.video.width),
|
||||
get_uint32_le(&sth->sh.video.height),
|
||||
false, ti);
|
||||
ti);
|
||||
|
||||
mxinfo(FMT_TID "Using the video output module.\n", ti->fname.c_str(),
|
||||
(int64_t)tid);
|
||||
|
@ -1381,21 +1381,27 @@ qtmp4_reader_c::create_packetizer(int64_t tid) {
|
||||
ti->private_size = sizeof(alBITMAPINFOHEADER);
|
||||
ti->private_data = (unsigned char *)bih;
|
||||
dmx->ptzr =
|
||||
add_packetizer(new video_packetizer_c(this, MKV_V_MSCOMP, 0.0,
|
||||
dmx->v_width, dmx->v_height,
|
||||
false, ti));
|
||||
add_packetizer(new mpeg4_l2_video_packetizer_c(this, 0.0,
|
||||
dmx->v_width,
|
||||
dmx->v_height, true,
|
||||
ti));
|
||||
safefree(bih);
|
||||
ti->private_data = NULL;
|
||||
mxinfo(FMT_TID "Using the MPEG-4 layer 2 video output module.\n",
|
||||
ti->fname.c_str(), (int64_t)dmx->id);
|
||||
|
||||
} else if (!strncasecmp(dmx->fourcc, "mpg1", 4) ||
|
||||
!strncasecmp(dmx->fourcc, "mpg2", 4)) {
|
||||
string codec_id;
|
||||
int version;
|
||||
|
||||
codec_id = mxsprintf("V_MPEG%c", dmx->fourcc[3]);
|
||||
version = dmx->fourcc[3] - '0';
|
||||
dmx->ptzr =
|
||||
add_packetizer(new video_packetizer_c(this, codec_id.c_str(),
|
||||
-1.0, dmx->v_width,
|
||||
dmx->v_height, false, ti));
|
||||
add_packetizer(new mpeg1_2_video_packetizer_c(this, version,
|
||||
-1.0, dmx->v_width,
|
||||
dmx->v_height, 0, 0,
|
||||
false, ti));
|
||||
mxinfo(FMT_TID "Using the MPEG-%d video output module.\n",
|
||||
ti->fname.c_str(), (int64_t)dmx->id, version);
|
||||
|
||||
} else if (!strncasecmp(dmx->fourcc, "avc1", 4)) {
|
||||
double fps;
|
||||
@ -1449,15 +1455,17 @@ qtmp4_reader_c::create_packetizer(int64_t tid) {
|
||||
ti->private_size = dmx->priv_size;
|
||||
ti->private_data = dmx->priv;
|
||||
dmx->ptzr =
|
||||
add_packetizer(new video_packetizer_c(this, MKV_V_MPEG4_AVC, fps,
|
||||
dmx->v_width, dmx->v_height,
|
||||
false, ti));
|
||||
add_packetizer(new mpeg4_l10_video_packetizer_c(this, fps,
|
||||
dmx->v_width,
|
||||
dmx->v_height, ti));
|
||||
ti->private_data = NULL;
|
||||
|
||||
if (hack_engaged(ENGAGE_AVC_USE_BFRAMES))
|
||||
dmx->avc_use_bframes = true;
|
||||
else
|
||||
PTZR(dmx->ptzr)->relaxed_timecode_checking = true;
|
||||
mxinfo(FMT_TID "Using the MPEG-4 layer 10 (AVC) video output "
|
||||
"module.\n", ti->fname.c_str(), (int64_t)dmx->id);
|
||||
|
||||
} else {
|
||||
ti->private_size = dmx->v_stsd_size;
|
||||
@ -1465,11 +1473,11 @@ qtmp4_reader_c::create_packetizer(int64_t tid) {
|
||||
dmx->ptzr =
|
||||
add_packetizer(new video_packetizer_c(this, MKV_V_QUICKTIME, 0.0,
|
||||
dmx->v_width, dmx->v_height,
|
||||
false, ti));
|
||||
ti));
|
||||
ti->private_data = NULL;
|
||||
mxinfo(FMT_TID "Using the video output module (FourCC: %.4s).\n",
|
||||
ti->fname.c_str(), (int64_t)dmx->id, dmx->fourcc);
|
||||
}
|
||||
mxinfo(FMT_TID "Using the video output module (FourCC: %.4s).\n",
|
||||
ti->fname.c_str(), (int64_t)dmx->id, dmx->fourcc);
|
||||
|
||||
} else {
|
||||
if (!strncasecmp(dmx->fourcc, "QDMC", 4) ||
|
||||
|
@ -260,8 +260,7 @@ real_reader_c::create_packetizer(int64_t tid) {
|
||||
mxprints(buffer, "V_REAL/%s", dmx->fourcc);
|
||||
dmx->ptzr =
|
||||
add_packetizer(new video_packetizer_c(this, buffer, dmx->fps,
|
||||
dmx->width, dmx->height, false,
|
||||
ti));
|
||||
dmx->width, dmx->height, ti));
|
||||
if ((dmx->fourcc[0] != 'R') || (dmx->fourcc[1] != 'V') ||
|
||||
(dmx->fourcc[2] != '4') || (dmx->fourcc[3] != '0'))
|
||||
dmx->rv_dimensions = true;
|
||||
|
@ -32,82 +32,42 @@ extern "C" {
|
||||
|
||||
using namespace libmatroska;
|
||||
|
||||
video_packetizer_c::video_packetizer_c(generic_reader_c *nreader,
|
||||
const char *ncodec_id,
|
||||
double nfps,
|
||||
int nwidth,
|
||||
int nheight,
|
||||
bool nbframes,
|
||||
track_info_c *nti)
|
||||
throw (error_c) : generic_packetizer_c(nreader, nti) {
|
||||
char *fourcc;
|
||||
video_packetizer_c::video_packetizer_c(generic_reader_c *_reader,
|
||||
const char *_codec_id,
|
||||
double _fps,
|
||||
int _width,
|
||||
int _height,
|
||||
track_info_c *_ti):
|
||||
generic_packetizer_c(_reader, _ti),
|
||||
fps(_fps), width(_width), height(_height),
|
||||
frames_output(0), ref_timecode(-1), duration_shift(0) {
|
||||
|
||||
fps = nfps;
|
||||
width = nwidth;
|
||||
height = nheight;
|
||||
frames_output = 0;
|
||||
bframes = nbframes;
|
||||
ref_timecode = -1;
|
||||
if (get_cue_creation() == CUE_STRATEGY_UNSPECIFIED)
|
||||
set_cue_creation(CUE_STRATEGY_IFRAMES);
|
||||
duration_shift = 0;
|
||||
bref_frame.type = '?';
|
||||
fref_frame.type = '?';
|
||||
aspect_ratio_extracted = false;
|
||||
|
||||
set_track_type(track_video);
|
||||
|
||||
mpeg_video = MPEG_VIDEO_NONE;
|
||||
if ((ti->private_data != NULL) &&
|
||||
(ti->private_size >= sizeof(alBITMAPINFOHEADER))) {
|
||||
fourcc = (char *)&((alBITMAPINFOHEADER *)ti->private_data)->bi_compression;
|
||||
if (!strncasecmp(fourcc, "DIVX", 4) ||
|
||||
!strncasecmp(fourcc, "XVID", 4) ||
|
||||
!strncasecmp(fourcc, "DX5", 3))
|
||||
mpeg_video = MPEG_VIDEO_V4_LAYER_2;
|
||||
}
|
||||
if ((mpeg_video == MPEG_VIDEO_NONE) && (ncodec_id != NULL) &&
|
||||
!strncmp(ncodec_id, MKV_V_MPEG4_SP, strlen(MKV_V_MPEG4_SP) - 2)) {
|
||||
if (!strcmp(ncodec_id, MKV_V_MPEG4_AVC))
|
||||
mpeg_video = MPEG_VIDEO_V4_LAYER_10;
|
||||
else
|
||||
mpeg_video = MPEG_VIDEO_V4_LAYER_2;
|
||||
}
|
||||
|
||||
if ((mpeg_video == MPEG_VIDEO_NONE) && (ncodec_id != NULL) &&
|
||||
(!strcmp(ncodec_id, MKV_V_MPEG1) || !strcmp(ncodec_id, MKV_V_MPEG2)))
|
||||
mpeg_video = (ncodec_id[6] == '1') ? MPEG_VIDEO_V1 : MPEG_VIDEO_V2;
|
||||
|
||||
if ((mpeg_video == MPEG_VIDEO_V4_LAYER_2) &&
|
||||
hack_engaged(ENGAGE_NATIVE_MPEG4))
|
||||
set_codec_id(MKV_V_MPEG4_ASP);
|
||||
else if (ncodec_id != NULL)
|
||||
set_codec_id(ncodec_id);
|
||||
if (_codec_id != NULL)
|
||||
set_codec_id(_codec_id);
|
||||
else
|
||||
set_codec_id(MKV_V_MSCOMP);
|
||||
|
||||
if (((mpeg_video != MPEG_VIDEO_V4_LAYER_2) ||
|
||||
!hack_engaged(ENGAGE_NATIVE_MPEG4)) &&
|
||||
(hcodec_id != "") && (hcodec_id == MKV_V_MSCOMP) &&
|
||||
set_codec_private(ti->private_data, ti->private_size);
|
||||
check_fourcc();
|
||||
}
|
||||
|
||||
void
|
||||
video_packetizer_c::check_fourcc() {
|
||||
if ((hcodec_id == MKV_V_MSCOMP) &&
|
||||
(ti->private_data != NULL) &&
|
||||
(ti->private_size >= sizeof(alBITMAPINFOHEADER)) &&
|
||||
(ti->fourcc[0] != 0))
|
||||
memcpy(&((alBITMAPINFOHEADER *)ti->private_data)->bi_compression,
|
||||
ti->fourcc, 4);
|
||||
if ((mpeg_video != MPEG_VIDEO_V4_LAYER_2) ||
|
||||
!hack_engaged(ENGAGE_NATIVE_MPEG4))
|
||||
set_codec_private(ti->private_data, ti->private_size);
|
||||
}
|
||||
|
||||
void
|
||||
video_packetizer_c::set_headers() {
|
||||
// Set MinCache to 1 for I- and P-frames. If you only
|
||||
// have I-frames then it can be set to 0 (e.g. MJPEG). 2 is needed
|
||||
// if there are B-frames as well.
|
||||
if (bframes)
|
||||
set_track_min_cache(2);
|
||||
else
|
||||
set_track_min_cache(1);
|
||||
if (fps > 0.0)
|
||||
set_track_default_duration((int64_t)(1000000000.0 / fps));
|
||||
|
||||
@ -134,87 +94,6 @@ video_packetizer_c::process(memory_c &mem,
|
||||
int64_t bref,
|
||||
int64_t fref) {
|
||||
int64_t timecode;
|
||||
vector<video_frame_t> frames;
|
||||
uint32_t i;
|
||||
|
||||
debug_enter("video_packetizer_c::process");
|
||||
|
||||
if (!aspect_ratio_extracted) {
|
||||
if (mpeg_video == MPEG_VIDEO_V4_LAYER_2)
|
||||
extract_mpeg4_aspect_ratio(mem.data, mem.size);
|
||||
else if (mpeg_video == MPEG_VIDEO_V4_LAYER_10)
|
||||
extract_mpeg4_aspect_ratio(ti->private_data, ti->private_size);
|
||||
aspect_ratio_extracted = true;
|
||||
}
|
||||
|
||||
if ((fps < 0.0) &&
|
||||
((mpeg_video == MPEG_VIDEO_V1) || (mpeg_video == MPEG_VIDEO_V2)))
|
||||
extract_mpeg1_2_fps(mem.data, mem.size);
|
||||
|
||||
if ((mpeg_video == MPEG_VIDEO_V4_LAYER_2) &&
|
||||
hack_engaged(ENGAGE_NATIVE_MPEG4))
|
||||
mpeg4_find_frame_types(mem.data, mem.size, frames);
|
||||
|
||||
if ((mpeg_video == MPEG_VIDEO_V4_LAYER_2) &&
|
||||
hack_engaged(ENGAGE_NATIVE_MPEG4) && (fps != 0.0)) {
|
||||
for (i = 0; i < frames.size(); i++) {
|
||||
if ((frames[i].type == 'I') ||
|
||||
((frames[i].type != 'B') && (fref_frame.type != '?')))
|
||||
flush_frames(frames[i].type);
|
||||
|
||||
if (old_timecode == -1)
|
||||
timecode = (int64_t)(1000000000.0 * frames_output / fps) +
|
||||
duration_shift;
|
||||
else
|
||||
timecode = old_timecode;
|
||||
|
||||
if ((duration == -1) || (duration == (int64_t)(1000.0 / fps)))
|
||||
duration = (int64_t)(1000000000.0 / fps);
|
||||
else
|
||||
duration_shift += duration - (int64_t)(1000000000.0 / fps);
|
||||
|
||||
frames_output++;
|
||||
frames[i].timecode = timecode;
|
||||
frames[i].duration = duration;
|
||||
frames[i].data = (unsigned char *)safememdup(&mem.data[frames[i].pos],
|
||||
frames[i].size);
|
||||
|
||||
if (frames[i].type == 'I') {
|
||||
frames[i].bref = -1;
|
||||
frames[i].fref = -1;
|
||||
if (bref_frame.type == '?') {
|
||||
bref_frame = frames[i];
|
||||
memory_c mem(frames[i].data, frames[i].size, false);
|
||||
add_packet(mem, frames[i].timecode, frames[i].duration);
|
||||
} else
|
||||
fref_frame = frames[i];
|
||||
|
||||
} else if (frames[i].type != 'B') {
|
||||
frames_output--;
|
||||
if (bref_frame.type == '?')
|
||||
mxerror("video_packetizer: Found a P frame but no I frame. This "
|
||||
"should not have happened. Either this is a bug in mkvmerge "
|
||||
"or the video stream is damaged.\n");
|
||||
frames[i].bref = bref_frame.timecode;
|
||||
frames[i].fref = -1;
|
||||
fref_frame = frames[i];
|
||||
|
||||
} else {
|
||||
if (!bframes) {
|
||||
set_codec_id(MKV_V_MPEG4_ASP);
|
||||
set_track_min_cache(2);
|
||||
rerender_track_headers();
|
||||
}
|
||||
bframes = true;
|
||||
queued_frames.push_back(frames[i]);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
debug_leave("video_packetizer_c::process");
|
||||
|
||||
return FILE_STATUS_MOREDATA;
|
||||
}
|
||||
|
||||
if (old_timecode == -1)
|
||||
timecode = (int64_t)(1000000000.0 * frames_output / fps) + duration_shift;
|
||||
@ -240,14 +119,9 @@ video_packetizer_c::process(memory_c &mem,
|
||||
ref_timecode = timecode;
|
||||
}
|
||||
|
||||
debug_leave("video_packetizer_c::process");
|
||||
|
||||
return FILE_STATUS_MOREDATA;
|
||||
}
|
||||
|
||||
video_packetizer_c::~video_packetizer_c() {
|
||||
}
|
||||
|
||||
void
|
||||
video_packetizer_c::dump_debug_info() {
|
||||
mxdebug("video_packetizer_c: queue: %d; frames_output: %d; "
|
||||
@ -255,39 +129,125 @@ video_packetizer_c::dump_debug_info() {
|
||||
ref_timecode);
|
||||
}
|
||||
|
||||
void
|
||||
video_packetizer_c::flush() {
|
||||
flush_frames(true);
|
||||
connection_result_e
|
||||
video_packetizer_c::can_connect_to(generic_packetizer_c *src) {
|
||||
video_packetizer_c *vsrc;
|
||||
|
||||
vsrc = dynamic_cast<video_packetizer_c *>(src);
|
||||
if (vsrc == NULL)
|
||||
return CAN_CONNECT_NO_FORMAT;
|
||||
if ((width != vsrc->width) || (height != vsrc->height) ||
|
||||
(fps != vsrc->fps) || (hcodec_id != vsrc->hcodec_id))
|
||||
return CAN_CONNECT_NO_PARAMETERS;
|
||||
if (((ti->private_data == NULL) && (vsrc->ti->private_data != NULL)) ||
|
||||
((ti->private_data != NULL) && (vsrc->ti->private_data == NULL)) ||
|
||||
(ti->private_size != vsrc->ti->private_size))
|
||||
return CAN_CONNECT_NO_PARAMETERS;
|
||||
if ((ti->private_data != NULL) &&
|
||||
memcmp(ti->private_data, vsrc->ti->private_data, ti->private_size))
|
||||
return CAN_CONNECT_NO_PARAMETERS;
|
||||
return CAN_CONNECT_YES;
|
||||
}
|
||||
|
||||
void
|
||||
video_packetizer_c::extract_mpeg4_aspect_ratio(const unsigned char *buffer,
|
||||
int size) {
|
||||
uint32_t num, den;
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
aspect_ratio_extracted = true;
|
||||
if (ti->aspect_ratio_given || ti->display_dimensions_given)
|
||||
return;
|
||||
mpeg1_2_video_packetizer_c::
|
||||
mpeg1_2_video_packetizer_c(generic_reader_c *_reader,
|
||||
int _version,
|
||||
double _fps,
|
||||
int _width,
|
||||
int _height,
|
||||
int _dwidth,
|
||||
int _dheight,
|
||||
bool _framed,
|
||||
track_info_c *_ti):
|
||||
video_packetizer_c(_reader, "V_MPEG1", _fps, _width, _height, _ti),
|
||||
framed(_framed), aspect_ratio_extracted(false) {
|
||||
|
||||
if (((mpeg_video == MPEG_VIDEO_V4_LAYER_2) &&
|
||||
mpeg4_extract_par(buffer, size, num, den))
|
||||
||
|
||||
((mpeg_video == MPEG_VIDEO_V4_LAYER_10) &&
|
||||
mpeg4_l10_extract_par(buffer, size, num, den))) {
|
||||
ti->aspect_ratio_given = true;
|
||||
ti->aspect_ratio = (float)hvideo_pixel_width /
|
||||
(float)hvideo_pixel_height * (float)num / (float)den;
|
||||
generic_packetizer_c::set_headers();
|
||||
rerender_track_headers();
|
||||
mxinfo("Track %lld of '%s': Extracted the aspect ratio information "
|
||||
"from the MPEG4 video data and set the display dimensions to "
|
||||
"%u/%u.\n", (int64_t)ti->id, ti->fname.c_str(),
|
||||
(uint32_t)ti->display_width, (uint32_t)ti->display_height);
|
||||
set_codec_id(mxsprintf("V_MPEG%d", _version));
|
||||
if (!ti->aspect_ratio_given && !ti->display_dimensions_given) {
|
||||
if ((_dwidth > 0) && (_dheight > 0)) {
|
||||
ti->display_dimensions_given = true;
|
||||
ti->display_width = _dwidth;
|
||||
ti->display_height = _dheight;
|
||||
}
|
||||
} else
|
||||
aspect_ratio_extracted = true;
|
||||
}
|
||||
|
||||
int
|
||||
mpeg1_2_video_packetizer_c::process(memory_c &mem,
|
||||
int64_t timecode,
|
||||
int64_t duration,
|
||||
int64_t bref,
|
||||
int64_t fref) {
|
||||
unsigned char *data_ptr;
|
||||
int new_bytes, state;
|
||||
|
||||
if (fps < 0.0)
|
||||
extract_fps(mem.data, mem.size);
|
||||
|
||||
if (!aspect_ratio_extracted)
|
||||
extract_aspect_ratio(mem.data, mem.size);
|
||||
|
||||
if (framed) {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
state = parser.GetState();
|
||||
if ((state == MPV_PARSER_STATE_EOS) ||
|
||||
(state == MPV_PARSER_STATE_ERROR))
|
||||
return FILE_STATUS_DONE;
|
||||
|
||||
data_ptr = mem.data;
|
||||
new_bytes = mem.size;
|
||||
|
||||
do {
|
||||
int bytes_to_add;
|
||||
|
||||
bytes_to_add = (parser.GetFreeBufferSpace() < new_bytes) ?
|
||||
parser.GetFreeBufferSpace() : new_bytes;
|
||||
if (bytes_to_add > 0) {
|
||||
parser.WriteData(data_ptr, bytes_to_add);
|
||||
data_ptr += bytes_to_add;
|
||||
new_bytes -= bytes_to_add;
|
||||
}
|
||||
|
||||
state = parser.GetState();
|
||||
while (state == MPV_PARSER_STATE_FRAME) {
|
||||
MPEGFrame *frame;
|
||||
|
||||
frame = parser.ReadFrame();
|
||||
if (frame == NULL)
|
||||
break;
|
||||
|
||||
if (hcodec_private == NULL)
|
||||
create_private_data();
|
||||
|
||||
memory_c new_mem(frame->data, frame->size, true);
|
||||
video_packetizer_c::process(new_mem, frame->timecode, frame->duration,
|
||||
frame->firstRef, frame->secondRef);
|
||||
frame->data = NULL;
|
||||
delete frame;
|
||||
|
||||
state = parser.GetState();
|
||||
}
|
||||
} while (new_bytes > 0);
|
||||
|
||||
return FILE_STATUS_MOREDATA;
|
||||
}
|
||||
|
||||
void
|
||||
video_packetizer_c::extract_mpeg1_2_fps(const unsigned char *buffer,
|
||||
mpeg1_2_video_packetizer_c::flush() {
|
||||
memory_c dummy((unsigned char *)"", 0, false);
|
||||
|
||||
parser.SetEOS();
|
||||
process(dummy);
|
||||
video_packetizer_c::flush();
|
||||
}
|
||||
|
||||
void
|
||||
mpeg1_2_video_packetizer_c::extract_fps(const unsigned char *buffer,
|
||||
int size) {
|
||||
int idx;
|
||||
|
||||
@ -303,8 +263,128 @@ video_packetizer_c::extract_mpeg1_2_fps(const unsigned char *buffer,
|
||||
}
|
||||
|
||||
void
|
||||
video_packetizer_c::flush_frames(char next_frame,
|
||||
bool flush_all) {
|
||||
mpeg1_2_video_packetizer_c::extract_aspect_ratio(const unsigned char *buffer,
|
||||
int size) {
|
||||
float ar;
|
||||
|
||||
if (ti->aspect_ratio_given || ti->display_dimensions_given)
|
||||
return;
|
||||
|
||||
if (mpeg1_2_extract_ar(buffer, size, ar)) {
|
||||
ti->display_dimensions_given = true;
|
||||
if ((ar <= 0) || (ar == 1))
|
||||
set_video_display_width(width);
|
||||
else
|
||||
set_video_display_width((int)(height * ar));
|
||||
set_video_display_height(height);
|
||||
rerender_track_headers();
|
||||
aspect_ratio_extracted = true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
mpeg1_2_video_packetizer_c::create_private_data() {
|
||||
MPEGChunk *raw_seq_hdr;
|
||||
|
||||
raw_seq_hdr = parser.GetRealSequenceHeader();
|
||||
if (raw_seq_hdr != NULL) {
|
||||
set_codec_private(raw_seq_hdr->GetPointer(), raw_seq_hdr->GetSize());
|
||||
rerender_track_headers();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
mpeg4_l2_video_packetizer_c::
|
||||
mpeg4_l2_video_packetizer_c(generic_reader_c *_reader,
|
||||
double _fps,
|
||||
int _width,
|
||||
int _height,
|
||||
bool _input_is_native,
|
||||
track_info_c *_ti):
|
||||
video_packetizer_c(_reader, MKV_V_MPEG4_ASP, _fps, _width, _height, _ti),
|
||||
aspect_ratio_extracted(false), input_is_native(_input_is_native) {
|
||||
|
||||
assert(!input_is_native);
|
||||
|
||||
if (!hack_engaged(ENGAGE_NATIVE_MPEG4) || (_fps == 0.0)) {
|
||||
set_codec_id(MKV_V_MSCOMP);
|
||||
check_fourcc();
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
mpeg4_l2_video_packetizer_c::process(memory_c &mem,
|
||||
int64_t old_timecode,
|
||||
int64_t duration,
|
||||
int64_t bref,
|
||||
int64_t fref) {
|
||||
int64_t timecode;
|
||||
vector<video_frame_t> frames;
|
||||
int i;
|
||||
|
||||
if (!aspect_ratio_extracted)
|
||||
extract_aspect_ratio(mem.data, mem.size);
|
||||
|
||||
if (!hack_engaged(ENGAGE_NATIVE_MPEG4) || (fps == 0.0)) {
|
||||
video_packetizer_c::process(mem, old_timecode, duration, bref, fref);
|
||||
return FILE_STATUS_MOREDATA;
|
||||
}
|
||||
|
||||
mpeg4_find_frame_types(mem.data, mem.size, frames);
|
||||
|
||||
for (i = 0; i < frames.size(); i++) {
|
||||
if ((frames[i].type == 'I') ||
|
||||
((frames[i].type != 'B') && (fref_frame.type != '?')))
|
||||
flush_frames(frames[i].type);
|
||||
|
||||
if (old_timecode == -1)
|
||||
timecode = (int64_t)(1000000000.0 * frames_output / fps) +
|
||||
duration_shift;
|
||||
else
|
||||
timecode = old_timecode;
|
||||
|
||||
if ((duration == -1) || (duration == (int64_t)(1000.0 / fps)))
|
||||
duration = (int64_t)(1000000000.0 / fps);
|
||||
else
|
||||
duration_shift += duration - (int64_t)(1000000000.0 / fps);
|
||||
|
||||
frames_output++;
|
||||
frames[i].timecode = timecode;
|
||||
frames[i].duration = duration;
|
||||
frames[i].data = (unsigned char *)safememdup(&mem.data[frames[i].pos],
|
||||
frames[i].size);
|
||||
|
||||
if (frames[i].type == 'I') {
|
||||
frames[i].bref = -1;
|
||||
frames[i].fref = -1;
|
||||
if (bref_frame.type == '?') {
|
||||
bref_frame = frames[i];
|
||||
memory_c mem(frames[i].data, frames[i].size, false);
|
||||
add_packet(mem, frames[i].timecode, frames[i].duration);
|
||||
} else
|
||||
fref_frame = frames[i];
|
||||
|
||||
} else if (frames[i].type != 'B') {
|
||||
frames_output--;
|
||||
if (bref_frame.type == '?')
|
||||
mxerror("video_packetizer: Found a P frame but no I frame. This "
|
||||
"should not have happened. Either this is a bug in mkvmerge "
|
||||
"or the video stream is damaged.\n");
|
||||
frames[i].bref = bref_frame.timecode;
|
||||
frames[i].fref = -1;
|
||||
fref_frame = frames[i];
|
||||
|
||||
} else
|
||||
queued_frames.push_back(frames[i]);
|
||||
}
|
||||
|
||||
return FILE_STATUS_MOREDATA;
|
||||
}
|
||||
|
||||
void
|
||||
mpeg4_l2_video_packetizer_c::flush_frames(char next_frame,
|
||||
bool flush_all) {
|
||||
uint32_t i;
|
||||
|
||||
if (bref_frame.type == '?') {
|
||||
@ -363,102 +443,61 @@ video_packetizer_c::flush_frames(char next_frame,
|
||||
bref_frame.type = '?';
|
||||
}
|
||||
|
||||
connection_result_e
|
||||
video_packetizer_c::can_connect_to(generic_packetizer_c *src) {
|
||||
video_packetizer_c *vsrc;
|
||||
void
|
||||
mpeg4_l2_video_packetizer_c::flush() {
|
||||
flush_frames(true);
|
||||
}
|
||||
|
||||
vsrc = dynamic_cast<video_packetizer_c *>(src);
|
||||
if (vsrc == NULL)
|
||||
return CAN_CONNECT_NO_FORMAT;
|
||||
if ((width != vsrc->width) || (height != vsrc->height) ||
|
||||
(fps != vsrc->fps) || (hcodec_id != vsrc->hcodec_id))
|
||||
return CAN_CONNECT_NO_PARAMETERS;
|
||||
if (((ti->private_data == NULL) && (vsrc->ti->private_data != NULL)) ||
|
||||
((ti->private_data != NULL) && (vsrc->ti->private_data == NULL)) ||
|
||||
(ti->private_size != vsrc->ti->private_size))
|
||||
return CAN_CONNECT_NO_PARAMETERS;
|
||||
if ((ti->private_data != NULL) &&
|
||||
memcmp(ti->private_data, vsrc->ti->private_data, ti->private_size))
|
||||
return CAN_CONNECT_NO_PARAMETERS;
|
||||
return CAN_CONNECT_YES;
|
||||
void
|
||||
mpeg4_l2_video_packetizer_c::extract_aspect_ratio(const unsigned char *buffer,
|
||||
int size) {
|
||||
uint32_t num, den;
|
||||
|
||||
aspect_ratio_extracted = true;
|
||||
if (ti->aspect_ratio_given || ti->display_dimensions_given)
|
||||
return;
|
||||
|
||||
if (mpeg4_extract_par(buffer, size, num, den)) {
|
||||
ti->aspect_ratio_given = true;
|
||||
ti->aspect_ratio = (float)hvideo_pixel_width /
|
||||
(float)hvideo_pixel_height * (float)num / (float)den;
|
||||
generic_packetizer_c::set_headers();
|
||||
rerender_track_headers();
|
||||
mxinfo("Track %lld of '%s': Extracted the aspect ratio information "
|
||||
"from the MPEG4 layer 2 video data and set the display dimensions "
|
||||
"to %u/%u.\n", (int64_t)ti->id, ti->fname.c_str(),
|
||||
(uint32_t)ti->display_width, (uint32_t)ti->display_height);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
mpeg_12_video_packetizer_c::
|
||||
mpeg_12_video_packetizer_c(generic_reader_c *_reader,
|
||||
int _version,
|
||||
double _fps,
|
||||
int _width,
|
||||
int _height,
|
||||
int _dwidth,
|
||||
int _dheight,
|
||||
track_info_c *_ti):
|
||||
video_packetizer_c(_reader, "V_MPEG1", _fps, _width, _height, true, _ti) {
|
||||
mpeg4_l10_video_packetizer_c::
|
||||
mpeg4_l10_video_packetizer_c(generic_reader_c *_reader,
|
||||
double _fps,
|
||||
int _width,
|
||||
int _height,
|
||||
track_info_c *_ti):
|
||||
video_packetizer_c(_reader, MKV_V_MPEG4_AVC, _fps, _width, _height, _ti) {
|
||||
|
||||
mpeg_video = (_version == 1) ? MPEG_VIDEO_V1 : MPEG_VIDEO_V2;
|
||||
set_codec_id(mxsprintf("V_MPEG%d", _version));
|
||||
if (!ti->aspect_ratio_given && !ti->display_dimensions_given) {
|
||||
ti->display_dimensions_given = true;
|
||||
ti->display_width = _dwidth;
|
||||
ti->display_height = _dheight;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
mpeg_12_video_packetizer_c::process(memory_c &mem,
|
||||
int64_t,
|
||||
int64_t,
|
||||
int64_t,
|
||||
int64_t) {
|
||||
unsigned char *data_ptr;
|
||||
int new_bytes, state;
|
||||
|
||||
state = parser.GetState();
|
||||
if ((state == MPV_PARSER_STATE_EOS) ||
|
||||
(state == MPV_PARSER_STATE_ERROR))
|
||||
return FILE_STATUS_DONE;
|
||||
|
||||
data_ptr = mem.data;
|
||||
new_bytes = mem.size;
|
||||
|
||||
do {
|
||||
int bytes_to_add;
|
||||
|
||||
bytes_to_add = (parser.GetFreeBufferSpace() < new_bytes) ?
|
||||
parser.GetFreeBufferSpace() : new_bytes;
|
||||
if (bytes_to_add > 0) {
|
||||
parser.WriteData(data_ptr, bytes_to_add);
|
||||
data_ptr += bytes_to_add;
|
||||
new_bytes -= bytes_to_add;
|
||||
}
|
||||
|
||||
state = parser.GetState();
|
||||
while (state == MPV_PARSER_STATE_FRAME) {
|
||||
MPEGFrame *frame;
|
||||
|
||||
frame = parser.ReadFrame();
|
||||
if (frame == NULL)
|
||||
break;
|
||||
|
||||
memory_c new_mem(frame->data, frame->size, true);
|
||||
video_packetizer_c::process(new_mem, frame->timecode, frame->duration,
|
||||
frame->firstRef, frame->secondRef);
|
||||
frame->data = NULL;
|
||||
delete frame;
|
||||
|
||||
state = parser.GetState();
|
||||
}
|
||||
} while (new_bytes > 0);
|
||||
|
||||
return FILE_STATUS_MOREDATA;
|
||||
if ((ti->private_data != NULL) && (ti->private_size > 0))
|
||||
extract_aspect_ratio();
|
||||
}
|
||||
|
||||
void
|
||||
mpeg_12_video_packetizer_c::flush() {
|
||||
memory_c dummy((unsigned char *)"", 0, false);
|
||||
mpeg4_l10_video_packetizer_c::extract_aspect_ratio() {
|
||||
uint32_t num, den;
|
||||
|
||||
parser.SetEOS();
|
||||
process(dummy);
|
||||
video_packetizer_c::flush();
|
||||
if (ti->aspect_ratio_given || ti->display_dimensions_given)
|
||||
return;
|
||||
|
||||
if (mpeg4_l10_extract_par(ti->private_data, ti->private_size, num, den)) {
|
||||
ti->aspect_ratio_given = true;
|
||||
ti->aspect_ratio = (float)hvideo_pixel_width /
|
||||
(float)hvideo_pixel_height * (float)num / (float)den;
|
||||
mxinfo("Track %lld of '%s': Extracted the aspect ratio information "
|
||||
"from the MPEG-4 layer 10 (AVC) video data and set the display "
|
||||
"dimensions to %u/%u.\n", (int64_t)ti->id, ti->fname.c_str(),
|
||||
(uint32_t)ti->display_width, (uint32_t)ti->display_height);
|
||||
}
|
||||
}
|
||||
|
@ -30,26 +30,19 @@
|
||||
class video_packetizer_c: public generic_packetizer_c {
|
||||
protected:
|
||||
double fps;
|
||||
int width, height, bpp, frames_output;
|
||||
int width, height, frames_output;
|
||||
int64_t ref_timecode, duration_shift;
|
||||
bool avi_compat_mode, bframes, pass_through;
|
||||
bool aspect_ratio_extracted;
|
||||
mpeg_video_type_e mpeg_video;
|
||||
vector<video_frame_t> queued_frames;
|
||||
video_frame_t bref_frame, fref_frame;
|
||||
bool pass_through;
|
||||
|
||||
public:
|
||||
video_packetizer_c(generic_reader_c *nreader, const char *ncodec_id,
|
||||
double nfps, int nwidth, int nheight, bool nbframes,
|
||||
track_info_c *nti)
|
||||
throw (error_c);
|
||||
virtual ~video_packetizer_c();
|
||||
video_packetizer_c(generic_reader_c *_reader, const char *_codec_id,
|
||||
double _fps, int _width, int _height,
|
||||
track_info_c *_ti);
|
||||
|
||||
virtual int process(memory_c &mem, int64_t old_timecode = -1,
|
||||
int64_t duration = -1, int64_t bref = VFT_IFRAME,
|
||||
int64_t fref = VFT_NOBFRAME);
|
||||
virtual void set_headers();
|
||||
virtual void flush();
|
||||
|
||||
virtual void dump_debug_info();
|
||||
|
||||
@ -59,25 +52,60 @@ public:
|
||||
virtual connection_result_e can_connect_to(generic_packetizer_c *src);
|
||||
|
||||
protected:
|
||||
virtual void flush_frames(char next_frame = '?', bool flush_all = false);
|
||||
virtual void extract_mpeg4_aspect_ratio(const unsigned char *buffer,
|
||||
int size);
|
||||
virtual void extract_mpeg1_2_fps(const unsigned char *buffer, int size);
|
||||
virtual void check_fourcc();
|
||||
};
|
||||
|
||||
class mpeg_12_video_packetizer_c: public video_packetizer_c {
|
||||
class mpeg1_2_video_packetizer_c: public video_packetizer_c {
|
||||
protected:
|
||||
M2VParser parser;
|
||||
bool framed, aspect_ratio_extracted;
|
||||
|
||||
public:
|
||||
mpeg_12_video_packetizer_c(generic_reader_c *_reader, int _version,
|
||||
mpeg1_2_video_packetizer_c(generic_reader_c *_reader, int _version,
|
||||
double _fps, int _width, int _height,
|
||||
int _dwidth, int _dheight, track_info_c *_ti);
|
||||
int _dwidth, int _dheight, bool _framed,
|
||||
track_info_c *_ti);
|
||||
|
||||
virtual int process(memory_c &mem, int64_t old_timecode = -1,
|
||||
int64_t duration = -1, int64_t bref = VFT_IFRAME,
|
||||
int64_t fref = VFT_NOBFRAME);
|
||||
virtual void flush();
|
||||
|
||||
protected:
|
||||
virtual void extract_fps(const unsigned char *buffer, int size);
|
||||
virtual void extract_aspect_ratio(const unsigned char *buffer, int size);
|
||||
virtual void create_private_data();
|
||||
};
|
||||
|
||||
class mpeg4_l2_video_packetizer_c: public video_packetizer_c {
|
||||
protected:
|
||||
vector<video_frame_t> queued_frames;
|
||||
video_frame_t bref_frame, fref_frame;
|
||||
bool aspect_ratio_extracted, input_is_native;
|
||||
|
||||
public:
|
||||
mpeg4_l2_video_packetizer_c(generic_reader_c *_reader,
|
||||
double _fps, int _width, int _height,
|
||||
bool _input_is_native, track_info_c *_ti);
|
||||
|
||||
virtual int process(memory_c &mem, int64_t old_timecode = -1,
|
||||
int64_t duration = -1, int64_t bref = VFT_IFRAME,
|
||||
int64_t fref = VFT_NOBFRAME);
|
||||
virtual void flush();
|
||||
|
||||
protected:
|
||||
virtual void flush_frames(char next_frame = '?', bool flush_all = false);
|
||||
virtual void extract_aspect_ratio(const unsigned char *buffer, int size);
|
||||
};
|
||||
|
||||
class mpeg4_l10_video_packetizer_c: public video_packetizer_c {
|
||||
public:
|
||||
mpeg4_l10_video_packetizer_c(generic_reader_c *_reader,
|
||||
double _fps, int _width, int _height,
|
||||
track_info_c *_ti);
|
||||
|
||||
protected:
|
||||
virtual void extract_aspect_ratio();
|
||||
};
|
||||
|
||||
#endif // __P_VIDEO_H
|
||||
|
Loading…
Reference in New Issue
Block a user