-- vim:set ft=lua:
ini='Setting\\HttpPublic.ini'
dir=edcb.GetPrivateProfile('SET', 'ModulePath', '', 'Common.ini')..'\\Tools\\'
ffmpeg=edcb.GetPrivateProfile('SET','ffmpeg',dir..'ffmpeg',ini)

onid=tonumber(mg.get_var(mg.request_info.query_string, 'onid'))
tsid=tonumber(mg.get_var(mg.request_info.query_string, 'tsid'))
sid=tonumber(mg.get_var(mg.request_info.query_string, 'sid'))
mode=tonumber(mg.get_var(mg.request_info.query_string, 'mode')) or 2

mp4=tonumber(edcb.GetPrivateProfile('SET','mp4',false,ini))~=0

-- ios判定
for hk,hv in pairs(mg.request_info.http_headers) do
  if hk:lower()=='user-agent' then
    for i,v in ipairs({'iPhone','iPad'}) do
      if hv:match(v) then
        ios=true
        break
      end
    end
    break
  end
end

-- 変換コマンド
quality=mg.get_var(mg.request_info.query_string, 'quality') or ''
XOPT=edcb.GetPrivateProfile('MOVIE',quality,false,ini)
-- iosの場合強制的にmp4
if XOPT=='0' or (ios and not XOPT:match('mp4'))then
  if mp4 or ios then
    XOPT='-vcodec libx264 -profile:v main -level 31 -b:v 896k -maxrate 4M -bufsize 4M -preset veryfast -g 120 -vf yadif=0:-1:1 -s 512x288 -r 30000/1001 -acodec aac -ab 128k -f mp4 -movflags frag_keyframe+empty_moov -'
  else
    XOPT='-vcodec libvpx -b:v 896k -quality realtime -cpu-used 1 -vf yadif=0:-1:1 -s 512x288 -r 30000/1001 -acodec libvorbis -ab 128k -f webm -'
  end
end
-- mp4判定 (XOPTにmp4が含まれているはず)
mp4=XOPT:match('mp4')

audio=tonumber(mg.get_var(mg.request_info.query_string, 'audio'))
if audio then
  if audio==0 then
    XOPT='-map 0:0 -map 0:1 -map 0:2 '..XOPT
  elseif audio<10 then
    XOPT='-map 0:0 -map 0:'..audio..' '..XOPT
  elseif audio==10 then
    XOPT='-filter_complex channelsplit[FL][FR] -map 0:v -map [FL] -map [FR] -metadata:s:a:0 language=jpn -metadata:s:a:1 language=eng '..XOPT  --デュアルモノ[日]
  elseif audio==11 then
    XOPT='-filter_complex channelsplit[FL][FR] -map 0:v -map [FR] -map [FL] -metadata:s:a:0 language=eng -metadata:s:a:1 language=jpn '..XOPT  --デュアルモノ[英]
  end
end

-- 変換後の拡張子
XEXT=mp4 and '.mp4' or '.webm'
-- 転送開始前に変換しておく量(bytes)
XPREPARE=tonumber(edcb.GetPrivateProfile('SET','xprepare',48128,ini))
-- NetworkTVモードの名前付きパイプをFindFileで見つけられない場合(EpgTimerSrvのWindowsサービス化など？)に対応するか
FIND_BY_OPEN=tonumber(edcb.GetPrivateProfile('SET','FIND_BY_OPEN',false,ini))~=0

n=math.floor(tonumber(mg.get_var(mg.request_info.query_string, 'n')) or 0)
id=tonumber(mg.get_var(mg.request_info.query_string, 'id')) or 0

-- トランスコードするかどうか
XCODE=bit32.band(mode,2)==2 and tonumber(mg.get_var(mg.request_info.query_string, 'xcode') or 1)~=0

if n<0 then
  -- プロセスが残っていたらすべて終わらせる
  edcb.os.execute('wmic process where "name=\'ffmpeg.exe\' and commandline like \'%%SendTSTCP[_]%%[_]%%\'" call terminate >nul')
elseif n<=65535 then
  if onid and edcb.IsOpenNetworkTV then
    if id<0 then id=math.random(1000) end
    -- NetworkTVモードを開始
    ok,pid=edcb.OpenNetworkTV(mode, onid, tsid, sid, id)
  end
  if sid==0 then
    -- NetworkTVモードを終了
    edcb.CloseNetworkTV(id)
  elseif XCODE then
    -- PID取得を試みる
    if not pid and edcb.IsOpenNetworkTV then ok,pid=edcb.IsOpenNetworkTV(id) end
    if ok then
      -- 名前付きパイプができるまで待つ
      for i=1,50 do
        ff=edcb.FindFile('\\\\.\\pipe\\SendTSTCP_*_'..pid, 1)
        if ff and ff[1].name:find('^[^_]+_%d+_%d+$') then
          f=edcb.io.popen('""'..ffmpeg..'" -f mpegts -i "\\\\.\\pipe\\'..ff[1].name..'" '..XOPT..'"', 'rb')
          fname='view'..XEXT
          break
        elseif FIND_BY_OPEN then
          -- ポートを予想して開いてみる
          for j=0,9 do
            ff=edcb.io.open('\\\\.\\pipe\\SendTSTCP_'..j..'_'..pid, 'rb')
            if ff then
              ff:close()
              -- 再び開けるようになるまで少しラグがある
              edcb.Sleep(4000)
              f=edcb.io.popen('""'..ffmpeg..'" -f mpegts -i "\\\\.\\pipe\\SendTSTCP_'..j..'_'..pid..'" '..XOPT..'"', 'rb')
              fname='view'..XEXT
              break
            end
          end
          if ff then break end
        end
        edcb.Sleep(200)
      end
    end
  end
end

if not f then
  if onid and not ok then
    ct='<error>'..(edcb.IsOpenNetworkTV and 'EpgDataCap_Bonの起動に失敗' or 'EDCBが非対応です')..'</error>'
  elseif XCODE and sid~=0 and not ff then
    ct='<error>名前付きパイプが見つかりませんでした</error>'
    if onid then edcb.CloseNetworkTV(id) end
  elseif ok or sid==0 then
    ct='<success>EpgDataCap_Bonを'..(ok and '起動' or '停止')..'</success><id>'..id..'</id>'
  end
  if ct then
    ct='<?xml version="1.0" encoding="UTF-8" ?'..'><entry>'..ct..'</entry>'
    mg.write('HTTP/1.1 200 OK\r\nContent-Type: text/xml\r\nContent-Length: '..#ct..'\r\nConnection: close\r\n\r\n', ct)
  else
    mg.write('HTTP/1.1 404 Not Found\r\nConnection: close\r\n\r\n')
  end
else
  mg.write('HTTP/1.1 200 OK\r\nContent-Type: '..mg.get_mime_type(fname)..'\r\nContent-Disposition: filename='..fname..'\r\nConnection: close\r\n\r\n')
  while true do
    buf=f:read(XPREPARE or 48128)
    XPREPARE=nil
    if buf and #buf ~= 0 then
      if not mg.write(buf) then
        -- キャンセルされた
        mg.cry('canceled')
        break
      end
    else
      -- 終端に達した
      mg.cry('end')
      break
    end
  end
  f:close()
  if onid then edcb.CloseNetworkTV(id) end
end
