#!/usr/bin/env python
# -*- coding: utf-8 -*-
#---------------------------------------------------------------------------------------
# Player for LiveStream(WebCam etc) with BGM
# use ffmpeg(muxer) + liveStreamer (video stream)
#                   + audio_cat (Audio stream)
#---------------------------------------------------------------------------------------
import os, sys
import time
import glob
import subprocess
import codecs
import threading
import random
import win32pipe, win32file
import textwrap
import tempfile
import urllib
import atexit

from PIL import Image,ImageChops,ImageOps
from PIL import ImageDraw, ImageFont
from optparse import OptionParser
from multiprocessing import Process, Lock, Pipe
from RzWebSubs import ws_getAudiolist,ws_mkconcat

sys.path.append('regzamod')
from Common.RzCmnSubs import dbg,dbg2,dbg0,error,setdbg
from Common.RzCmnSubs import isAudio,isImage,isVideo,isWebVideo,isWebContents,conv_encoding
from Common.RzCmnSubs import gs_encode_sys,gs_debug,gs_verbose,gs_ff_loglev
from Common.RzCmnSubs import gs_python,gs_prog_ytdl,gs_prog_ytdl_s,gs_prog_streamer,gs_streamer_conf

#---- globals -------------------------
ytopts_filmon0="--hls-segment-timeout 10 --hls-timeout 60"  #default, for first connection
ytopts_filmon1="--hls-segment-timeout 10 --hls-timeout 10"  #for re-connect
ytopts_filmon1="--hls-segment-timeout 10 --hls-timeout 20"  #for re-connect
ytopts_filmon1="--hls-segment-timeout 10 --hls-timeout 30"  #for re-connect

#---- external progs
#prog_ffmpeg="win32/ffmpeg.exe"  #not work well
prog_ffmpeg="win32/ffmpeg-RZ.exe"

dummy_audio="regzamod/RzIAVplayer/DefaultClips/Silent-180sec.mp3"
use_bgm=1
g_multi_pipe=1  # ffmpeg can use multi-pipe_input
g_webtemp_prefix="web_log"
g_abps=448000
g_asrat=48000
g_ustream_mobile=0    #use High-resolution type stream (uhs) (cause failure)
g_ustream_mobile=1    #use Low- resolution type stream (hls) (working)
logf=sys.stderr
auto_pipe=0  # conect PIPE by SYS, todo: need watch dog when i died

def audiocat (vlist,mpos,spos,mmax,pipe_w):
	#dbg("audiocat: start, spos=%d, vlist=%r" % (spos,vlist))
	
	ytdl_opt="best[height=720]/bestvideo[height<=480]/best"
	ytdl_opt="bestaudio/best"
	
	if(spos>len(vlist)):
		spos=0
	while(True):
		#setnxpos(mpos+1,spos+1,mmax)
		bgv=vlist[spos]
		dbg("audiocat: 1")
		bgvs=bgv.encode("cp932")  # what the heck!! subprocess.Popen args force shift-jis
		dbg("audiocat: 2 bgvs=%s" % bgvs)
		ffpara_v="-f vob -c:a ac3 -ab %d -ar %d -q:a 1 -loglevel %s -y -map 0:a" % (g_abps,g_asrat,gs_ff_loglev)
		#dbg("audiocat: 3 bgvs=%r" % bgvs)
		if(isWebVideo(bgv)):
			dbg("audiocat: 4 isWebVideo=true")
			ffpara_v="\"%s\" -i pipe:0 %s pipe:1" % (opt.progpath2,ffpara_v)
			#dbg("audiocat: 5")
			bgvs=bgvs.replace("&","^&").replace("|","^|").replace("(","^(").replace(")","^)")   # escape DOS special chars
			ytpara_v="%s -f \"%s\" \"%s\"" % (gs_prog_ytdl_s,ytdl_opt,bgvs)
			#dbg("audiocat: 6")
			para_v="%s -o - | %s" % (ytpara_v,ffpara_v)
			#dbg("audiocat-web: exec bgv proc para=%r" % para_v)
			p4=exec_prog_sh(para_v,sys.stdin,pipe_w,sys.stderr,False)
			p4.wait()
		else:
			para_v="\"%s\" -i \"%s\"  %s pipe:1" % (opt.progpath2,bgvs,ffpara_v)
			dbg("audiocat: exec bgv proc para=%r" % para_v)
			p4=exec_prog_sh(para_v,sys.stdin,pipe_w,sys.stderr,False)
			p4.wait()
			dbg("audiocat: exit code=%r" % p4.returncode)
			if(p4.returncode!=0):
				break
		spos+=1
		if(spos>=len(vlist)):
			spos=0

def exec_prog_sh (args,stdi,stdo,stde,clfd):
	dbg("exec_prog_sh args=%r" % args)
	p=None
	try:
		cwd="./"
		p = subprocess.Popen(args, shell=True, cwd=cwd, stdin=stdi, stdout=stdo,
			stderr=stde, close_fds=clfd)
	except OSError:
		dbg("exec_prog_sh: Failed to exec %s" % args)
	return p

def exec_prog (args,stdi,stdo,stde,sh):
	if(gs_debug>0): dbg("rzLivePlayer: exec_prog: args=%r" % args)
	p=None
	try:
		cwd="./"
		p = subprocess.Popen(args, shell=sh, bufsize=-1, stdin=stdi, stdout=stdo,
			stderr=stde, close_fds=False)
	except OSError:
		dbg("rzLivePlayer: exec_prog: Failed to exec %s" % args)
	#p.wait()
	return p

def named_pipe (name):
	#pname=r'\\.\pipe\wfsr_pipe'
	# pipe may become multiple in a session, so shouldn't use constant id
	# ex. pipes of prev and new process may overwap and co-exist in a short time for change
	#pname="\\\\.\\pipe\\%s(%s)" % (name,opt.sess_id)

	millis = int(round(time.time() * 1000))
	pname="\\\\.\\pipe\\%s(%d)" % (name,millis)
	dbg("pname=%s" % pname)
	
	fh = win32pipe.CreateNamedPipe(pname,
                          win32pipe.PIPE_ACCESS_DUPLEX,
                          win32pipe.PIPE_TYPE_MESSAGE | win32pipe.PIPE_WAIT,
                          1,65536,65536,300,None)
	return fh,pname

def watchdog_timer(pid,timeup):
	time.sleep(timeup)
	os.kill(pid,9)
	dbg("rzLivePlayer: watchdog_timer: timeout=%d, kill pid=%d" % (timeup,pid))

def watchdog_timer2(pid1,pid2,timeup):
	time.sleep(timeup)
	os.kill(pid1,9)
	os.kill(pid2,9)
	dbg("rzLivePlayer: watchdog_timer2: timeout=%d, kill pid=%d" % (timeup,pid))

def watchdog_wait(kill_pid,wait_proc):
	dbg("watchdog_wait: target proc=%r" % wait_proc)
	#if(wait_proc!=None):  # don't use !=, to compare with None
	#if(wait_proc is not None): # even this ,valid wait_proc seems judged as None, why??
	if(wait_proc is not None):
		wait_proc.wait()
	else:
		return
	
	dbg("watchdog_wait: target proc(pid=%r) terminated" % wait_proc.pid)
	time.sleep(2.0)
	if(kill_pid>0):
		# kill will cause error messasge on PMS
		os.kill(kill_pid,9) 
	else:
		# kill target must be me
		# does't work well: sys.exit seems to work only on main thread, not on sub thread
		#sys.exit(1)  
		os._exit(1)

#---- watchdog
def watchdog_pipe(pr,ppid,pid1,pid2,tempf):
	import time  #need here
	# kill child(pid) when parent(ppid) diled
	dbg("rzLivePlayer: watchdog_pipe: started, mypid=%r parent pid=%r target_pid=%r,%r" % (os.getpid(), ppid, pid1, pid2))
	time1=time.time()

	try:
		#read pipe in blocking mode
		#i.e. wait untill parent die, b/c parent never send to the pipe
		pr.recv()
	except EOFError:
		dbg("rzLivePlayer: watchdog_pipe: EOFError on pipe.recv")
		#parent seems to be killed
		pass	#Noop
	except IOError:
		dbg("rzLivePlayer: watchdog_pipe: IOError on pipe.recv")
		pass	#Noop
	except:
		dbg("rzLivePlayer: watchdog_pipe: Unknown Exception")
		pass	#Noop
	
	dbg("rzLivePlayer: watchdog_pipe: kill pid=%r,%r" % (pid1,pid2))
	try:
		if(pid1 is not None):
			os.kill(pid1,9)
		if(pid2 is not None):
			os.kill(pid2,9)
	except WindowsError:
		dbg("rzLivePlayer: watchdog_pipe: WindowsError: pid=%r,%r may not exists" % (pid1,pid2))

	time2=time.time()
	time=time2-time1
	dbg("rzLivePlayer: watchdog_pipe: play time=%f" % time)
	#sys.exit(0)
	os._exit(0)

#---- pipe pump
def pipe_pump(pr,pw):
	#transfer data inter-pipe
	#child progs will die if i died. b/c pipe will disconnected
	cnt=0
	err=0
	while True:
		cnt+=1
		try:
			#small buffer may cause audio stattering
			buf=pr.read(50000)
			if(buf):
				#dbg("rzLivePlayer.pipe_pump: Write Start cnt=%d, len=%d" % (cnt,sys.getsizeof(buf)))
				pw.write(buf)
				#dbg("rzLivePlayer.pipe_pump: Write End cnt=%d" % cnt)
			else:
				dbg("rzLivePlayer.pipe_pump: read ended, exit loop")
				sys.stdout.flush()
				pw.close()
				break
		except Exception,e:
			dbg("rzLivePlayer.pipe_pump: Exception caught err=%r, exit loop" % e)
			#break
			os._exit(0) 

def pipe_win(fi,fo):
	dbg("pipe_rw: Start")
	bufsz=50000
	while True:
		try:
			#dbg("pipe_win: read start")
			data=fi.read(bufsz)
			#dbg("pipe_win: read end")
			if(data):
				rc,wc=win32file.WriteFile(fo,data,None)
			else:
				break
		except Exception,e:
			dbg("rzLivePlayer.pipe_win: Exception caught err=%r, exit loop" % e)
			#break
			os._exit(0)

	dbg("pipe_win: End")
	fi.close()

#----------------------------------------------------------------------------------
# main
#----------------------------------------------------------------------------------
if __name__ == '__main__':
	
	#setdbg(gs_debug)
	#---- change default encoding
	if(False):
		#seems to have no effects
		reload(sys)
		sys.setdefaultencoding('utf-8')

	dbg("rzLivePlayer: Main Start")

	#---- get main args 
	if(len(sys.argv)<3):
		print >>sys.stderr, "rzLivePlayer: Usage: rzLivePlayer.py {video_in(URL)} {video_out} [options]"
		sys.exit(1)
		
	myprog=sys.argv[0]
	url=sys.argv[1]
	video_out=sys.argv[2]
	#bgm_in=sys.argv[3]    # path string may contain spaces 
	
	#---- get main args
	#OptionParser() can't handle param value with spaces?
	parser = OptionParser()
	parser.add_option("--sess_id",		action="store",	dest="sess_id",		type="string"	,default="0")
	parser.add_option("--bgm",			action="store",	dest="bgm",			type="int"		,default=0)
	parser.add_option("--bgm_in",		action="store",	dest="bgm_in",		type="string"	,default="regzamod/RzWEBplayer/test/PolyLithm.mp3")
	parser.add_option("--opt_str",		action="store",	dest="opt_str",		type="string"	,default="")
	parser.add_option("--temp",			action="store",	dest="temp",		type="string"	,default=".")
	parser.add_option("--dpsize_w",		action="store",	dest="dpsize_w",	type="int"		,default=1280)
	parser.add_option("--dpsize_h",		action="store",	dest="dpsize_h",	type="int"		,default=720)
	parser.add_option("--ifps",			action="store",	dest="ifps",		type="float"	,default=0.0)
	parser.add_option("--clippath_a",	action="store",	dest="clippath_a",	type="string"	,default=None)

	parser.add_option("--m3u8",			action="store",	dest="m3u8",		type="int"		,default=0)
	parser.add_option("--m2ts",			action="store",	dest="m2ts",		type="int"		,default=0)
	parser.add_option("--h264",			action="store",	dest="h264",		type="int"		,default=0)
	parser.add_option("--remux",		action="store",	dest="remux",		type="int"		,default=0)
	parser.add_option("--asp_hack",		action="store",	dest="asp_hack",	type="int"		,default=0)
	parser.add_option("--aspect",		action="store",	dest="aspect",		type="string"	,default="16:9")
	parser.add_option("--progpath",		action="store",	dest="progpath",	type="string",	default="win32/ffmpeg.exe")
	parser.add_option("--progpath2",	action="store",	dest="progpath2",	type="string",	default="win32/ffmpeg-RZ.exe")
	parser.add_option("--retry_cnt" ,	action="store",	dest="retry_cnt",	type="int",		default=0)
	(opt,args) = parser.parse_args()

	#---- init settings 
	opt.temp=opt.temp+"\\web"  # slash cause confusion on ffmpeg 
	#ws_init(opt.temp,opt.sess_id)
	#logf=opt.temp+"/"+g_webtemp_prefix+"("+opt.sess_id+")"+".txt"

	#---- opt args 
	ifps=""
	ifps_v=""
	if(opt.ifps==25.0):
		ifps="-r 25000/1001"
		ifps_v="25000/1001"
	
	no_audio=0
	if(opt.opt_str.rfind("-no_audio")>=0):
		no_audio=1
	
	proc_type=0
	pos=opt.opt_str.rfind("proc_type=")
	if(pos>=0):
		lst=opt.opt_str[pos+len("proc_type="):].split(",",1)
		dbg("param peoc_type="+lst[0])
		proc_type=int(lst[0])

	trans_format=""
	pos=opt.opt_str.rfind("trans_format=")
	if(pos>=0):
		lst=opt.opt_str[pos+len("trans_format="):].split(",",1)
		dbg("param trans_format="+lst[0])
		trans_format=lst[0]
	
	ff_transfmt="vob"
	ff_m2ts=""
	if(trans_format=="m2ts"):
		ff_transfmt="mpegts"
		ff_m2ts="-mpegts_m2ts_mode 1"

	#---- judge process mode
	exproc_v=0
	exproc_a=0
	video_in=url
	if(url.find("ustream")>=0 and url.find("recorded")<0 or proc_type==3):  
		# ustream live
		video_in="pipe:0"
		exproc_v=1
		
	elif(url.endswith("m3u8")):
		# youtube live?
		pass
	
	if(use_bgm==0):
		opt.bgm=0

	#---- get bgm
	if(opt.bgm>=1):
		#Indicates force add bgm 
		dbg("RzLivePlayer: opt.clippath_a=%s" % opt.clippath_a)
		alist=ws_getAudiolist(opt.clippath_a)
		#dbg("RzLivePlayer: alist=%r" % alist)
		if(len(alist)<=0):
			opt.clippath_a="regzamod/RzIAVplayer/DefaultClips"
			alist=ws_getAudiolist(opt.clippath_a)
		dbg("RzLivePlayer: audio_list size=%d" % len(alist))
		if(len(alist)<1):
			dbg("RzLivePlayer: audio_list has no entries --> use dummy_audio")
			alist=[dummy_audio]
	elif(no_audio):
		#Indicates video without audio: may cause error on terminal, Let's supply dummy audio 
		alist=[dummy_audio]
	
	# make audio concat file
	if(not g_multi_pipe and (opt.bgm>=1 or no_audio)):
		bgm_in=None
		pos=random.randint(0,len(alist)-1)
		if(alist[pos].startswith("http")):
			#ffmpeg concat seems can't handle url contents
			bgm_in=alist[pos]
		else:	
			concatf="%s\\concat(%s).txt" % (opt.temp,opt.sess_id)
			#make concatinated audios last long time
			max=len(alist)
			if(max<40):
				max=40   # avr. 3min * 40 = 120min
			ws_mkconcat(alist,pos,concatf,max)	
		dbg("RzLivePlayer: audio_list select pos=%d" % pos)
		
	#---- kick transcoder main
	ffopt="-user-agent Firefox/26.0 -threads 4 "
	ffopt="-y"  # mustn't be null

	#ffmpeg's auto scaling fails some time!!
	#vf_param="-vf scale=%d:%d" % (opt.dpsize_w,opt.dpsize_h)
	#vf_param="-filter_complex pad=(ih+1)*16/9/sar:ih:(ow-iw)/2:(oh-ih)/2,scale=%dx%d" % (opt.dpsize_w,opt.dpsize_h)
	#vf_param="-filter_complex pad='if(gt(iw,(ih+1)*16/9/sar),iw,(ih+1)*16/9/sar)':ih:'if(gt(ow,iw),(ow-iw)/2,0)':'if(gt(oh,ih),(oh-ih)/2,0)',scale=%dx%d" % (opt.dpsize_w,opt.dpsize_h)
	#vf_param="-filter_complex scale='if(gt(a,16/9),1280,-1)':'if(gt(a,16/9),-1,720)',pad=1280:720:'if(gt(1280,iw),(1280-iw)/2,0)':'if(gt(720,ih),(720-ih)/2,0)'"
	
	#vf_param="-filter_complex scale='if(gt(dar,16/9),%s,-1)':'if(gt(dar,16/9),-1,%s)',pad=%s:%s:'if(gt(%s,iw),(%s-iw)/2,0)':'if(gt(%s,ih),(%s-ih)/2,0)'" % (opt.dpsize_w,opt.dpsize_h,opt.dpsize_w,opt.dpsize_h,opt.dpsize_w,opt.dpsize_w,opt.dpsize_h,opt.dpsize_h)
	vf_param="-filter_complex scale='if(gt(dar,16/9),%s,%s*dar)':'if(gt(dar,16/9),%s/dar,%s)',crop='if(gt(iw,%s),%s,iw)':'if(gt(ih,%s),%s,ih)',pad=%s:%s:'if(gt(%s,iw),(%s-iw)/2,0)':'if(gt(%s,ih),(%s-ih)/2,0)'" % (opt.dpsize_w,opt.dpsize_h,opt.dpsize_w,opt.dpsize_h,opt.dpsize_w,opt.dpsize_w,opt.dpsize_h,opt.dpsize_h,opt.dpsize_w,opt.dpsize_h,opt.dpsize_w,opt.dpsize_w,opt.dpsize_h,opt.dpsize_h)
	
	if(opt.bgm>=1 or no_audio):
		#---- use given bgm as audio,instead of audio in video
		if(g_multi_pipe):
			# multi pipe_input for ffmpeg doesn't work well
			#(bgm_fdr,bgm_fdw)=os.pipe()  # for bgm piping: don't work well
			bgm_fdh,bgm_fdn= named_pipe("pipe_win")
			
			#ffpara="-f %s -vcodec mpeg2video -acodec ac3 -ab %d -ar 48000" % (ff_transfmt,g_abps)
			#ffpara="-f %s -vcodec mpeg2video -acodec copy -async 10" % (ff_transfmt)
			ffpara="-f %s -vcodec mpeg2video -acodec copy" % (ff_transfmt)
			
			#ffpara+=" -q:v 1 -vf scale=%d:%d -aspect %s" % (opt.dpsize_w,opt.dpsize_h,opt.aspect)
			ffpara+=" -q:v 1 %s -aspect %s" % (vf_param,opt.aspect)
			ffpara+=" -loglevel %s -y -map 1:v -map 0:a %s" % (gs_ff_loglev,video_out)
			if(ifps_v==""):
				para=[prog_ffmpeg,"-i",bgm_fdn,ffopt,            "-i",video_in] + ffpara.split()
			else:
				para=[prog_ffmpeg,"-i",bgm_fdn,ffopt,"-r",ifps_v,"-i",video_in] + ffpara.split() 
		else:
			# video_in,bgm_in strings may contain spaces: so shouldn't split by space
			# -stream_loop seems don't work well: 
			# -f vob stops whole video at single audio ends
			# -f mpegts doesn't stops whole video , but cause freeze on rewind,pause 
			if(bgm_in is not None):
				ffpara="%s %s -i %s -i %s -f %s -vcodec mpeg2video -acodec ac3 -ar 48000" % (ffopt,ifps,video_in,bgm_in,ff_transfmt)
				ffpara+=" -ab %d -q:v 1 %s -aspect %s" % (g_abps,vf_param,opt.aspect)
				ffpara+=" -loglevel %s -y %s -map 0:v -map 1:a %s" % (gs_ff_loglev,ff_m2ts,video_out)
				para=[prog_ffmpeg] + ffpara.split()
			else:
				#--- concatf is file_path: may contain spaces, so use keyword instead of realvalue to avoid splitted by split()
				ffpara="%s %s -i %s -stream_loop -1 -safe 0 -f concat -i $concat$ -f %s -vcodec mpeg2video -acodec ac3 -ar 48000" % (ffopt,ifps,video_in,ff_transfmt)
				ffpara+=" -ab %d -q:v 1 %s -aspect %s" % (g_abps,vf_param,opt.aspect)
				ffpara+=" -loglevel %s -y %s -map 0:v -map 1:a %s" % (gs_ff_loglev,ff_m2ts,video_out)
				para=[prog_ffmpeg] + ffpara.split()
				
	else:
		#---- use audio in the video
		ffpara="%s -i %s -f %s -vcodec mpeg2video -acodec ac3 -ar 48000" % (ffopt,video_in,ff_transfmt)
		ffpara+=" -ab %d -q:v 1 %s -aspect %s " % (g_abps,vf_param,opt.aspect)
		ffpara+=" -loglevel %s -y %s %s" % (gs_ff_loglev,ff_m2ts,video_out)
		para=[prog_ffmpeg] + ffpara.split()
	
	#--- substitute keyword to realvalue
	for i in range(len(para)):  
		# range(n): (0 to n-1)
		if(para[i]=="$concat$"):
			para[i]=concatf
	
	dbg("rzLivePlayer: transcoder main params=%r" % para)
	
	if(exproc_v==0):
		p1=exec_prog(para,sys.stdin,sys.stdout,sys.stderr,False)
	else:
		p1=exec_prog(para,subprocess.PIPE,None,None,False)
	
	#---- kick video_extructor (Livestreamer)
	p2=None
	if(exproc_v!=0): # need special extructor for video 
		#livestreamer began fail on 'best(uhs)' for ustream, use 'mobile(hls:HTTP Live Streaming)' instead
		#ytpara=" %s best --stdout" % (url)
		if(g_ustream_mobile and url.find("ustream")>=0):
			#use mobile(HLS) type stream 
			stream_type="mobile_1080p,mobile_720p,mobile_480p,mobile_360p,mobile_240p,best"
		else:
			#use hi-res type stream : began failing
			stream_type="best"
		
		ytopts=""
		if(url.find("http://www.filmon.com")>=0):
			#to fast detect timeout for FilmON
			if(opt.retry_cnt==0):
				ytopts=ytopts_filmon0
			else:
				ytopts=ytopts_filmon1
			#pass
			
		# syntax: livestreamer [OPTIONS] [URL] [STREAM]
		# --retry-streams {delay_secs}: retry open the stream that not opened yet
		# --retry-open {retry_counts} : retry re-open the stream that once opened
		# --> aboves has no effecs for the case you want retry when connection once closed from the site
		#ytpara="--retry-streams 1 --retry-open 1 --config %s --stdout %s %s" % (gs_streamer_conf,url,stream_type)
		ytpara="--config %s %s --stdout %s %s" % (gs_streamer_conf,ytopts,url,stream_type)
		
		#para=[prog_streamer]+ytpara.split()
		para=gs_prog_streamer+ytpara.split()
		if(auto_pipe):
			p2=exec_prog(para,sys.stdin,p1.stdin,sys.stderr,False)
		else:
			p2=exec_prog(para,sys.stdin,subprocess.PIPE,sys.stderr,False)
	
	#---- kick watchdog "proc" for detect parent died------
	# Process: run as a process
	pid_p1=None
	pid_p2=None
	if(p1 is not None):
		pid_p1=p1.pid
	if(p2 is not None):
		pid_p2=p2.pid
	pr,pw=Pipe()	
	p3=Process(target=watchdog_pipe,args=(pw,os.getpid(),pid_p1,pid_p2,logf))
	p3.start()
	
	#---- kick watchdog "thread" for detect child proc p1 died
	wdwait1=threading.Thread(target=watchdog_wait, name="watchdog_wait", args=(os.getpid(),p1))
	wdwait1.start()
	
	#---- kick watchdog "thread" for detect child proc p2 died
	wdwait2=threading.Thread(target=watchdog_wait, name="watchdog_wait", args=(os.getpid(),p2))
	wdwait2.start()

	#---- pipe pumping within above two proc (p2(video_extructor) --> p1(main_transcoder))
	pump1=None
	if(not auto_pipe and p2 is not None):
		#transfer data inter-pipe
		dbg("rzLivePlayer: Pumping Start")
		pump1=threading.Thread(target=pipe_pump, name="pipe_pump1", args=(p2.stdout,p1.stdin))
		pump1.start()

	#---- kick bgm proc
	pump2=None
	if(g_multi_pipe and (opt.bgm>=1 or no_audio)):
		pr2,pw2=os.pipe()
		fr= os.fdopen(pr2)
		fw= os.fdopen(pw2)
		
		#---- kick pipe_pump (t3(audiocat) --> p1(main_transcoder))
		dbg("rzLivePlayer: kick pipe_win")

		t2=threading.Thread(target=pipe_win, name="pipe_win", args=(fr,bgm_fdh))
		t2.start()
		mmax=len(alist)
		mpos=0
		spos=random.randint(0,len(alist)-1)
		
		#---- kick bgm proc
		dbg("rzLivePlayer: kick audiocat")
		
		t3=threading.Thread(target=audiocat, name="audiocat", args=(alist,mpos,spos,mmax,fw))
		t3.start()
		
		dbg("rzLivePlayer: p1.wait() Start")
		p1.wait();
		dbg("rzLivePlayer: p1.wait() End")

		while(False):
			if(True):
				#audio in
				ffpara="-f vob -acodec ac3 -ab %d -ar 48000 -loglevel %s -y pipe:1" % (g_abps,gs_ff_loglev)
				bgm=alist[pos]
				bgm=bgm.encode("cp932")  # whoat the heck!! subprocess.Popen args force shift-jis
				para=[prog_ffmpeg, "-i",bgm] + ffpara.split()
				dbg("rzLivePlayer: bgm proc para=%r" % para)
				p4=exec_prog(para,sys.stdin,fw,sys.stderr,False)
				p4.wait()
				pos+=1
				if(pos>=len(alist)):
					pos=0

			elif(False):
				fp=open(opt.bgm_in,"rb")
				pump2=threading.Thread(target=pipe_pump, name="pipe_pump2", args=(fp,os.fdopen(bgm_fdw,"wb")))
				pump2.start()
				if(pump2 is not None):
					pump2.join()
			else:
				ffpara="-f ac3 -acodec ac3 -ab %d -loglevel %s -y -" % (g_abps,gs_ff_loglev)
				para=[prog_ffmpeg, "-i", alist[pos]] + ffpara.split()
				dbg("rzLivePlayer: bgm proc para=%r" % para)
				p4=exec_prog(para,sys.stdin,subprocess.PIPE,sys.stderr,False)
				pump2=threading.Thread(target=pipe_pump, name="pipe_pump2", args=(p4.stdout,os.fdopen(bgm_fdw)))
				pump2.start()
				if(pump2 is not None):
					pump2.wait()
	
	#---- ending ------------------------
	dbg("rzLivePlayer: Ending Start")
	if(pump1 is not None):
		pump1.join()
	dbg("rzLivePlayer: pump1.join() end")
	
	sys.stdout.flush()
	if(p2 is not None):
		p2.terminate()
	p1.wait();
	p3.terminate()
	time.sleep(2)
	#sys.exit()
	os._exit(0)
