Skip to content

Commit

Permalink
Legacy WebUI: asyncbuf.exeを追加
Browse files Browse the repository at this point in the history
pvやmbufferの簡易版みたいなもの
送信待ちの間に変換処理が失速しがちなため
  • Loading branch information
xtne6f committed Aug 23, 2020
1 parent 73d3cf0 commit a375241
Show file tree
Hide file tree
Showing 5 changed files with 339 additions and 23 deletions.
6 changes: 4 additions & 2 deletions Document/MinGW/Makefile
Expand Up @@ -7,7 +7,7 @@ TARGETS = EpgDataCap_Bon \
Write_Default \
EpgTimerSrv

all: readex.exe relayread.exe tsidmove.exe cp_dep $(addsuffix .all, $(TARGETS))
all: asyncbuf.exe readex.exe relayread.exe tsidmove.exe cp_dep $(addsuffix .all, $(TARGETS))
clean: $(addsuffix .clean, $(TARGETS)) rm_dep rm_tools
%.all:
$(MAKE) -C ../../$*/$* TARGET=../../Document/MinGW/$*
Expand All @@ -19,6 +19,8 @@ ifdef MINGW_PREFIX
endif
rm_dep:
$(RM) libwinpthread-1.dll
asyncbuf.exe: ../../ini/Tools/asyncbuf.c
$(CC) -municode -Wl,-s -static -D_UNICODE -Os -o $@ $<
readex.exe: ../../ini/Tools/readex.c
$(CC) -municode -Wl,-s -static -D_UNICODE -Os -o $@ $<
relayread.exe: ../../ini/Tools/relayread.c
Expand All @@ -30,4 +32,4 @@ tsidmove.exe: ../../Common/ParseTextInstances.cpp \
../../ini/Tools/tsidmove/tsidmove.cpp
$(CXX) -municode -Wl,-s -static-libgcc -static-libstdc++ -I../../ini/Tools/tsidmove -D_UNICODE -std=c++17 -pedantic-errors -Os -o $@ $+
rm_tools:
$(RM) readex.exe relayread.exe tsidmove.exe
$(RM) asyncbuf.exe readex.exe relayread.exe tsidmove.exe
25 changes: 15 additions & 10 deletions ini/HttpPublic/legacy/view.lua
@@ -1,9 +1,5 @@
-- 名前付きパイプ(SendTSTCPの送信先:0.0.0.1 ポート:0~65535)を転送するスクリプト

-- コマンドはEDCBのToolsフォルダにあるものを優先する
ffmpeg=edcb.GetPrivateProfile('SET', 'ModulePath', '', 'Common.ini')..'\\Tools\\ffmpeg.exe'
if not edcb.FindFile(ffmpeg, 1) then ffmpeg='ffmpeg.exe' end

-- フィルタオプション
XFILTER='-vf yadif=0:-1:1'
XFILTER_CINEMA='-vf pullup -r 24000/1001'
Expand All @@ -15,11 +11,18 @@ XOPT='-vcodec libvpx -b:v 896k -quality realtime -cpu-used 1 $FILTER -s 512x288
-- 変換後の拡張子
XEXT='.webm'
--XEXT='.mp4'
-- 出力バッファの量(bytes。asyncbuf.exeを用意すること。変換負荷や通信のむらを吸収する)
XBUF=0
-- 転送開始前に変換しておく量(bytes)
XPREPARE=nil
XPREPARE=0
-- NetworkTVモードの名前付きパイプをFindFileで見つけられない場合(EpgTimerSrvのWindowsサービス化など?)に対応するか
FIND_BY_OPEN=false

-- コマンドはEDCBのToolsフォルダにあるものを優先する
tools=edcb.GetPrivateProfile('SET','ModulePath','','Common.ini')..'\\Tools\\'
ffmpeg=(edcb.FindFile(tools..'ffmpeg.exe',1) and tools or '')..'ffmpeg.exe'
asyncbuf=(edcb.FindFile(tools..'asyncbuf.exe',1) and tools or '')..'asyncbuf.exe'

dofile(mg.script_name:gsub('[^\\/]*$','')..'util.lua')

post=AssertPost()
Expand Down Expand Up @@ -50,7 +53,8 @@ if true 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'..dual..' -i "\\\\.\\pipe\\'..ff[1].name..'" -map 0:v:0 -map 0:a:'..audio2..' '..XOPT:gsub('$FILTER',filter)..'"', 'rb')
f=edcb.io.popen('""'..ffmpeg..'" -f mpegts'..dual..' -i "\\\\.\\pipe\\'..ff[1].name..'" -map 0:v:0 -map 0:a:'..audio2..' '..XOPT:gsub('$FILTER',filter)
..(XBUF>0 and ' | "'..asyncbuf..'" '..XBUF..' '..XPREPARE or '')..'"', 'rb')
fname='view'..XEXT
break
elseif FIND_BY_OPEN then
Expand All @@ -61,7 +65,8 @@ if true then
ff:close()
-- 再び開けるようになるまで少しラグがある
edcb.Sleep(4000)
f=edcb.io.popen('""'..ffmpeg..'" -f mpegts'..dual..' -i "\\\\.\\pipe\\SendTSTCP_'..j..'_'..pid..'" -map 0:v:0 -map 0:a:'..audio2..' '..XOPT:gsub('$FILTER',filter)..'"', 'rb')
f=edcb.io.popen('""'..ffmpeg..'" -f mpegts'..dual..' -i "\\\\.\\pipe\\SendTSTCP_'..j..'_'..pid..'" -map 0:v:0 -map 0:a:'..audio2..' '..XOPT:gsub('$FILTER',filter)
..(XBUF>0 and ' | "'..asyncbuf..'" '..XBUF..' '..XPREPARE or '')..'"', 'rb')
fname='view'..XEXT
break
end
Expand All @@ -84,7 +89,8 @@ if true then
-- 名前付きパイプがあれば開く
ff=edcb.FindFile('\\\\.\\pipe\\SendTSTCP_'..n..'_*', 1)
if ff and ff[1].name:find('^[^_]+_%d+_%d+$') then
f=edcb.io.popen('""'..ffmpeg..'" -f mpegts'..dual..' -i "\\\\.\\pipe\\'..ff[1].name..'" -map 0:v:0 -map 0:a:'..audio2..' '..XOPT:gsub('$FILTER',filter)..'"', 'rb')
f=edcb.io.popen('""'..ffmpeg..'" -f mpegts'..dual..' -i "\\\\.\\pipe\\'..ff[1].name..'" -map 0:v:0 -map 0:a:'..audio2..' '..XOPT:gsub('$FILTER',filter)
..(XBUF>0 and ' | "'..asyncbuf..'" '..XBUF..' '..XPREPARE or '')..'"', 'rb')
fname='view'..XEXT
end
end
Expand All @@ -97,8 +103,7 @@ if not f then
else
mg.write(Response(200,mg.get_mime_type(fname))..'Content-Disposition: filename='..fname..'\r\n\r\n')
while true do
buf=f:read(XPREPARE or 48128)
XPREPARE=nil
buf=f:read(48128)
if buf and #buf ~= 0 then
if not mg.write(buf) then
-- キャンセルされた
Expand Down
23 changes: 12 additions & 11 deletions ini/HttpPublic/legacy/xcode.lua
@@ -1,12 +1,6 @@
-- ファイルを転送するスクリプト
-- ファイルをタイムシフト再生できる: http://localhost:5510/xcode.lua?fname=video/foo.ts

-- コマンドはEDCBのToolsフォルダにあるものを優先する
ffmpeg=edcb.GetPrivateProfile('SET', 'ModulePath', '', 'Common.ini')..'\\Tools\\ffmpeg.exe'
if not edcb.FindFile(ffmpeg, 1) then ffmpeg='ffmpeg.exe' end
readex=edcb.GetPrivateProfile('SET', 'ModulePath', '', 'Common.ini')..'\\Tools\\readex.exe'
if not edcb.FindFile(readex, 1) then readex='readex.exe' end

-- トランスコードするかどうか(する場合はreadex.exeとffmpeg.exeを用意すること)
XCODE=false
-- フィルタオプション
Expand All @@ -20,8 +14,16 @@ XOPT='-vcodec libvpx -b:v 896k -quality realtime -cpu-used 1 $FILTER -s 512x288
-- 変換後の拡張子
XEXT='.webm'
--XEXT='.mp4'
-- 出力バッファの量(bytes。asyncbuf.exeを用意すること。変換負荷や通信のむらを吸収する)
XBUF=0
-- 転送開始前に変換しておく量(bytes)
XPREPARE=nil
XPREPARE=0

-- コマンドはEDCBのToolsフォルダにあるものを優先する
tools=edcb.GetPrivateProfile('SET','ModulePath','','Common.ini')..'\\Tools\\'
ffmpeg=(edcb.FindFile(tools..'ffmpeg.exe',1) and tools or '')..'ffmpeg.exe'
readex=(edcb.FindFile(tools..'readex.exe',1) and tools or '')..'readex.exe'
asyncbuf=(edcb.FindFile(tools..'asyncbuf.exe',1) and tools or '')..'asyncbuf.exe'

dofile(mg.script_name:gsub('[^\\/]*$','')..'util.lua')

Expand Down Expand Up @@ -54,12 +56,12 @@ if fpath then
-- 容量確保の可能性があるときは周期188+同期語0x47(188*256+0x47=48199)で対象ファイルを終端判定する
sync=edcb.GetPrivateProfile('SET','KeepDisk',0,'EpgTimerSrv.ini')~='0'
f=edcb.io.popen('""'..readex..'" '..offset..(sync and ' 4p48199' or ' 4')..' "'..fpath..'" | "'
..ffmpeg..'"'..dual..' -i pipe:0 -map 0:v:0 -map 0:a:'..audio2..' '..XOPT:gsub('$FILTER',filter)..'"', 'rb')
..ffmpeg..'"'..dual..' -i pipe:0 -map 0:v:0 -map 0:a:'..audio2..' '..XOPT:gsub('$FILTER',filter)
..(XBUF>0 and ' | "'..asyncbuf..'" '..XBUF..' '..XPREPARE or '')..'"', 'rb')
fname='xcode'..XEXT
else
-- 容量確保には未対応
f:seek('set', offset)
XPREPARE=nil
end
end
end
Expand All @@ -73,8 +75,7 @@ else
mg.write(Response(200,mg.get_mime_type(fname))..'Content-Disposition: filename='..fname..'\r\n\r\n')
retry=0
while true do
buf=f:read(XPREPARE or 48128)
XPREPARE=nil
buf=f:read(48128)
if buf and #buf ~= 0 then
retry=0
if not mg.write(buf) then
Expand Down
142 changes: 142 additions & 0 deletions ini/Tools/asyncbuf.c
@@ -0,0 +1,142 @@
/* asyncbuf.c: 標準入力をバッファして標準出力する (2020-08-23)
* WTFPL2 ( http://en.wikipedia.org/wiki/WTFPL#Version_2 )
*/
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <process.h>

static const size_t BUF_UNIT_SIZE = 65536;
static HANDLE g_evenq;
static HANDLE g_evdeq;
static CRITICAL_SECTION g_cs;
static HANDLE g_th;
static char *g_buf;
static size_t g_size;
static size_t g_fill;
static size_t g_front;
static size_t g_rear;
static int g_closing;

static UINT WINAPI worker(void *p)
{
(void)p;
for (;;) {
size_t remain;
EnterCriticalSection(&g_cs);
remain = (g_size + g_rear - g_front) % g_size;
if ((g_closing || remain >= g_fill) && remain >= (g_closing ? 1 : BUF_UNIT_SIZE)) {
size_t n = remain < BUF_UNIT_SIZE ? remain : BUF_UNIT_SIZE;
LeaveCriticalSection(&g_cs);
g_fill = 0;
if (n > g_size - g_front) {
n = g_size - g_front;
}
if (fwrite(g_buf + g_front, 1, n, stdout) != n) {
EnterCriticalSection(&g_cs);
g_closing = 1;
LeaveCriticalSection(&g_cs);
SetEvent(g_evdeq);
break;
}
EnterCriticalSection(&g_cs);
g_front = (g_front + n) % g_size;
LeaveCriticalSection(&g_cs);
SetEvent(g_evdeq);
} else if (g_closing) {
LeaveCriticalSection(&g_cs);
break;
} else {
LeaveCriticalSection(&g_cs);
WaitForSingleObject(g_evenq, INFINITE);
}
}
fflush(stdout);
return 0;
}

int wmain(int argc, wchar_t **argv)
{
if (argc != 3) {
fputs("Usage: asyncbuf buf_size_bytes initial_fill_bytes\n", stderr);
return 2;
}
if (_setmode(_fileno(stdin), _O_BINARY) < 0 || _setmode(_fileno(stdout), _O_BINARY) < 0) {
return 1;
}
g_size = wcstoul(argv[1], NULL, 10);
if (g_size < BUF_UNIT_SIZE * 2) {
g_size = BUF_UNIT_SIZE * 2;
} else if (g_size > 1024 * 1024 * 1024) {
g_size = 1024 * 1024 * 1024;
}
g_fill = wcstoul(argv[2], NULL, 10);
if (g_fill > g_size - BUF_UNIT_SIZE * 2) {
g_fill = g_size - BUF_UNIT_SIZE * 2;
}
g_buf = (char *)malloc(g_size);
if (!g_buf) {
return 1;
}
g_evenq = CreateEvent(NULL, FALSE, FALSE, NULL);
if (!g_evenq) {
free(g_buf);
return 1;
}
g_evdeq = CreateEvent(NULL, FALSE, FALSE, NULL);
if (!g_evdeq) {
CloseHandle(g_evenq);
free(g_buf);
return 1;
}
InitializeCriticalSection(&g_cs);
g_th = (HANDLE)_beginthreadex(NULL, 0, worker, NULL, 0, NULL);
if (!g_th) {
DeleteCriticalSection(&g_cs);
CloseHandle(g_evdeq);
CloseHandle(g_evenq);
free(g_buf);
return 1;
}

for (;;) {
EnterCriticalSection(&g_cs);
if ((g_size + g_front - g_rear - 1) % g_size >= BUF_UNIT_SIZE) {
size_t n = BUF_UNIT_SIZE;
LeaveCriticalSection(&g_cs);
if (n > g_size - g_rear) {
n = g_size - g_rear;
}
n = fread(g_buf + g_rear, 1, n, stdin);
if (n == 0) {
EnterCriticalSection(&g_cs);
g_closing = 1;
LeaveCriticalSection(&g_cs);
SetEvent(g_evenq);
break;
}
EnterCriticalSection(&g_cs);
g_rear = (g_rear + n) % g_size;
LeaveCriticalSection(&g_cs);
SetEvent(g_evenq);
} else if (g_closing) {
LeaveCriticalSection(&g_cs);
break;
} else {
LeaveCriticalSection(&g_cs);
WaitForSingleObject(g_evdeq, INFINITE);
}
}

WaitForSingleObject(g_th, INFINITE);
CloseHandle(g_th);
DeleteCriticalSection(&g_cs);
CloseHandle(g_evdeq);
CloseHandle(g_evenq);
free(g_buf);
return 0;
}

0 comments on commit a375241

Please sign in to comment.