mirror of
https://gitlab.com/mbunkus/mkvtoolnix.git
synced 2024-12-24 11:54:01 +00:00
Added support for the "stereo mode" flag for video tracks.
This commit is contained in:
parent
787bd740d5
commit
8083266e1d
@ -1,3 +1,8 @@
|
||||
2006-11-07 Moritz Bunkus <moritz@bunkus.org>
|
||||
|
||||
* mkvmerge: new feature: Added support for the "stereo mode"
|
||||
flag for video tracks.
|
||||
|
||||
2006-11-03 Moritz Bunkus <moritz@bunkus.org>
|
||||
|
||||
* mkvmerge: bug fix: For MP4 files with certain CTTS contents
|
||||
|
@ -452,6 +452,12 @@ exclusive.
|
||||
.TP
|
||||
\fB\-\-cropping\fR <\fITID\fR:\fIleft\fR,\fItop\fR,\fIright\fR,\fIbottom\fR>
|
||||
Sets the pixel cropping parameters of a video track to the given values.
|
||||
.TP
|
||||
\fB\-\-stereo\-mode\fR <\fITID\fR:\fIn\fR|\fIkeyword\fR>
|
||||
Sets the stereo mode for the video track with the track ID \fITID\fR.
|
||||
The mode can either be a number \fIn\fR between 0 and 3 or one of the
|
||||
keywords \fInone\fR (same as n=0), \fIright\fR (same as n=1), \fIleft\fR
|
||||
(same as n=2) or \fIboth\fR (same as n=3).
|
||||
.LP
|
||||
Options that only apply to text subtitle tracks:
|
||||
.TP
|
||||
|
@ -1045,6 +1045,7 @@ kax_reader_c::read_headers() {
|
||||
KaxVideoPixelCropTop *kv_pctop;
|
||||
KaxVideoPixelCropRight *kv_pcright;
|
||||
KaxVideoPixelCropBottom *kv_pcbottom;
|
||||
KaxVideoStereoMode *kv_stereo_mode;
|
||||
|
||||
kv_pwidth = FINDFIRST(ktvideo, KaxVideoPixelWidth);
|
||||
if (kv_pwidth != NULL) {
|
||||
@ -1118,6 +1119,13 @@ kax_reader_c::read_headers() {
|
||||
track->v_pcbottom);
|
||||
}
|
||||
|
||||
kv_stereo_mode = FINDFIRST(ktvideo, KaxVideoStereoMode);
|
||||
if (NULL != kv_stereo_mode) {
|
||||
track->v_stereo_mode = (stereo_mode_e)uint64(*kv_stereo_mode);
|
||||
mxverb(2, PFX "| + Stereo mode: %d\n",
|
||||
(int)track->v_stereo_mode);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
kcodecid = FINDFIRST(ktentry, KaxCodecID);
|
||||
@ -1353,6 +1361,8 @@ kax_reader_c::init_passthrough_packetizer(kax_track_t *t) {
|
||||
(t->v_pcright > 0) || (t->v_pcbottom > 0)))
|
||||
ptzr->set_video_pixel_cropping(t->v_pcleft, t->v_pctop,
|
||||
t->v_pcright, t->v_pcbottom);
|
||||
if (STEREO_MODE_UNSPECIFIED == ptzr->ti.stereo_mode)
|
||||
ptzr->set_stereo_mode(t->v_stereo_mode);
|
||||
if (ptzr->get_cue_creation() == CUE_STRATEGY_UNSPECIFIED)
|
||||
ptzr->set_cue_creation( CUE_STRATEGY_IFRAMES);
|
||||
|
||||
@ -1505,6 +1515,8 @@ kax_reader_c::create_packetizer(int64_t tid) {
|
||||
PTZR(t->ptzr)->set_video_pixel_cropping(t->v_pcleft, t->v_pctop,
|
||||
t->v_pcright,
|
||||
t->v_pcbottom);
|
||||
if (STEREO_MODE_UNSPECIFIED == PTZR(t->ptzr)->ti.stereo_mode)
|
||||
PTZR(t->ptzr)->set_stereo_mode(t->v_stereo_mode);
|
||||
} else
|
||||
init_passthrough_packetizer(t);
|
||||
|
||||
|
@ -55,6 +55,7 @@ struct kax_track_t {
|
||||
// Parameters for video tracks
|
||||
uint64_t v_width, v_height, v_dwidth, v_dheight;
|
||||
uint64_t v_pcleft, v_pctop, v_pcright, v_pcbottom;
|
||||
stereo_mode_e v_stereo_mode;
|
||||
float v_frate;
|
||||
char v_fourcc[5];
|
||||
bool v_bframes;
|
||||
@ -97,6 +98,7 @@ struct kax_track_t {
|
||||
lacing_flag(false),
|
||||
v_width(0), v_height(0), v_dwidth(0), v_dheight(0),
|
||||
v_pcleft(0), v_pctop(0), v_pcright(0), v_pcbottom(0),
|
||||
v_stereo_mode(STEREO_MODE_UNSPECIFIED),
|
||||
v_frate(0.0),
|
||||
v_bframes(false),
|
||||
a_channels(0), a_bps(0), a_formattag(0),
|
||||
|
@ -231,6 +231,10 @@ set_usage() {
|
||||
" Explicitely set the display dimensions.\n"
|
||||
" --cropping <TID:left,top,right,bottom>\n"
|
||||
" Sets the cropping parameters.\n"
|
||||
" --stereo-mode <TID:n|none|left|right|both>\n"
|
||||
" Sets the stereo mode parameter. It can\n"
|
||||
" either be a numer 0 - 3 or one of the\n"
|
||||
" keywords 'none', 'right', 'left' or 'both'.\n"
|
||||
"\n Options that only apply to text subtitle tracks:\n"
|
||||
" --sub-charset <TID:charset>\n"
|
||||
" Sets the charset the text subtitles are\n"
|
||||
@ -668,6 +672,45 @@ parse_cropping(const string &s,
|
||||
ti.pixel_crop_list[id] = crop;
|
||||
}
|
||||
|
||||
/** \brief Parse the \c --stereo-mode argument
|
||||
|
||||
The argument must either be a number between 0 and 3 or
|
||||
one of the keywords \c 'none', \c 'left', \c 'right' or \c 'both'.
|
||||
*/
|
||||
static void
|
||||
parse_stereo_mode(const string &s,
|
||||
track_info_c &ti) {
|
||||
static const char * const keywords[] = {
|
||||
"none", "right", "left", "both", NULL
|
||||
};
|
||||
static const char *errmsg =
|
||||
_("Stereo mode parameter: not given in the form "
|
||||
"<TID>:<n|keyword> where n is a number between 0 and 3 "
|
||||
"or one of the keywords 'none', 'right', 'left', 'both' "
|
||||
"(argument was '%s').\n");
|
||||
int64_t i, id;
|
||||
vector<string> v;
|
||||
|
||||
v = split(s, ":");
|
||||
if (v.size() != 2)
|
||||
mxerror(errmsg, s.c_str());
|
||||
|
||||
id = 0;
|
||||
if (!parse_int(v[0], id))
|
||||
mxerror(errmsg, s.c_str());
|
||||
|
||||
for (i = 0; NULL != keywords[i]; ++i)
|
||||
if (v[1] == keywords[i]) {
|
||||
ti.stereo_mode_list[id] = (stereo_mode_e)i;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!parse_int(v[1], i) || (i < 0) || (i > STEREO_MODE_BOTH))
|
||||
mxerror(errmsg, s.c_str());
|
||||
|
||||
ti.stereo_mode_list[id] = (stereo_mode_e)i;
|
||||
}
|
||||
|
||||
/** \brief Parse the duration formats to \c --split
|
||||
|
||||
This function is called by ::parse_split if the format specifies
|
||||
@ -1806,6 +1849,13 @@ parse_args(vector<string> args) {
|
||||
parse_cropping(next_arg, *ti);
|
||||
sit++;
|
||||
|
||||
} else if (this_arg == "--stereo-mode") {
|
||||
if (no_next_arg)
|
||||
mxerror(_("'--stereo-mode' lacks the crop parameters.\n"));
|
||||
|
||||
parse_stereo_mode(next_arg, *ti);
|
||||
sit++;
|
||||
|
||||
} else if ((this_arg == "-y") || (this_arg == "--sync")) {
|
||||
if (no_next_arg)
|
||||
mxerror(_("'%s' lacks the audio delay.\n"), this_arg.c_str());
|
||||
|
@ -182,6 +182,12 @@ generic_packetizer_c::generic_packetizer_c(generic_reader_c *nreader,
|
||||
else
|
||||
ti.pixel_cropping_specified = false;
|
||||
|
||||
// Let's see if the user has specified a stereo mode for this track.
|
||||
if (map_has_key(ti.stereo_mode_list, ti.id))
|
||||
ti.stereo_mode = ti.stereo_mode_list[ti.id];
|
||||
else if (map_has_key(ti.stereo_mode_list, -1))
|
||||
ti.stereo_mode = ti.stereo_mode_list[-1];
|
||||
|
||||
// Let's see if the user has specified a default duration for this track.
|
||||
htrack_default_duration = -1;
|
||||
default_duration_forced = true;
|
||||
@ -527,6 +533,19 @@ generic_packetizer_c::set_video_pixel_cropping(int left,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
generic_packetizer_c::set_stereo_mode(stereo_mode_e stereo_mode) {
|
||||
ti.stereo_mode = stereo_mode;
|
||||
|
||||
if ((NULL != track_entry) &&
|
||||
(STEREO_MODE_UNSPECIFIED != stereo_mode)) {
|
||||
KaxTrackVideo &video = GetChild<KaxTrackVideo>(*track_entry);
|
||||
|
||||
*(static_cast<EbmlUInteger *>
|
||||
(&GetChild<KaxVideoStereoMode>(video))) = ti.stereo_mode;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
generic_packetizer_c::set_headers() {
|
||||
int idx, disp_width, disp_height;
|
||||
@ -689,6 +708,10 @@ generic_packetizer_c::set_headers() {
|
||||
(&GetChild<KaxVideoPixelCropBottom>(video))) =
|
||||
ti.pixel_cropping.bottom;
|
||||
}
|
||||
|
||||
if (STEREO_MODE_UNSPECIFIED != ti.stereo_mode)
|
||||
*(static_cast<EbmlUInteger *>
|
||||
(&GetChild<KaxVideoStereoMode>(video))) = ti.stereo_mode;
|
||||
}
|
||||
|
||||
} else if (htrack_type == track_audio) {
|
||||
@ -1393,6 +1416,7 @@ track_info_c::track_info_c():
|
||||
packet_delay(0),
|
||||
compression(COMPRESSION_UNSPECIFIED),
|
||||
pixel_cropping_specified(false),
|
||||
stereo_mode(STEREO_MODE_UNSPECIFIED),
|
||||
no_chapters(false),
|
||||
no_attachments(false),
|
||||
no_tags(false),
|
||||
@ -1482,6 +1506,9 @@ track_info_c::operator =(const track_info_c &src) {
|
||||
pixel_cropping = src.pixel_cropping;
|
||||
pixel_cropping_specified = src.pixel_cropping_specified;
|
||||
|
||||
stereo_mode_list = src.stereo_mode_list;
|
||||
stereo_mode = src.stereo_mode;
|
||||
|
||||
no_chapters = src.no_chapters;
|
||||
no_attachments = src.no_attachments;
|
||||
no_tags = src.no_tags;
|
||||
|
@ -103,6 +103,14 @@ struct pixel_crop_t {
|
||||
pixel_crop_t(): left(0), top(0), right(0), bottom(0) {}
|
||||
};
|
||||
|
||||
enum stereo_mode_e {
|
||||
STEREO_MODE_UNSPECIFIED = -1,
|
||||
STEREO_MODE_NONE = 0,
|
||||
STEREO_MODE_RIGHT = 1,
|
||||
STEREO_MODE_LEFT = 2,
|
||||
STEREO_MODE_BOTH = 3,
|
||||
};
|
||||
|
||||
class track_info_c {
|
||||
protected:
|
||||
bool initialized;
|
||||
@ -163,6 +171,9 @@ public:
|
||||
pixel_crop_t pixel_cropping; // For this very track
|
||||
bool pixel_cropping_specified;
|
||||
|
||||
map<int64_t, stereo_mode_e> stereo_mode_list; // As given on the command line
|
||||
stereo_mode_e stereo_mode; // For this very track
|
||||
|
||||
map<int64_t, int64_t> default_durations; // As given on the command line
|
||||
map<int64_t, int> max_blockadd_ids; // As given on the command line
|
||||
|
||||
@ -448,6 +459,7 @@ public:
|
||||
}
|
||||
virtual void set_video_pixel_cropping(int left, int top, int right,
|
||||
int bottom);
|
||||
virtual void set_stereo_mode(stereo_mode_e stereo_mode);
|
||||
|
||||
virtual void set_as_default_track(int type, int priority);
|
||||
|
||||
|
@ -68,3 +68,4 @@ T_218theora:35ea3cf1add9a6687627953e1645d4c9-fac4b041366588e3c8215b9fbb696db2:pa
|
||||
T_219srt_short_timecodes:a7db07ee64751fcc24993dd4af73ccf1:passed:20060926-112658
|
||||
T_220ass_with_comments_at_start:51ccd0cbe4e60b21817d7547310250bb:passed:20060926-120101
|
||||
T_221aac_lc_misdetected_as_sbr:f980b6252a24a5f855ec90e3d9d3a1fe:passed:20061103-174221
|
||||
T_222stereo_mode:22eebd6bda7d848379044be8d9d8f440-38a1988c087c40e6e52025bb974f2c56-38a1988c087c40e6e52025bb974f2c56:passed:20061107-092251
|
||||
|
42
tests/test-222stereo_mode.rb
Normal file
42
tests/test-222stereo_mode.rb
Normal file
@ -0,0 +1,42 @@
|
||||
#!/usr/bin/ruby -w
|
||||
|
||||
class T_222stereo_mode < Test
|
||||
def description
|
||||
return "mkvmerge / Stereo mode flag for video tracks / in(AVI)"
|
||||
end
|
||||
|
||||
def run
|
||||
merge(tmp + "-1",
|
||||
"-A --stereo-mode 0:none data/avi/v.avi " +
|
||||
"-A --stereo-mode 0:right data/avi/v.avi " +
|
||||
"-A --stereo-mode 0:left data/avi/v.avi " +
|
||||
"-A --stereo-mode 0:both data/avi/v.avi ")
|
||||
if (!FileTest.exist?(tmp + "-1"))
|
||||
error("First merge failed")
|
||||
end
|
||||
|
||||
hash = hash_file(tmp + "-1")
|
||||
|
||||
merge(tmp + "-2",
|
||||
"--stereo-mode 4:none --stereo-mode 3:right " +
|
||||
"--stereo-mode 2:left --stereo-mode 1:both #{tmp}-1")
|
||||
File.unlink(tmp + "-1")
|
||||
if (!FileTest.exist?(tmp + "-2"))
|
||||
error("Second merge failed")
|
||||
end
|
||||
|
||||
hash += "-" + hash_file(tmp + "-2")
|
||||
|
||||
merge(tmp + "-3", tmp + "-2")
|
||||
File.unlink(tmp + "-2")
|
||||
if (!FileTest.exist?(tmp + "-3"))
|
||||
error("Third merge failed")
|
||||
end
|
||||
|
||||
hash += "-" + hash_file(tmp + "-3")
|
||||
File.unlink(tmp + "-3")
|
||||
|
||||
return hash
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user