# AVC3Dmodifier.tcl (c) r0lZ 2023
# Version 2023.04.06
#
# This file is part of BD3D2MK3D.  All rights reserved.
# (c) 2012-2023 r0lZ - Open source
#
# GUI that uses Videofan3D's h264Modify.exe and MkvToolnix to add, remove or modify the
# 3D information from 3D or 2D AVC/h264 MKV video files.
# That information is the frame-packing SEI messages of any AVC elementary stream and
# the stereo-mode tag of the video header of any MKV file.
# Should be used to fix the bad tags, or to remove the tags causing problems to some
# hardware players (notably those based on the BigScreen software - Shame on them!)
#
# BUGS:
# - When MONO (2D) is set in a MKV AND its AVC stream, the tag is NOT set in the MKV header.
#   (It's a little, harmless bug of mkvmerge.exe.  MONO can be added later with mkvpropedit.)
# - Workaround for the missing Frame Sequential mode in h264Modify.exe. 
#   Bug fixed but not with an elegent solution.  H264Modify should be modified.

proc AVCModifyGUI {} {
	namespace eval ::avcmodify {}
	set w .avcmodify

	if { ! [winfo exists .avcmodify]} { 
		set ::avcmodify::infile ""
		set ::avcmodify::usesrcdir 1
		set ::avcmodify::destdir ""
		set ::avcmodify::outfile ""
		set ::avcmodify::stereomode " "
		set ::avcmodify::mkvkeep 1
		set ::avcmodify::avckeep 1
		set ::avcmodify::deltempavc 1
		set ::avcmodify::opendestdir 0
		set ::avcmodify::playvideo 0

		# MISSING AVC and MVC tags:
		# - Frame Alternation : missing in MKV and h264Modify (x264 --frame-packing 5)
		# - Tile : missing in MKV (x264 --frame-packing 7)
		set ::avcmodify::mkvformats [list \
			{Mono (2D)} 0 \
			{SBS Left view first} 1 \
			{SBS Right view first} 11 \
			{TAB Left view first} 3 \
			{TAB Right view first} 2 \
			{Frame Sequential Left view first (**)} 15 \
			{Frame Sequential Right view first (**)} 16 \
			{Checkerboard Left view first} 5 \
			{Checkerboard Right view first} 4 \
			{Row interleaved Left view first} 7 \
			{Row interleaved Right view first} 6 \
			{Column interleaved Left row first} 9 \
			{Column interleaved Right view first} 8 \
			{Tile Left view first (**)} 17 \
			{Tile Right view first (**)} 18 \
			{Field interlaced Left view first (*)} 13 \
			{Field interlaced Right view first (*)} 14 \
			{Anaglyph Cyan/Red (*)} 10 \
			{Anaglyph Green/Magenta (*)} 12]

		set ::avcmodify::avcformats [list \
			MONO \
			SBS:LR \
			TAB:RL \
			TAB:LR \
			CHECKER:RL \
			CHECKER:LR \
			ROWINT:RL \
			ROWINT:LR \
			COLINT:RL \
			COLINT:LR \
			{} \
			SBS:RL \
			{} {} {} \
			FRAMEALT:LR \
			FRAMEALT:RL \
			TILE:LR \
			TILE:RL]

		set ::avcmodify::displayformats {" "}
		foreach {i j} $::avcmodify::mkvformats {
			lappend ::avcmodify::displayformats $i
		}

		set ::status ""

		toplevel $w
		wm withdraw $w
		wm transient $w .
		wm title $w "Add/Remove 3D video format tags to/from a MKV or an AVC file"
		wm protocol $w WM_DELETE_WINDOW "grab release $w; wm withdraw $w"
		bind $w <Escape> "destroy $w"
		#bind $w <Return> ::Extract3DPlanes

		pack [ttk::labelframe $w.help -text "About this tool"] -side top -fill x -expand 1 -padx 4 -pady 4
		set    txt "Create, fix or remove the 3D format \"tags\" (the frame-packing SEI messages in\n"
		append txt "the AVC video stream and the stereo-mode property in the MKV video header)\n"
		append txt "from a MKV file or from an AVC (h264) elementary stream."
		pack [label $w.help.txt -text $txt -justify left] -side left -fill x -expand 1
		pack [ttk::button $w.help.b -text "?" -width 3 -command {HardPlayersHelp .avcmodify}] -side right -padx 2

		pack [ttk::labelframe $w.f2 -text "Input MKV ot AVC file to patch :"] -fill x -padx 4 -pady 4 -expand 1
		pack [frame $w.f2.f] -fill x -expand 1
		pack [ttk::entry $w.f2.f.e -width 75 -textvariable ::avcmodify::infile -state readonly] -side left -padx 2 -fill x -expand 1
		pack [ttk::button $w.f2.f.b -width 3 -text "..." -command avcmodifyInput] -side left -padx 2

		pack [ttk::labelframe $w.f3a -text "Default output folder :"] -fill x -padx 4 -pady 2
		pack [frame $w.f3a.f1] -fill x
		pack [ttk::radiobutton $w.f3a.f1.r1 -text "Use the source folder"    -variable ::avcmodify::usesrcdir -value 1 \
				-command {.avcmodify.f3a.f2.sf configure -state disabled; .avcmodify.f3a.f2.sfb configure -state disabled}] -side left -padx 2
		pack [ttk::radiobutton $w.f3a.f1.r2 -text "Use the folder below" -variable ::avcmodify::usesrcdir -value 0 \
				-command {.avcmodify.f3a.f2.sf configure -state readonly; .avcmodify.f3a.f2.sfb configure -state normal}] -side left -padx 6
		pack [label $w.f3a.f1.l -text "Be sure to have enough disc space !"] -side right
		pack [frame $w.f3a.f2] -fill x
		pack [ttk::entry $w.f3a.f2.sf -textvariable ::avcmodify::destdir -state disabled] -side left -padx 2 -fill x -expand 1
		pack [ttk::button $w.f3a.f2.sfb -width 3 -text "..." -command avcmodifyDestDir -state disabled] -side left -padx 2

		pack [ttk::labelframe $w.f3 -text "Output patched MKV or AVC file :"] -fill x -padx 4 -pady 2
		pack [ttk::entry $w.f3.e -textvariable ::avcmodify::outfile -state disabled] -side left -padx 2 -fill x -expand 1
		pack [ttk::button $w.f3.b -width 3 -text "..." -command avcmodifyOutput -state disabled] -side left -padx 2

		pack [ttk::labelframe $w.f4 -text "Correct 2D or 3D stereoscopy format of your MKV or AVC file :"] -fill x -padx 4 -pady 4 -expand 1
		pack [frame $w.f4.f] -fill x
		pack [ttk::combobox $w.f4.f.cb1 -values $::avcmodify::displayformats \
				-textvariable ::avcmodify::stereomode -state readonly] -fill x -expand 1 -side left -padx 2
		pack [ttk::button $w.f4.f.h -width 3 -text "?" -command StereoscopyFormatsHelp] -side left -padx 2
		pack [label $w.f4.w -text "Notes :  (*) Only available as MKV stereo-mode.    (**) Only available as AVC frame-packing."] -side left

		pack [ttk::labelframe $w.f5 -text "Tags to Create, Keep unchanged, Modify or Delete :"] -fill x -padx 4 -pady 4 -expand 1
		unset txt
		pack [frame $w.f5.f1 -bd 2 -relief ridge] -padx 4 -pady 2 -fill x -expand 1
		pack [frame $w.f5.f1.f] -side top
		pack [frame $w.f5.f1.f.f1] -pady 2
		pack [label $w.f5.f1.f.f1.t -text "MKV stereo-mode tag : "] -side left
		pack [ttk::radiobutton $w.f5.f1.f.f1.s1 -text "Create, Keep or Modify" -variable ::avcmodify::mkvkeep -value 1 \
				-command {.avcmodify.ok configure -text "Modify the 3D format tags of the MKV or AVC file..."}] -side left
		pack [ttk::radiobutton $w.f5.f1.f.f1.s2 -text "Delete tag" -variable ::avcmodify::mkvkeep -value 0 \
				-command {.avcmodify.ok configure -text "Modify the 3D format tags of the MKV or AVC file..."}] -side left
		pack [ttk::radiobutton $w.f5.f1.f.f1.s3 -text "Demux AVC only" -variable ::avcmodify::mkvkeep -value -1 -command DemuxOnlyWarning] -side left
		pack [ttk::button $w.f5.f1.f.b1 -text "Get current MKV stereoscopy format tag and Codec from the MKV file" -width 69 -command AVCModifyUpdateGUI -state disabled] -side top -pady 2
		
		pack [frame $w.f5.f2 -bd 2 -relief ridge] -padx 4 -pady 2 -fill x -expand 1
		pack [frame $w.f5.f2.f] -side top
		pack [frame $w.f5.f2.f.f2] -fill x -pady 2
		pack [label $w.f5.f2.f.f2.t -text "AVC frame-packing tag : "] -side left
		pack [ttk::radiobutton $w.f5.f2.f.f2.s2 -text "Create, Keep or Modify" -variable ::avcmodify::avckeep -value 1] -side left
		pack [ttk::radiobutton $w.f5.f2.f.f2.s3 -text "Delete tag" -variable ::avcmodify::avckeep -value 0] -side left
		pack [ttk::radiobutton $w.f5.f2.f.f2.s1 -text "Do not change" -variable ::avcmodify::avckeep -value -1 -command InPlaceWarning] -side left
		#pack [label $w.f5.f2.f.t2 -text "It is currently not possible to retrieve the current AVC\nframe-packing setting from the MKV or AVC file.\nNote:  Deleting or modifying this tag requires to demux and remux\nthe AVC video stream.  It's a relatively long operation."] -side top
		pack [ttk::button $w.f5.f2.f.b2 -text "Get current AVC frame-packing format from the AVC (h264) file" -width 69 -command AVCModifyUpdateGUI -state disabled] -side top -pady 2

		pack [ttk::labelframe $w.f6 -text "When the job is finished :"] -fill x -padx 4 -pady 4 -expand 1
		pack [ttk::checkbutton $w.f6.op1 -text "Delete temp AVC streams" -variable ::avcmodify::deltempavc]  -padx 4 -side left
		pack [ttk::checkbutton $w.f6.op2 -text "Open destination folder" -variable ::avcmodify::opendestdir] -padx 8 -side left
		pack [ttk::checkbutton $w.f6.op3 -text "Play the MKV video file" -variable ::avcmodify::playvideo]   -padx 4 -side left

		pack [ttk::button $w.ok -text "Modify the 3D format tags of the MKV or AVC file..." -width 69 -command AVCModifyMainJob -state disabled] -pady 6

		pack [ttk::progressbar $w.pr -orient horiz -maximum 100 -variable ::progress] -fill x -padx 4 -pady 2
		pack [frame $w.stf -bd 1 -height 2 -relief sunken] -fill x
		pack [entry $w.st -textvariable ::status -state readonly -exportselection false -bd 0 -relief flat -takefocus 0] -fill x -padx 4

		update
		wm minsize $w [winfo reqwidth $w] [winfo reqheight $w]
		wm protocol $w WM_DELETE_WINDOW "set ::status {}; Progress 0; grab release $w; wm withdraw $w"
		update
		wm geometry $w [winfo reqwidth $w]x[winfo reqheight $w]+[expr [winfo rootx .] + 4]+[expr [winfo rooty .] - 24]

		if {$::tcl_platform(platform) == "windows" && ! [catch {package require tkdnd}]} {
			dnd bindtarget $w text/uri-list <Drop> {AVCModifyGUIDrop %D}
		}
	}

	Progress 0

	if {$::avcmodify::infile == ""} {
		set state disabled
	} else {
		set state normal
	}
	.avcmodify.f3.e configure -state $state
	.avcmodify.f3.b configure -state $state

	wm resizable $w 1 0
	wm deiconify $w
	grab set $w
	focus $w
	focus $w.f2.f.b
	set ::status "Open or drop the MKV or AVC file to patch..."
	return
}

proc AVCModifyUpdateGUI {} {
	set w .avcmodify

	if {$::avcmodify::infile == ""} {return 1}

	.avcmodify.ok configure -text "Modify the 3D format tags of the MKV or AVC file..."

	set ext [string tolower [file extension $::avcmodify::infile]]
	if {$ext == ".mkv" || $ext == ".mk3d"} {
		if {$::avcmodify::mkvkeep == -1} {
			.avcmodify.ok configure -text "Demux the AVC video track from the MKV file..."
		}
		set vinfo [GetMKVVideoInfo [file normalize $::avcmodify::infile]]
		if {[string first "ERROR:" $vinfo] != -1} {
			StatusMsg $vinfo 0 1
			bell
			return 1
		}
		array set mkvinfo $vinfo
		set smode $mkvinfo(stereo_mode)
		if {$smode == ""} {
			set smode "Not present!"
			set ::avcmodify::stereomode " "
			#set ::avcmodify::mkvkeep 0
		} else {
			array set smodenames $::avcmodify::mkvformats
			foreach name [array names smodenames] {
				if {$smodenames($name) == $smode} {
					set smode $name
					set ::avcmodify::stereomode $smode
					#set ::avcmodify::mkvkeep 1
					break
				}
			}
		}
		set ::status "MKV tag: $smode ;  Codec: $mkvinfo(codec_id)"
	 	if {[string first "AVC" $mkvinfo(codec_id)] == -1} {
	 		append ::status " (Not AVC!)"
			set state disabled
			#set ::avcmodify::avckeep -1
	 	} else {
			set state normal
		}
		$w.f5.f2.f.f2.s1 configure -state $state
		$w.f5.f2.f.f2.s2 configure -state $state
		$w.f5.f2.f.f2.s3 configure -state $state
		focus $w.f4.f.cb1
	} elseif {$ext == ".avc" || $ext == ".264" || $ext == ".h264"} {
		set r [GetAVCFramePacking $::avcmodify::infile]
		set AVCFramePacking [lindex $r 1]
		set ::avcmodify::stereomode " " 
		if {$AVCFramePacking == " "} {
			StatusMsg "Frame-packing of AVC file : Not defined or not found"
		} else {
			StatusMsg "Frame-packing of AVC file : $AVCFramePacking"
		}
		if {[lsearch $::avcmodify::mkvformats $AVCFramePacking] >= 0} {
			set ::avcmodify::stereomode $AVCFramePacking
		}
		focus $w.f4.f.cb1
	} else {
		StatusMsg "ERROR: Unrecognised file extension $ext !" 1 1
		bell
		return 1
	}
	return 0
}

proc StereoscopyFormatsHelp {} {
	set msg    "This field should contain the 3D (or 2D) format to set in the destination MKV file and/or in the AVC stream.\n\n"
	append msg "BD3D2MK3D creates all 3D files in SBS, TAB (aka T&B) or Frame Sequential format, always Left view first (the well established standard), so you should normally use only one of that three stereoscopy formats if you need to modify a file that has been encoded with BD3D2MK3D.\n\n"
	append msg "(*) The Field Interlaced and the two Anaglyph 3D formats are only supported by the MKV stereo-mode.  They cannot be added as AVC frame-packing tags.\n\n"
	append msg "(**) The Frame Sequential (aka Frame Alternation) and Tile 3D formats are only supported by the AVC frame-packing.  They cannot be added as MKV stereo-mode tags.  The Frame Sequential tag is automatically added by BD3D2MK3D in the AVC stream, but unfortunately that tag is ignored by some players.\n\n"
	append msg "The Mono (2D) format is available, but it is useless, as without any tag a player should always assume that it's a 2D movie.\n\n"
	append msg "Use the Get Current Format buttons below to inspect the current tags.  Unfortunately, since it is not possible to retrieve the AVC frame-packing tag without demuxing the MKV file first, it is only possible to inspect that tag when your input file is an AVC elementary stream.\n\n"
	append msg "Some players may also use some extensions in the filename (such as \"Movie 3D HSBS.mkv\") to try to determine the 3D format.  So, to check your tags, it is better to remove these extensions."
	tk_messageBox -message $msg -icon info -parent .avcmodify -title "Stereoscopy formats help"
	return
}

proc DemuxOnlyWarning {} {
	.avcmodify.ok configure -text "Demux the AVC video track from the MKV file..."
	set msg "This option is there primilarly to help you inspect the 3D frame-packing of the AVC video stream of a MKV video file.  "
	append msg "Since it is impossible to retrieve it without demuxing the stream, this option does just that.  To inspect the frame-packing, load the demuxed AVC, and use the \"Get current AVC frame-packing\" button.\n\n"
	append msg "When this option is selected, most options from the GUI are not active (although you can still change them).\n\n"
	append msg "In particular, the output file is always saved in the output folder under the name \"XXX_orig.avc\" (where XXX is the original name of the MKV file).  "
	append msg "It is therefore useless to modify the output file name.\n\n"
	append msg "Similarly, as no file is being patched in this operation, the Correct 3D format and all options related to the 3D tags are ignored."
	tk_messageBox -message $msg -icon info -parent .avcmodify -title "Demux AVC Only help"
	return
}

proc InPlaceWarning {} {
	set msg "When the AVC frame-packing tag doesn't need to be modified (when Do not change is selected), it is not necessary to demux the AVC stream.\n"
	append msg "It is therefore possible to change the KKV stereoscopy mode in place, directly on the source MKV file with MkvPropEdit.\n"
	append msg "It's very fast, but that means that you will have no backup of your original file (but this operation is harmless).  "
	append msg "That should not be a problem, as you can modify or delete the MKV stereoscopy flag again if you did a mistake, but don't be surprised if you can't find the Output patched MKV file.  "
	append msg "The patched MKV file IS the original file."
	tk_messageBox -message $msg -icon warning -parent .avcmodify -title "Do not change AVC frame-packing warning"
	return
}

proc avcmodifyInput {} {
	set ::status ""
	set initialdir [GetProjectFolder]
	set initialfile ""
	if {$::avcmodify::infile != ""} {
		if {[file isdirectory [file dirname $::avcmodify::infile]]} {
			set initialdir [file dirname $::avcmodify::infile]
			if {[file exists $::avcmodify::infile]} {
				set initialfile [file tail $::avcmodify::infile]
			}
		}
	}
	set r [tk_getOpenFile -initialdir $initialdir -initialfile $initialfile \
			-filetypes {{{MKV and AVC} {.mkv .mk3d .avc .h264 .264}} \
			{{MKV video} {.mkv .mk3d}} {{AVC stream} {.avc .h264 .264}}} \
			-parent .avcmodify -title "Open the MKV or AVC file to patch..."]
	if {$r != ""} {
		set ::avcmodify::infile  [file nativename $r]
		if {$::avcmodify::usesrcdir} {
			set ::avcmodify::destdir [file nativename [file dirname $r]]
		}
		set ::avcmodify::outfile [file tail [file nativename [file rootname $r]_patched[file extension $r]]]
		.avcmodify.f2.f.e xview 1000
		.avcmodify.f3a.f2.sf xview 1000
		.avcmodify.f3.e xview 1000
		.avcmodify.f3.e icursor [string length [file rootname $::avcmodify::outfile]]
		set ext [string tolower [file extension $r]]
		if {$ext == ".avc" || $ext == ".h264" || $ext == ".264"} {
			set state disabled
			.avcmodify.f5.f2.f.b2 configure -state normal
		} else {
			set state normal
			.avcmodify.f5.f2.f.b2 configure -state disabled
		}
		.avcmodify.f5.f1.f.f1.s1 configure -state $state
		.avcmodify.f5.f1.f.f1.s2 configure -state $state
		.avcmodify.f5.f1.f.f1.s3 configure -state $state
		.avcmodify.f5.f1.f.b1    configure -state $state
		.avcmodify.f3.e          configure -state normal
		.avcmodify.f3.b          configure -state normal
		.avcmodify.f5.f2.f.f2.s1 configure -state normal
		.avcmodify.f5.f2.f.f2.s2 configure -state normal
		.avcmodify.f5.f2.f.f2.s3 configure -state normal
		.avcmodify.ok            configure -state normal
		Progress 0
	}
	return $r
}
proc AVCModifyGUIDrop {files} {
	set ::status ""
	set ext ""
	set found false
	foreach f $files {
		set ext [string tolower [file extension $f]]
		if {$ext == ".mkv" || $ext == ".mk3d" || $ext == ".avc" || $ext == ".h264" || $ext == ".264"} {
			set ::avcmodify::infile  [file nativename $f]
			if {$::avcmodify::usesrcdir} {
				set ::avcmodify::destdir [file nativename [file dirname $f]]
			}
			set ::avcmodify::outfile [file tail [file nativename [file rootname $f]_patched[file extension $f]]]
			.avcmodify.f2.f.e xview 1000
			.avcmodify.f3a.f2.sf xview 1000
			.avcmodify.f3.e xview 1000
			.avcmodify.f3.e icursor [string length [file rootname $::avcmodify::outfile]]
			focus .avcmodify.f3.e
			if {$ext == ".avc" || $ext == ".h264" || $ext == ".264"} {
				set state disabled
				.avcmodify.f5.f2.f.b2 configure -state normal
			} else {
				set state normal
				.avcmodify.f5.f2.f.b2 configure -state disabled
			}
			.avcmodify.f5.f1.f.f1.s1 configure -state $state
			.avcmodify.f5.f1.f.f1.s2 configure -state $state
			.avcmodify.f5.f1.f.f1.s3 configure -state $state
			.avcmodify.f5.f1.f.b1    configure -state $state
			.avcmodify.f3.e          configure -state normal
			.avcmodify.f3.b          configure -state normal
			.avcmodify.f5.f2.f.f2.s1 configure -state normal
			.avcmodify.f5.f2.f.f2.s2 configure -state normal
			.avcmodify.f5.f2.f.f2.s3 configure -state normal
			.avcmodify.ok            configure -state normal
			focus .avcmodify.f3.e
			Progress 0
			return $f
		}
	}
	set ::status "ERROR: Unrecognised file extension $ext"
	bell
	focus .avcmodify.f2.f.b
	return ""
}
proc avcmodifyDestDir {} {
	set ::status ""
	set initialdir ""
	if {$::avcmodify::infile != ""} {
		if {[file isdirectory [file dirname $::avcmodify::infile]]} {
			set initialdir [file dirname $::avcmodify::infile]
		}
	}
	if {$initialdir == ""} {
		set initialdir [GetProjectFolder]
	}
	set title "Save patched outout in this folder..."
	set r [tk_chooseDirectory -initialdir $initialdir -mustexist true -parent .avcmodify -title $title] 
	if {$r != ""} {
		set ::avcmodify::destdir [file nativename $r]
		focus .avcmodify.f3.e
	}
	Progress 0
	return $r
}
proc avcmodifyOutput {} {
	set ::status ""
	set initialdir ""
	set initialfile ""
	if {$::avcmodify::destdir != ""} {
		if {[file isdirectory $::avcmodify::destdir]} {
			set initialdir $::avcmodify::destdir
		}
		set initialfile [file tail $::avcmodify::outfile]
	}
	if {$initialdir == "" && $::avcmodify::infile != ""} {
		if {[file isdirectory [file dirname $::avcmodify::infile]]} {
			set initialdir [file dirname $::avcmodify::infile]
			set initialfile [file nativename [file rootname $::avcmodify::infile]_patched[file extension $::avcmodify::infile]]
		}
	}
	if {$initialdir == ""} {
		set initialdir [GetProjectFolder]
	}
	set filetypes  {{{MKV and AVC} {.mkv .mk3d .avc .h264 .264}} \
			{{MKV video} {.mkv .mk3d}} {{AVC stream} {.avc .h264 .264}}}
	set ext ""
	set title "Save patched outout as..."
	if {$::avcmodify::infile != ""} {
		set ext [string tolower [file extension $::avcmodify::infile]]
		if {$ext == ".mkv" || $ext == ".mk3d"} {
			set filetypes  {{{MKV video} {.mkv .mk3d}}}
			set title "Save patched MKV video as..."
		} elseif {$ext == "avc" || $ext == ".h264" || $ext == ".264"} {
			set filetypes  {{{AVC stream} {.avc .h264 .264}}}
			set title "Save patched AVC elementary stream as..."
		}
	}
	set r [tk_getSaveFile -initialdir $initialdir -initialfile $initialfile \
			-filetypes $filetypes -defaultextension $ext \
			-parent .avcmodify -title $title]
	if {$r != ""} {
		if {$::avcmodify::usesrcdir} {
			set ::avcmodify::destdir [file nativename [file dirname $r]]
		}
		set ::avcmodify::outfile [file tail [file nativename [file rootname $r]_patched[file extension $r]]]
		focus .avcmodify.f3.e
	}
	Progress 0
	return $r
}

proc GetMKVVideoInfo {mkvfile} {
	set exe [GetAppPath mkvinfo.exe true]
	if {[catch {set fl [open "|\"$exe\" \"[string map {/ \\\\} $mkvfile]\""]} err]} {
		bell
		return "ERROR: $err"
	}
	fconfigure $fl -encoding utf-8

	set intrack false
	set invideo false
	set lasttrackinfo {}
	set videoinfo {}
	while {! [eof $fl]} {
		set line [gets $fl]
		if {[string trim $line] == ""} continue
		set line [string map {{|+} {} {| + } {} {|  + } {} {|   + } {} {|    + } {}} [string trim $line]]

		if {$line == "Track"} {
			if {$invideo} {
				set videoinfo $lasttrackinfo
				break
			} else {
				set intrack true
				set invideo false
				set lasttrackinfo {}
				continue
			}
		}
		if {$intrack} {
			lappend lasttrackinfo $line
		}
		if {$line == "Video track"} {
			set invideo true
		}
	}
	if {[catch {close $fl} err]} {
		bell
		return "ERROR: MkvInfo exited abnormally."
	}
	if {$videoinfo == {}} {
		bell
		return "ERROR: Cannot find a video track in the MKV file!"
	}

	ToLog "\n*** Video information from MKV \"$mkvfile\" :"
	set infolist {}
	foreach line $videoinfo {
		set pos [string first ": " $line]
		if {$pos != -1} {
			ToLog $line
			set keyword [string map {{ } {_} \" {}} [string range $line 0 [expr $pos -1]]]
			set value   [string range $line [expr $pos +2] end]
			lappend infolist $keyword $value
		}
	}
	array set mkvinfo $infolist
	#ToLog $infolist
	puts ""

	set out {}
	set tracknum [expr [lindex $mkvinfo(Track_number) 0] -1]
	lappend out tracknum $tracknum
	set codec_id $mkvinfo(Codec_ID)
	lappend out codec_id $codec_id
	set stereo_mode ""
	catch {set stereo_mode [lindex $mkvinfo(Stereo_mode) 0]}
	lappend out stereo_mode $stereo_mode

	if { ! [catch {set name $mkvinfo(Name)}]} {
		lappend out name [string map {\" \\\" \\ \\\\} $name]
	}
	if { ! [catch {set language $mkvinfo(Language)}]} {
		lappend out language $language
	}
	if { ! [catch {set d_width  $mkvinfo(Display_width)}] && ! [catch {set d_height $mkvinfo(Display_height)}]} {
		lappend out display_dimensions ${d_width}x$d_height
	}
	if [info exists mkvinfo(Default_duration)] {
		set pos [string first " \(" $mkvinfo(Default_duration)]
		if {$pos != -1} {
			set fps [lindex [string range $mkvinfo(Default_duration) [expr $pos+2] end] 0]
			lappend out fps $fps
		}
	}
	if { ! [catch {set lacing $mkvinfo(Lacing_flag)}]} {
		lappend out lacing $lacing
	}
	if { ! [catch {set crop_left $mkvinfo(Pixel_crop_left)}] &&  ! [catch {set crop_top    $mkvinfo(Pixel_crop_top)}] && \
		 ! [catch {set crop_right $mkvinfo(Pixel_crop_right)}] && ! [catch {set crop_bottom $mkvinfo(Pixel_crop_bottom)}]} {
		lappend out cropping "$crop_left,$crop_top,$crop_right,$crop_bottom"
	}
	if {$::config(debug)} {ToLog $out}	
	return $out
}

proc GetAVCFramePacking {avcfile {returnhexstring false}} {
	set exe [GetAppPath sfk.exe true]
	ToLog "\n*** Getting the frame-packing SEI messages from \"$avcfile\"..."
	if {$::config(debug)} {
		ToLog "Command : \"$exe\" hexfind \"[file normalize $avcfile]\" -bin /0001062d/ -lean"
	}
	if {[catch {set fl [open "|\"$exe\" hexfind \"[file normalize $avcfile]\" -bin /0001062d/ -lean"]} err]} {
		bell
		ToLog "Command : \"$exe\" hexfind \"[file normalize $avcfile]\" -bin /0001062d/ -lean"
		ToLog "ERROR: $err"
		return [list "ERROR" $err]
	}
	set pid [pid $fl]
	fconfigure $fl -encoding utf-8

	set fpformat ""
	set fporder  "NOTFOUND"
	set found false
	set hexstring ""
	while {! [eof $fl]} {
		set fpformat ""
		set fporder  "NOTFOUND"

		set line [gets $fl]
		if {[string trim $line] == ""} continue
		if {[string range $line 2 3] == "% "} {
			set progress [string trimleft [string range $line 0 1] 0]
			if {$progress != ""} { 
				Progress $progress
			}
			continue
		}
		if {[string first "hit at offset" $line] > -1} {
			ToLog $line
			continue
		}
		if {[string range $line 0 10] == " >0001062D "} {
			ToLog $line
			set b0 [expr 0x[string range $line 11 12]]
			if {$b0 != 7 && $b0 != 4 && $b0 != 5} continue
			set b1 [expr 0x[string range $line 13 14]]
			if {$b1 < 0x80 || $b1 > 0x83} continue
			set b2 [expr 0x[string range $line 15 16]]
			if {[expr $b2 & 0x3C] != 0} continue
			#set b3 [expr 0x[string range $line 16 17]]	;# Frame flipping, currently not used by BD3D2MK3D
			set hexstring [string range $line 11 18]

			set fpqual  [expr $b2 & 0x80]

			if {$b0 == 7} {
				switch $b1 {
					128 {
						if {$fpqual != 128} continue
						set fpformat "COLINT"
					}
					129 {
						if {$fpqual == 128} {
							set fpformat "SBS"
						} elseif {$fpqual == 0} {
							set fpformat "ROWINT"
						} else {
							continue
						}
					}
					130 {
						if {$fpqual != 0} continue
						set fpformat "TAB"
					}
					131 {
						if {$fpqual == 0} {
							set fpformat "MONO"
						} elseif {$fpqual == 128} {
							set fpformat "TILE"
						} else {
							continue
						}
					}
					default {continue}
				}
			}
			if {$b0 == 4 && $b1 == 130 && [expr $b2 & 0x80] == 0x80} {
				set fpformat "FRAMEALT" 
			}
			if {$b0 == 5 && $b1 == 128 && [expr $b2 & 0x40] == 0x40} {
				set fpformat "CHECKER" 
			}
			set fporder [expr $b2 & 0x03]
			switch $fporder {
				0 {set fporder ""}
				1 {set fporder "LR"}
				2 {set fporder "RL"}
			}
		}
		if {$fpformat != "" && $fporder != "NOTFOUND"} {
			set found true
			Progress 100
			catch {kill $pid}
			break
		}
	}
	Progress 100
	catch {close $fl}
# 	if {[catch {close $fl} err]} {
# 		bell
# 		return [list "ERROR" "sfk exited abnormally."]
# 	}

	ToLog "Frame-packing : $fpformat:$fporder"
	if {$returnhexstring} {
		return [list "HEX" $hexstring]
	}

	if {$found} {
		set idx [lsearch $::avcmodify::avcformats $fpformat]
		if {$idx == -1} {
			set idx [lsearch $::avcmodify::avcformats "$fpformat:$fporder"]
		}
		if {$idx == -1} {
			set out "not defined or not found."
		} else {
			foreach {i j} $::avcmodify::mkvformats {
				if {$j == $idx} {
					set out $i
					break
				}
			}
			if {$out == " "} {set out "UNKNOWN"}
		}
	} else {
		set out " "
	}
	Progress 0
	return [list $fpformat:$fporder $out]
}

# Main job to mofigy the MKV stereo-mode and/or the AVC frame packing
#
# TODO: Implement the (missing in h264Modify) Frame Alternation AVC frame-packing with SFK :
# - Read the current AVC mode in hex (for example 0001062d87838100 for SBS:LR)
# - If not present, add any frame-packing with h264Modify
# - Overwrite the original frame-packing in the AVC file with this commend:
# sfk.exe replace "file_to_patch.avc" -bin /0001062dXXXXXX00/0001062d07838Y00/ -yes
# (where XXXXXXXX is the original frame-packing hex string, and Y is 1 for LR or 2 for RL)
proc AVCModifyMainJob {} {
	set ::status ""
	Progress 0

	if {$::avcmodify::infile == ""} {
		set ::status "Select the input MKV or AVC file first !"
		bell
		focus .avcmodify.f2.f.b
		return 0
	}
	if {! [file exists $::avcmodify::infile]} {
		set ::status "The input file doesn't exist !"
		bell
		focus .avcmodify.f2.f.b
		return 0
	}

	set ext [string tolower [file extension $::avcmodify::infile]]
	if {$ext == ".mkv" || $ext == ".mk3d"} {
		set inputtype "MKV"
	} else {
		set inputtype "AVC"
	}

	array set smodenames $::avcmodify::mkvformats
	set requestedmode $::avcmodify::stereomode

	# Only demux video from MKV
	if {$inputtype == "MKV" && $::avcmodify::mkvkeep == -1} {
		set  inavcstream "[file normalize [file join $::avcmodify::destdir [file tail [file rootname $::avcmodify::infile]]_orig.avc]]"
		if {[file exists $inavcstream]} {
			set r [tk_messageBox -message "Output AVC file exists already:\n\"[file tail $inavcstream]\"\n\nOK to overwrite it ?" \
					-title "Output AVC exists !" -icon warning -type yesno]
			if {$r == "no"} {
				return 0
			}
		}
		ToLog "Getting information from original MKV file..."
		set vinfo [GetMKVVideoInfo [file normalize $::avcmodify::infile]]
		if {[string first "ERROR:" $vinfo] == 0} {
			bell
			StatusMsg $vinfo 0 1
			focus .avcmodify.f2.f.b
			return 1
		}
		array set mkvinfo $vinfo
		ToLog "$mkvinfo(codec_id) track #$mkvinfo(tracknum), stereo mode: $mkvinfo(stereo_mode)" 
	 	if {[string first "AVC" $mkvinfo(codec_id)] == -1} {
	 		set ::status "Video stream is is not encoded with the AVC/h264 codec !"
			bell
			return 1
		}
		set r [DemuxVideoTrack [file normalize $::avcmodify::infile] $inavcstream $mkvinfo(tracknum)]
		puts ""
		Progress 0
		if {$r} {
			return 1
		} else {
			StatusMsg "AVC demuxed as \"[file tail $::avcmodify::infile]_orig.avc\"."
			if {$::avcmodify::opendestdir} {
				ToLog "Opening \"$::avcmodify::destdir\"..."
				catch {exec -- cmd /c start "" "$::avcmodify::destdir" &}
			}
			puts ""
			return 0
		}
	}

	if {$requestedmode == " "} {
		if {$::avcmodify::avckeep == 1 || ($::avcmodify::mkvkeep == 1 && $inputtype == "MKV")} {
			set ::status "Define the correct 3D output format first !"
			bell
			focus .avcmodify.f4.f.cb1
			return 0
		}
		set mkvstereomode ""
		set avcframepacking ""
	} else {
		set mkvstereomode $smodenames($requestedmode)
		set avcframepacking [lindex $::avcmodify::avcformats $mkvstereomode]
		if {$mkvstereomode >= 15 && $::avcmodify::mkvkeep == 1} {
			set mkvstereomode "DELETE"
		}
	}
	if {$inputtype == "MKV" && $::avcmodify::avckeep == -1 && $::avcmodify::mkvkeep == 1 \
			&& $mkvstereomode >= 15} {
		bell
		set ::status "The selected 3D format is not supported by the MKV stereo-mode tag !"
		focus .avcmodify.f4.f.cb1
		return 0
	}

	set outfile ""
	if {$::avcmodify::mkvkeep == 1 || $::avcmodify::avckeep != -1} {
		if {$::avcmodify::destdir == ""} {
			bell
			set ::status "Define the output folder first !"
			focus .avcmodify.f3a.f2.sfb
			return 0
		}
		if { ! [file isdirectory $::avcmodify::destdir]} {
			bell
			set ::status "The output folder doesn't exist !"
			focus .avcmodify.f3a.f2.sfb
			return 0
		}
		if {$::avcmodify::outfile == ""} {
			bell
			set ::status "Define the output MKV or AVC file first !"
			focus .avcmodify.f3.e
			return 0
		}
		set outfile [file join $::avcmodify::destdir $::avcmodify::outfile]
		if {[file exists $outfile]} {
			if {[tk_messageBox -message "The output file exists already:\n\"[file nativename $outfile]\"\nIf you continue, it will be overwritten.\n\nAre you sure ?" \
				-icon warning -title "Output file exists !" -parent .avcmodify -type okcancel] == "cancel"} {
				set ::status "Output MKV or AVC file exists !"
				focus .avcmodify.f3.e
				return 0
			}
		}
	}

	if {$::avcmodify::mkvkeep == 0} {
		set mkvstereomode "DELETE"
	}
	if {$::avcmodify::avckeep == 0} {
		set avcframepacking "DELETE"
	} elseif {$::avcmodify::avckeep == -1} {
		set avcframepacking "NOCHANGE"
	}

	set currentmkvmode ""
	set vinfo ""
	array set mkvinfo {}
	if {$inputtype == "MKV"} {
		ToLog "Getting information from original MKV file..."
		set vinfo [GetMKVVideoInfo [file normalize $::avcmodify::infile]]
		if {[string first "ERROR:" $vinfo] == 0} {
			bell
			StatusMsg $vinfo 0 1
			focus .avcmodify.f2.f.b
			return 1
		}
		array set mkvinfo $vinfo
		ToLog "$mkvinfo(codec_id) track #$mkvinfo(tracknum), stereo mode: $mkvinfo(stereo_mode)" 
		set currentmkvmode $mkvinfo(stereo_mode)
	}

	# Determine what has to be done
	
	set mkvmodify true
	set avcmodify true
	set demux true
	
	if {$avcframepacking == "NOCHANGE"} {
		set avcmodify false
		set demux false
	}

	if {$inputtype == "MKV"} {
		if {$mkvstereomode == "NOCHANGE"} {
			set mkvmodify false
		}
		if {$mkvstereomode == $currentmkvmode} {
			set mkvmodify false
			if { ! $avcmodify} {
				bell
				set ::status "Current MKV stereo-mode is already $requestedmode.  Nothing to do."
				focus .avcmodify.f2.f.b
				return 0
			}
		}
		if {$avcframepacking == "" && $::avcmodify::mkvkeep == 1} {
			tk_messageBox -icon error -parent .avcmodify -message \
				"\"$requestedmode\", as well as all Field interlaced and Anaglyph 3D modes, are not supported by the AVC frame-packing.\n\nYou should Delete the AVC frame-packing tag (or if it is present, you can leave it as it is, at your own risk).\n\nPlease retry."
			set avcmodify false
			set demux false
			focus .avcmodify.f5.f2.f.f2.s3
			return 0
		}
	}
	
	if {$inputtype == "AVC"} {
		set mkvmodify false
		set demux false
		if {$avcframepacking == ""} {
			bell
			set ::status "$requestedmode is not supported by AVC frame-packing."
			focus .avcmodify.f4.f.cb1
			return 1
		}
	}

	if { ! $mkvmodify && ! $avcmodify} {
		bell
		set ::status "Nothing to do !"
		return 0
	}

	puts "\n\n"
	StatusMsg "######## Add/Remove 3D Video Format Tags job started ######## ***"
	puts ""
	ToLog "Input file: $::avcmodify::infile"
	if {$inputtype == "MKV"} {
		ToLog "Video track number: $mkvinfo(tracknum)"
		ToLog "Original MKV 3D mode: $currentmkvmode"
	}
	ToLog "Requested stereo mode: MKV = $mkvstereomode, AVC = $avcframepacking"
	ToLog "Outputfile: $outfile"
	puts ""
	
	set  inavcstream "[file normalize [file join [file dirname $outfile] [file tail $::avcmodify::infile]_orig.avc]]"
	set outavcstream "[file normalize [file join [file dirname $outfile] [file tail $::avcmodify::infile]_patched.avc]]"
	#ToLog "\nmkvmodify $mkvmodify, avcmodify $avcmodify, demux $demux"

	# Workaround for the missing Frame Alternate format in H264Modify
	if {[string first "FRAMEALT" $avcframepacking] == 0 && $avcmodify} {
		set framealt true
		set useavcframepacking "TILE:LR"
	} else {
		set framealt false
		set useavcframepacking $avcframepacking
	}

	if {$mkvmodify && ! $avcmodify} {
		set r [SetMKVstereoModeWithPropEdit [file normalize $::avcmodify::infile] $mkvinfo(tracknum) $mkvstereomode]
		if {$r} {return 1}
		puts ""
	} elseif { ! $mkvmodify && $avcmodify != 0} {
		if {$inputtype == "AVC"} {
			set  inavcstream "[file normalize $::avcmodify::infile]"
			set outavcstream "[file normalize $outfile]"
			set r [ModifyAVCStream $inavcstream $outavcstream $useavcframepacking]
			if {$r} {return 1}
			puts ""
			if {$framealt} {
				set r [PatchAVCStreamForFrameAlt $outavcstream $avcframepacking]
				puts ""
				if {$r} {return 1}
			}
		} else {
			set r [DemuxVideoTrack [file normalize $::avcmodify::infile] $inavcstream $mkvinfo(tracknum)]
			puts ""
			if {$r} {return 1}
			set r [ModifyAVCStream $inavcstream $outavcstream $useavcframepacking]
			puts ""
			if {$r} {return 1}
			if {$::avcmodify::deltempavc} {
				StatusMsg "Deleting the temp orig AVC stream."
				catch {file delete  $inavcstream}
				puts ""
			}
			if {$framealt} {
				set r [PatchAVCStreamForFrameAlt $outavcstream  $avcframepacking]
				puts ""
				if {$r} {return 1}
			}
			set r [RemuxVideoTrack [file normalize $::avcmodify::infile] $outavcstream [file normalize $outfile] $vinfo $currentmkvmode]
			puts ""
			if {$r} {return 1}
			if {$::avcmodify::deltempavc} {
				StatusMsg "Deleting the temp patched AVC stream."
				catch {file delete  $outavcstream}
				puts ""
			}
		}
	} elseif {$mkvmodify && $avcmodify} {
		set r [DemuxVideoTrack [file normalize $::avcmodify::infile] $inavcstream $mkvinfo(tracknum)]
		puts ""
		if {$r} {return 1}
		set r [ModifyAVCStream $inavcstream $outavcstream $useavcframepacking]
		puts ""
		if {$r} {return 1}
		if {$::avcmodify::deltempavc} {
			StatusMsg "Deleting the temp orig AVC stream."
			catch {file delete  $inavcstream}
			puts ""
		}
		if {$framealt} {
			set r [PatchAVCStreamForFrameAlt $outavcstream  $avcframepacking]
			puts ""
			if {$r} {return 1}
		}
		set r [RemuxVideoTrack [file normalize $::avcmodify::infile] $outavcstream [file normalize $outfile] $vinfo $mkvstereomode]
		puts ""
		if {$r} {return 1}
		if {$::avcmodify::deltempavc} {
			StatusMsg "Deleting the temp patched AVC stream."
			catch {file delete  $outavcstream}
			puts ""
		}
		# Workaround for the mkvmerge bug that doesn't set the MONO stereo-mode: do it with MkvPropEdit
		if {$mkvstereomode == 0} { 
			StatusMsg "Setting the stereo-mode MONO to \"[file tail $outfile]\" with MkvPropEdit..."
			SetMKVstereoModeWithPropEdit $outfile 0 0 true
			puts ""
		}
	}
	StatusMsg "Operation successfull. Verify the output file!"
	Progress 0

	if {$::avcmodify::opendestdir} {
		ToLog "Opening \"$::avcmodify::destdir\"..."
		catch {exec -- cmd /c start "" "$::avcmodify::destdir" &}
	}
	if {$::avcmodify::playvideo && $inputtype == "MKV"} {
		if {$::avcmodify::opendestdir} {Pause 1000}
		ToLog "Playing \"[file nativename $outfile]\"..."
		if {[catch {exec -- cmd /c start "" "[string map {\\ \\\\} [file nativename $outfile]]" &} err]} {
			ToLog "Can't play the MKV file: $err" 1
			ToLog "Command was: cmd /c start \"\" \"[string map {\\ \\\\} [file nativename $outfile]]\"" 1
			ToLog "To play the output MKV, you should use a good 3D player that obey the 3D tags, like PotPlayer."
		}
	}
	puts ""
	return 0
}

proc SetMKVstereoModeWithPropEdit {mkvfile tracknum mkvstereomode {quiet false}} {
	if {! $quiet} {
		StatusMsg "Patching original \"[file tail $mkvfile]\" with MkvPropEdit..."
	}
	incr tracknum ;# MkvPropEdit track numbers are starting at 1
	set cmd "\"[GetAppPath mkvpropedit.exe true]\" \"[file normalize $mkvfile]\" --edit track:$tracknum "
	if {$mkvstereomode == "DELETE"} {
		append cmd "--delete stereo-mode"
	} else {
		append cmd "--set stereo-mode=$mkvstereomode"
	}
	ToLog "Command: $cmd"
	set p 20
	Progress $p
	if {[catch {set fh [open "|$cmd" r]} err]} {
		StatusMsg "ERROR patching MKV file: $err" false 1
		bell
		return 1
	}
	incr p 20
	Progress $p
	while {![eof $fh]} {
		set line [gets $fh]
		ToLog $line
		incr p 20
		Progress $p
	}
	Progress 0
	if {[catch {close $fh} err]} {
		StatusMsg "ERROR patching MKV file: $err" false 1
		bell
		return 1
	}
	if {! $quiet} {
		StatusMsg "Original MKV file patched successfully." false 0
	}
	return 0
}

proc DemuxVideoTrack {mkvfile avcstream tracknum} {
	StatusMsg "Demuxing track $tracknum from \"[file tail $mkvfile]\"..." false 0
	set cmd "\"[GetAppPath mkvextract.exe true]\" \"[file normalize $mkvfile]\" tracks \"$tracknum:[file normalize $avcstream]\""
	ToLog "Command: $cmd"
	if {[catch {set fh [open "|$cmd" r]} err]} {
		StatusMsg "Demux ERROR: $err" false 1
		bell
		return 1
	}
	while {![eof $fh]} {
		set line [gets $fh]
		if {[string first "Progress: " $line] == 0} {
			Progress [string trim [lindex $line 1] "%"]
		} else {
			ToLog $line
		}
	}
	Progress 0
	if {[catch {close $fh} err]} {
		StatusMsg "ERROR closing mkvextract command: $err" false 1
		bell
		return 1
	}
	StatusMsg "Demux of track $tracknum successfull" false 0
	return 0
}

proc ModifyAVCStream {inavcstream outavcstream avcframepacking} {
	StatusMsg "Modifying the frame-packing SEI messages of the AVC stream \"[file tail $inavcstream]\" to \"[file tail $outavcstream]\"..." false 0
	set cmd "\"[GetAppPath h264Modify.exe true]\" \"[file normalize $inavcstream]\" \"[file normalize $outavcstream]\" -frame_packing $avcframepacking"
	ToLog "Command: $cmd"
	set filesize [file size $inavcstream]
	if {$filesize < 20} {
		StatusMsg "ERROR: Input AVC stream is too short ($filesize bytes)!"
		bell
		catch {close $fh}
		return 1
	}
	if {[catch {set fh [open "|$cmd" r]} err]} {
		StatusMsg "ERROR modifying AVC stream: $err" false 1
		bell
		return 1
	}
	set lastline ""
	set nal7set false
	while {![eof $fh]} {
		set line [gets $fh]
		if { ! $nal7set && $line == "  nal_unit_type:  7 \"Sequence parameter set\""} {
			set nal7set true
			ToLog $line
			continue
		}
		if {[string first "NAL position " $line] == 0} {
			set idx [string first " (" $line]
			incr idx 2
			Progress [string range $line $idx end-1] $filesize
		} elseif {[string range $line 0 1] == "  "} {
			continue
		} elseif {$line == ""} {
			continue
		} else {
			ToLog $line
			set lastline $line
		}
	}
	Progress 100

#   # Can't use this, as h264Modify issues strange warnings in stderr when the command is closed !
#   # https://forum.doom9.org/showthread.php?p=1985128#post1985128
# 	if {[catch {close $fh} err]} {
# 		StatusMsg "ERROR: $err" false 1
# 		bell
# 		Progress 0
# 		return 1
# 	}
	catch {close $fh}
	if {[string first "End position " $lastline] == 0} {
		if {$nal7set } {
			StatusMsg "AVC stream successfully modified as \"[file tail $outavcstream]\"." false 0
		} else {
			StatusMsg "ERROR: NAL unit type 7 has not been created, modified or deleted!" false 1
			bell
			return 1
		}
	} else {
		StatusMsg "WARNING: AVC stream might not have been successfully patched!" false 0
		bell
	}

	Progress 0
	return 0
}

# Workaround for the missing Frame Alternate format in H264Modify
proc PatchAVCStreamForFrameAlt {avcfile avcframepacking} {
	set desthexstr "04828110"
	if {[string first ":RL" $avcframepacking] >= 0} {
		set desthexstr "04828210"
	}
	set r [GetAVCFramePacking $avcfile true]
	if {[lindex $r 0] == "HEX"} {
		set orighexstr [lindex $r 1]
	} else {
		return 1
	}
	set exe [GetAppPath sfk.exe true]
	ToLog "\n*** Patching the AVC stream \"[file tail $avcfile]\" for frame-packing $avcframepacking (not yet supported by h264Modify.exe)..."
	set cmd "\"$exe\" replace \"[file normalize $avcfile]\" -bin /0001062d$orighexstr/0001062d$desthexstr/ -yes"
	if {$::config(debug)} {
		ToLog "Command : $cmd"
	}
	if {[catch {set fl [open "|$cmd"]} err]} {
		bell
		ToLog "Command : $cmd"
		ToLog "ERROR: $err"
		return 1
	}
	while {! [eof $fl]} {
		set line [gets $fl]
		if {[string trim $line] == ""} continue
		if {[string range $line 2 3] == "% "} {
			set progress [string trimleft [string range $line 0 1] 0]
			if {$progress != ""} { 
				Progress $progress
			}
			continue
		}
		ToLog $line
	}
	Progress 0
	catch {close $fl}
	return 0
}

proc RemuxVideoTrack {inmkvfile avcstream outmkvfile vinfo mkvstereomode} {
	StatusMsg "Remuxing the AVC stream to the final MKV \"[file tail $outmkvfile]\"..." false 0
	ToLog "MKV stereo-mode = $mkvstereomode"

	array set mkvinfo $vinfo

	set cmd "\"[GetAppPath mkvmerge.exe true]\" --ui-language en --priority lower --output \"[file normalize $outmkvfile]\" --compression 0:none "
	if {$mkvstereomode != "DELETE"} {
		append cmd "--stereo-mode 0:$mkvstereomode "
	}
	if { ! [catch {set name $mkvinfo(name)}]} {
		append cmd "--track-name \"0:$name\" "
	}
	if { ! [catch {set language $mkvinfo(language)}]} {
		append cmd "--language \"0:$language\" "
	}
	if { ! [catch {set display_dimensions $mkvinfo(display-dimensions)}]} {
		append cmd "--display-dimensions \"0:$display_dimensions\" "
	}
	if { ! [catch {set fps $mkvinfo(fps)}]} {
		if {$fps == 23.976} {set fps 24000/1001}
		if {$fps == 29.97 } {set fps 30000/1001}
		if {$fps == 47.952} {set fps 48000/1001}
		if {$fps == 59.94 } {set fps 60000/1001}
		if {[info exists Lacing_flag] && $Lacing_flag == 1} {
			set fps "${fps}i"
		} else {
			set fps "${fps}p"
		}
		append cmd "--default-duration \"0:$fps\" "
	}
	if { ! [catch {set cropping  $mkvinfo(cropping)}]} {
		append cmd "--cropping 0:$cropping "
	}

	append cmd "\"[file normalize $avcstream]\" --no-video \"[file normalize $inmkvfile]\""
	ToLog "Command: $cmd"

	if {[catch {set fh [open "|$cmd" r]} err]} {
		StatusMsg "Mux ERROR: $err" false 1
		bell
		return 1
	}
	while {![eof $fh]} {
		set line [gets $fh]
		if {[string first "Progress: " $line] == 0} {
			Progress [string trim [lindex $line 1] "%"]
		} else {
			ToLog $line
		}
	}
	Progress 0
	if {[catch {close $fh} err]} {
		StatusMsg "ERROR closing MkvMerge command: $err" false 1
		bell
		return 1
	}
	StatusMsg "Successfull remux of \"[file tail $outmkvfile]\"" false 0
	return 0
}

# Add menu item in Tools menu
if {[catch {.mainmenu.tools index "Modify 3D format tags in MKV or AVC"}]} {
	.mainmenu.tools insert "Verify MKV file" command -label "Modify 3D format tags in MKV or AVC" -command AVCModifyGUI

	if {$::config(debug) && [winfo exists .mainmenu.debug]} {
		.mainmenu.debug add command -label "Reload AVC3Dmodifier.tcl" -command {
			destroy .avcmodify
			catch {namespace delete ::.avcmodify}
			after 10 {
				source [file join $::TOOLSETPATH AVC3Dmodifier.tcl]
			}
			after 10 AVCModifyGUI
		}
	}
}

