add null output for debugging
This commit is contained in:
parent
92507add43
commit
35790b6fbe
123
ffplayout/output/null.py
Normal file
123
ffplayout/output/null.py
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
# This file is part of ffplayout.
|
||||||
|
#
|
||||||
|
# ffplayout is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# ffplayout is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with ffplayout. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
"""
|
||||||
|
This module streams to -f null, so it is only for debugging.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from platform import system
|
||||||
|
from subprocess import PIPE, Popen
|
||||||
|
from threading import Thread
|
||||||
|
|
||||||
|
from ..folder import GetSourceFromFolder, MediaStore, MediaWatcher
|
||||||
|
from ..playlist import GetSourceFromPlaylist
|
||||||
|
from ..utils import (ff_proc, ffmpeg_stderr_reader, log, messenger, playlist,
|
||||||
|
playout, pre, pre_audio_codec, stdin_args,
|
||||||
|
terminate_processes)
|
||||||
|
|
||||||
|
COPY_BUFSIZE = 1024 * 1024 if system() == 'Windows' else 65424
|
||||||
|
|
||||||
|
|
||||||
|
def output():
|
||||||
|
"""
|
||||||
|
this output is for streaming to a target address,
|
||||||
|
like rtmp, rtp, svt, etc.
|
||||||
|
"""
|
||||||
|
|
||||||
|
ff_pre_settings = [
|
||||||
|
'-pix_fmt', 'yuv420p', '-r', str(pre.fps),
|
||||||
|
'-c:v', 'mpeg2video', '-intra',
|
||||||
|
'-b:v', f'{pre.v_bitrate}k',
|
||||||
|
'-minrate', f'{pre.v_bitrate}k',
|
||||||
|
'-maxrate', f'{pre.v_bitrate}k',
|
||||||
|
'-bufsize', f'{pre.v_bufsize}k'
|
||||||
|
] + pre_audio_codec() + ['-f', 'mpegts', '-']
|
||||||
|
|
||||||
|
try:
|
||||||
|
enc_cmd = [
|
||||||
|
'ffmpeg', '-v', f'level+{log.ff_level.lower()}', '-hide_banner',
|
||||||
|
'-nostats', '-re', '-thread_queue_size', '160', '-i', 'pipe:0'
|
||||||
|
] + playout.ffmpeg_param + ['-f', 'null', '-']
|
||||||
|
|
||||||
|
messenger.debug(f'Encoder CMD: "{" ".join(enc_cmd)}"')
|
||||||
|
|
||||||
|
ff_proc.encoder = Popen(enc_cmd, stdin=PIPE, stderr=PIPE)
|
||||||
|
|
||||||
|
enc_err_thread = Thread(target=ffmpeg_stderr_reader,
|
||||||
|
args=(ff_proc.encoder.stderr, False))
|
||||||
|
enc_err_thread.daemon = True
|
||||||
|
enc_err_thread.start()
|
||||||
|
|
||||||
|
if playlist.mode and not stdin_args.folder:
|
||||||
|
watcher = None
|
||||||
|
get_source = GetSourceFromPlaylist()
|
||||||
|
else:
|
||||||
|
messenger.info('Start folder mode')
|
||||||
|
media = MediaStore()
|
||||||
|
watcher = MediaWatcher(media)
|
||||||
|
get_source = GetSourceFromFolder(media)
|
||||||
|
|
||||||
|
try:
|
||||||
|
for node in get_source.next():
|
||||||
|
if watcher is not None:
|
||||||
|
watcher.current_clip = node.get('source')
|
||||||
|
|
||||||
|
messenger.info(
|
||||||
|
f'Play for {node["out"] - node["seek"]:.2f} '
|
||||||
|
f'seconds: {node.get("source")}')
|
||||||
|
|
||||||
|
dec_cmd = [
|
||||||
|
'ffmpeg', '-v', f'level+{log.ff_level.lower()}',
|
||||||
|
'-hide_banner', '-nostats'
|
||||||
|
] + node['src_cmd'] + node['filter'] + ff_pre_settings
|
||||||
|
|
||||||
|
messenger.debug(f'Decoder CMD: "{" ".join(dec_cmd)}"')
|
||||||
|
|
||||||
|
with Popen(
|
||||||
|
dec_cmd, stdout=PIPE, stderr=PIPE) as ff_proc.decoder:
|
||||||
|
dec_err_thread = Thread(target=ffmpeg_stderr_reader,
|
||||||
|
args=(ff_proc.decoder.stderr,
|
||||||
|
True))
|
||||||
|
dec_err_thread.daemon = True
|
||||||
|
dec_err_thread.start()
|
||||||
|
|
||||||
|
while True:
|
||||||
|
buf = ff_proc.decoder.stdout.read(COPY_BUFSIZE)
|
||||||
|
if not buf:
|
||||||
|
break
|
||||||
|
ff_proc.encoder.stdin.write(buf)
|
||||||
|
|
||||||
|
except BrokenPipeError:
|
||||||
|
messenger.error('Broken Pipe!')
|
||||||
|
terminate_processes(watcher)
|
||||||
|
|
||||||
|
except SystemExit:
|
||||||
|
messenger.info('Got close command')
|
||||||
|
terminate_processes(watcher)
|
||||||
|
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
messenger.warning('Program terminated')
|
||||||
|
terminate_processes(watcher)
|
||||||
|
|
||||||
|
# close encoder when nothing is to do anymore
|
||||||
|
if ff_proc.encoder.poll() is None:
|
||||||
|
ff_proc.encoder.kill()
|
||||||
|
|
||||||
|
finally:
|
||||||
|
if ff_proc.encoder.poll() is None:
|
||||||
|
ff_proc.encoder.kill()
|
||||||
|
ff_proc.encoder.wait()
|
Loading…
x
Reference in New Issue
Block a user