[mythtvnz] mythburn.py stream order
Brett
mythicalbeast at slingshot.co.nz
Sun Oct 31 00:59:37 BST 2010
Context:
Using mytharchive mythburn.py for DVD creation from transcoded dvb-t ts
recordings
Issue:
The mythburn.py script incorrectly configures the ts file stream order
for ffmpeg. It only works if the video is the first stream.
The script works okay if the stream order happens to be video first i.e.
TV3 (video,ac3,latm,data).
But the stream order on Prime is reported by myth/ffmpeg as
(data,video,latm_aac) & this fails to configure correctly.
The modified script correctly configures ffmpeg streams for Prime & TV3
& prefers AC3 over LATM_AAC & then LATM_AAC over other.
It correctly sets the video stream if it is not the first stream.
As in original script AC3, if present, is copied to preserve 5.1 as 2.0
downmix is not right in ffmpeg.
Brett
-------------- next part --------------
# hack for /usr/share/mythtv/mytharchive/mythburn.py
# corrects stream order to configure ffmpeg
# 4257 ############################################################
# 4258 chooses which streams from a file to include on the DVD
# tuple index constants
VIDEO_INDEX = 0
VIDEO_CODEC = 1
VIDEO_ID = 2
AUDIO_INDEX = 0
AUDIO_CODEC = 1
AUDIO_ID = 2
AUDIO_LANG = 3
AUDIO_LATM = "LIBFAAD_LATM"
INDEX_TYPE = "streamindex" # "ffmpegindex"
def selectStreams(folder):
"""Choose the streams we want from the source file"""
video = (-1, 'N/A', -1) # index, codec, ID
audio1 = (-1, 'N/A', -1, 'N/A') # index, codec, ID, lang
audio2 = (-1, 'N/A', -1, 'N/A')
#open the XML containing information about this file
infoDOM = xml.dom.minidom.parse(os.path.join(folder, 'streaminfo.xml'))
#error out if its the wrong XML
if infoDOM.documentElement.tagName != "file":
fatalError("This does not look like a stream info file (%s)" % os.path.join(folder, 'streaminfo.xml'))
#get video ID, CODEC
nodes = infoDOM.getElementsByTagName("video")
if nodes.length == 0:
write("Didn't find any video elements in stream info file.!!!")
write("");
sys.exit(1)
if nodes.length > 1:
write("Found more than one video element in stream info file.!!!")
node = nodes[0]
video = (int(node.attributes[INDEX_TYPE].value), node.attributes["codec"].value, int(node.attributes["id"].value))
write("BLM debug video ffmpegindex %s streamindex %s" % (node.attributes["ffmpegindex"].value, node.attributes["streamindex"].value))
#get audioID's - we choose the best 2 audio streams using this algorithm
# 1. if there is one or more stream(s) using the 1st preferred language we use that
# 2. if there is one or more stream(s) using the 2nd preferred language we use that
# 3. if we still haven't found a stream we use the stream with the lowest PID
# 4. we prefer ac3 over AUDIO_LATM
# 5. if there are more that one stream with the chosen language we use the one with the lowest PID
write("Preferred audio languages %s and %s" % (preferredlang1, preferredlang2))
nodes = infoDOM.getElementsByTagName("audio")
if nodes.length == 0:
write("Didn't find any audio elements in stream info file.!!!")
write("");
sys.exit(1)
found = False
# first try to find a stream with ac3 and preferred language 1
for node in nodes:
index = int(node.attributes[INDEX_TYPE].value)
lang = node.attributes["language"].value
format = string.upper(node.attributes["codec"].value)
pid = int(node.attributes["id"].value)
if lang == preferredlang1 and format == "AC3":
if found:
if pid < audio1[AUDIO_ID]:
audio1 = (index, format, pid, lang)
else:
audio1 = (index, format, pid, lang)
found = True
# second try to find a stream with AUDIO_LATM and preferred language 1
if not found:
for node in nodes:
index = int(node.attributes[INDEX_TYPE].value)
lang = node.attributes["language"].value
format = string.upper(node.attributes["codec"].value)
pid = int(node.attributes["id"].value)
if lang == preferredlang1 and format == AUDIO_LATM:
if found:
if pid < audio1[AUDIO_ID]:
audio1 = (index, format, pid, lang)
else:
audio1 = (index, format, pid, lang)
found = True
# finally use the stream with the lowest pid, prefer ac3 over AUDIO_LATM
if not found:
for node in nodes:
index = int(node.attributes[INDEX_TYPE].value)
format = string.upper(node.attributes["codec"].value)
pid = int(node.attributes["id"].value)
if not found:
audio1 = (index, format, pid, lang)
found = True
else:
if format == "AC3" and audio1[AUDIO_CODEC] == AUDIO_LATM:
audio1 = (index, format, pid, lang)
else:
if pid < audio1[AUDIO_ID]:
audio1 = (index, format, pid, lang)
# do we need to find a second audio stream?
if preferredlang1 != preferredlang2 and nodes.length > 1:
found = False
# first try to find a stream with ac3 and preferred language 2
for node in nodes:
index = int(node.attributes[INDEX_TYPE].value)
lang = node.attributes["language"].value
format = string.upper(node.attributes["codec"].value)
pid = int(node.attributes["id"].value)
if lang == preferredlang2 and format == "AC3":
if found:
if pid < audio2[AUDIO_ID]:
audio2 = (index, format, pid, lang)
else:
audio2 = (index, format, pid, lang)
found = True
# second try to find a stream with mp2 and preferred language 2
if not found:
for node in nodes:
index = int(node.attributes[INDEX_TYPE].value)
lang = node.attributes["language"].value
format = string.upper(node.attributes["codec"].value)
pid = int(node.attributes["id"].value)
if lang == preferredlang2 and format == AUDIO_LATM:
if found:
if pid < audio2[AUDIO_ID]:
audio2 = (index, format, pid, lang)
else:
audio2 = (index, format, pid, lang)
found = True
# finally use the stream with the lowest pid, prefer ac3 over mp2
if not found:
for node in nodes:
index = int(node.attributes[INDEX_TYPE].value)
format = string.upper(node.attributes["codec"].value)
pid = int(node.attributes["id"].value)
if not found:
# make sure we don't choose the same stream as audio1
if pid != audio1[AUDIO_ID]:
audio2 = (index, format, pid, lang)
found = True
else:
if format == "AC3" and audio2[AUDIO_CODEC] == AUDIO_LATM and pid != audio1[AUDIO_ID]:
audio2 = (index, format, pid, lang)
else:
if pid < audio2[AUDIO_ID] and pid != audio1[AUDIO_ID]:
audio2 = (index, format, pid, lang)
write("Video id: [%d] 0x%x (%s), Audio1: [%d] 0x%x (%s, %s), Audio2: [%d] - 0x%x (%s, %s)" % \
(video[VIDEO_INDEX], video[VIDEO_ID], video[VIDEO_CODEC], \
audio1[AUDIO_INDEX], audio1[AUDIO_ID], audio1[AUDIO_CODEC], audio1[AUDIO_LANG], \
audio2[AUDIO_INDEX], audio2[AUDIO_ID], audio2[AUDIO_CODEC], audio2[AUDIO_LANG]))
return (video, audio1, audio2)
# 4418
More information about the mythtvnz
mailing list