Compare commits

..

No commits in common. "master" and "0.6.0" have entirely different histories.

20 changed files with 1336 additions and 2618 deletions

152
ChangeLog
View File

@ -1,155 +1,3 @@
User johns
Date:
Preparations for new ffmpeg VDPAU API.
Added VDPAU multi decoder loop changes to VA-API code.
Reenabled VA-API auto detection.
Check and enforce USE_PIP is defined, for new code.
Fix comment spelling.
Disabled old code before removement.
Handle change of audio ac3 downmix direct.
Speedup queuing output surface, when decoder buffers are full.
Fix bug: info shows wrong decoded video surfaces.
Calculate queued output surfaces and show them in info message.
Add support for new API of vdr 2.3.1.
Fix bug: EnableDPMSatBlackScreen only available with USE_SCREENSAVER.
- H264_EOS_TRICKSPEED and USE_MPEG_COMPLETE enabled as default.
User master_red
Date: Mon Aug 10 15:29:33 CEST 2015
Configurable enable DPMS, while black screen is displayed.
User johns
Date: Tue Jun 30 10:12:09 CET 2015
Fix bug: wrong and crash, if vdr draws pixmaps outside OSD.
Fix bug: wrong version number check for av_frame_alloc(), ...
Workaround for ffmpeg 2.6 artifacts.
Fix bug: brightness and .. are calculated wrong.
Add automatic frame rate detection for older ffmpeg versions.
Fix bug: destroyed vdpau surfaces still used in queue.
Fix bug: need signed char, if compiler has unsigned chars.
Try smaller audio puffer, if default size fails.
Fix bug: center cut-out didn't use cut off pixels.
Fix bug #2058: support for Make.plgcfg.
Fix for compile with vdr 2.1.10, for older vdr versions.
User jinx
Date: Mon Feb 16 09:58:06 CET 2015
Enable toggle AC3 downmix.
User johns
Date: Thu Feb 12 10:30:50 CET 2015
Compile with vdr 2.1.10.
Fix bug: AVCodecContext.framerate not supported.
Use video stream frame rate for A/V sync.
User Antti Seppälä
Date: Thu Oct 16 14:15:15 CEST 2014
Corrected black surface for va-api.
User johns
Date: Thu Oct 16 14:05:17 CEST 2014
Newer va-api intel drivers support PutImage.
Use more portable fork for vfork.
Fix crash with VA-API vdpau backend.
User mini73
Date: Sat Oct 11 16:53:18 CEST 2014
Fix bug: random rubbish at the end of letter.
User johns
Date: Tue Sep 23 12:36:39 CEST 2014
Fix audio thread close race condition.
Support ffmpeg new AVFrame API in the audio codec.
Config for automatic AES parameters.
Use GCC built-in functions for atomic operations.
User master_red
Date: Wed Jun 4 14:44:32 CEST 2014
Support detach or suspend in plugin menu.
User johns
Date: Fri May 30 10:18:20 CEST 2014
Fix "make clean-plugins".
Fix compile with newer libav.
Fix OSD bugs.
Add some VA-API VPP info outputs.
Remove build files for old unstable VDR.
User hd.brummy
Date: Thu Jan 30 10:40:49 CET 2014
Update gentoo ebuild.
User johns
Date: Thu Jan 30 10:36:53 CET 2014
Fix spelling in arguments help.
Add Workaround for alsa blocking audio device.
Improves thread handling for audio flush and close.
User mini73
Date: Fri Jan 24 11:30:49 CET 2014
Fix bug: learing x11 remote keys fails.
Add support for umlauts in input fields.
User johns
Date: Tue Jan 14 14:59:44 CET 2014
Fix alternative OSD support with VDPAU bitmap surfaces.
Fix compile error with VDR 2.1.3.
Fix bug: memory leak.
PIP close clears the last used PIP channel.
Fix bug: -DOSD_DEBUG uses old (deleted) variable.
Fix bug: Option softhddevice.BlackPicture has no effect.
User Dr. Seltsam
Date: Tue Nov 5 16:46:34 CET 2013
Add support to configure and clear buffers on channel switch.
User johns
Date: Tue Oct 8 10:18:04 CET 2013
CLOCK_REALTIME -> CLOCK_MONOTONIC to allow time changes.
Add function VideoStreamOpen and always use VideoStreamClose.
Softer audio/video sync.
Add function GetStats to the video output module.
Add function ResetStart to the video output module.
Add function SetClosing to the video output module.
Generalize GetVaapiContext to GetHwAccelContext.
Add compile time configurable trickspeed packets dump.
Fix bug #1410: wrong spelled AC-3 and E-AC-3.
Add compile time selectable h264 trickspeed workaround.
Use ffmpeg new names AVCodecID, AV_CODEC_... .
Fix bug: video lagging behind after recording stop.
Reduce PES error messages.
Fix bug #1392: Wrong value for mixing LFE.
Fix bug: wrong grab size, introduced with AMD VDPAU.
Use VDR SPU decoder as default.
Fix bug: grab image negative quality isn't the default 100.
Support AMD VDPAU with surface size != requested size.
Add cache for auto-crop buffer.
Fix opengl and opengl threads bugs.
Initial opengl support with va-api only.
Fix "broken driver" message if empty ring buffer.
Enable seamless audio track change.
Fix bug #1302: Unsupported pixel format crash.
Fix the fix, when sillpicture is called in suspend mode.
Fix crash, when sillpicture is called in suspend mode.
Add workaround for zero width+height and ffmpeg >= 1.2.
User johns User johns
Date: Sun Mar 17 15:52:42 CET 2013 Date: Sun Mar 17 15:52:42 CET 2013

122
Makefile
View File

@ -15,20 +15,14 @@ PLUGIN = softhddevice
ALSA ?= $(shell pkg-config --exists alsa && echo 1) ALSA ?= $(shell pkg-config --exists alsa && echo 1)
# support OSS audio output module # support OSS audio output module
OSS ?= 1 OSS ?= 1
# support VDPAU video output module # support VDPAU video output modue
VDPAU ?= $(shell pkg-config --exists vdpau && echo 1) VDPAU ?= $(shell pkg-config --exists vdpau && echo 1)
# support VA-API video output module (deprecated) # support VA-API video output modue
VAAPI ?= $(shell pkg-config --exists libva && echo 1) VAAPI ?= $(shell pkg-config --exists libva && echo 1)
# support glx output
OPENGL ?= $(shell pkg-config --exists gl glu && echo 1)
# screensaver disable/enable # screensaver disable/enable
SCREENSAVER ?= 1 SCREENSAVER ?= 1
# use ffmpeg libswresample # use ffmpeg libswresample
SWRESAMPLE ?= $(shell pkg-config --exists libswresample && echo 1) SWRESAMPLE ?= $(shell pkg-config --exists libswresample && echo 1)
# use libav libavresample
ifneq ($(SWRESAMPLE),1)
AVRESAMPLE ?= $(shell pkg-config --exists libavresample && echo 1)
endif
CONFIG := # -DDEBUG #-DOSD_DEBUG # enable debug output+functions CONFIG := # -DDEBUG #-DOSD_DEBUG # enable debug output+functions
#CONFIG += -DSTILL_DEBUG=2 # still picture debug verbose level #CONFIG += -DSTILL_DEBUG=2 # still picture debug verbose level
@ -38,58 +32,8 @@ CONFIG += -DUSE_PIP # PIP support
#CONFIG += -DHAVE_PTHREAD_NAME # supports new pthread_setname_np #CONFIG += -DHAVE_PTHREAD_NAME # supports new pthread_setname_np
#CONFIG += -DNO_TS_AUDIO # disable ts audio parser #CONFIG += -DNO_TS_AUDIO # disable ts audio parser
#CONFIG += -DUSE_TS_VIDEO # build new ts video parser #CONFIG += -DUSE_TS_VIDEO # build new ts video parser
CONFIG += -DUSE_MPEG_COMPLETE # support only complete mpeg packets #CONFIG += -DUSE_MPEG_COMPLETE # support only complete mpeg packets
CONFIG += -DH264_EOS_TRICKSPEED # insert seq end packets for trickspeed #CONFIG += -DUSE_VDR_SPU # use VDR SPU decoder.
#CONDIF += -DDUMP_TRICKSPEED # dump trickspeed packets
#CONFIG += -DUSE_BITMAP # VDPAU, use bitmap surface for OSD
CONFIG += -DUSE_VDR_SPU # use VDR SPU decoder.
#CONFIG += -DUSE_SOFTLIMIT # (tobe removed) limit the buffer fill
### The version number of this plugin (taken from the main source file):
VERSION = $(shell grep 'static const char \*const VERSION *=' $(PLUGIN).cpp | awk '{ print $$7 }' | sed -e 's/[";]//g')
GIT_REV = $(shell git describe --always 2>/dev/null)
### The directory environment:
# Use package data if installed...otherwise assume we're under the VDR source directory:
PKGCFG = $(if $(VDRDIR),$(shell pkg-config --variable=$(1) $(VDRDIR)/vdr.pc),$(shell PKG_CONFIG_PATH="$$PKG_CONFIG_PATH:../../.." pkg-config --variable=$(1) vdr))
LIBDIR = $(call PKGCFG,libdir)
LOCDIR = $(call PKGCFG,locdir)
PLGCFG = $(call PKGCFG,plgcfg)
#
TMPDIR ?= /tmp
### The compiler options:
export CFLAGS = $(call PKGCFG,cflags)
export CXXFLAGS = $(call PKGCFG,cxxflags)
ifeq ($(CFLAGS),)
$(warning CFLAGS not set)
endif
ifeq ($(CXXFLAGS),)
$(warning CXXFLAGS not set)
endif
### The version number of VDR's plugin API:
APIVERSION = $(call PKGCFG,apiversion)
### Allow user defined options to overwrite defaults:
-include $(PLGCFG)
### The name of the distribution archive:
ARCHIVE = $(PLUGIN)-$(VERSION)
PACKAGE = vdr-$(ARCHIVE)
### The name of the shared object file:
SOFILE = libvdr-$(PLUGIN).so
### Parse softhddevice config
ifeq ($(ALSA),1) ifeq ($(ALSA),1)
CONFIG += -DUSE_ALSA CONFIG += -DUSE_ALSA
@ -108,15 +52,6 @@ ifeq ($(VAAPI),1)
CONFIG += -DUSE_VAAPI CONFIG += -DUSE_VAAPI
_CFLAGS += $(shell pkg-config --cflags libva-x11 libva) _CFLAGS += $(shell pkg-config --cflags libva-x11 libva)
LIBS += $(shell pkg-config --libs libva-x11 libva) LIBS += $(shell pkg-config --libs libva-x11 libva)
ifeq ($(OPENGL),1)
_CFLAGS += $(shell pkg-config --cflags libva-glx)
LIBS += $(shell pkg-config --libs libva-glx)
endif
endif
ifeq ($(OPENGL),1)
CONFIG += -DUSE_GLX
_CFLAGS += $(shell pkg-config --cflags gl glu)
LIBS += $(shell pkg-config --libs gl glu)
endif endif
ifeq ($(SCREENSAVER),1) ifeq ($(SCREENSAVER),1)
CONFIG += -DUSE_SCREENSAVER CONFIG += -DUSE_SCREENSAVER
@ -128,15 +63,54 @@ CONFIG += -DUSE_SWRESAMPLE
_CFLAGS += $(shell pkg-config --cflags libswresample) _CFLAGS += $(shell pkg-config --cflags libswresample)
LIBS += $(shell pkg-config --libs libswresample) LIBS += $(shell pkg-config --libs libswresample)
endif endif
ifeq ($(AVRESAMPLE),1)
CONFIG += -DUSE_AVRESAMPLE
_CFLAGS += $(shell pkg-config --cflags libavresample)
LIBS += $(shell pkg-config --libs libavresample)
endif
_CFLAGS += $(shell pkg-config --cflags libavcodec x11 x11-xcb xcb xcb-icccm) _CFLAGS += $(shell pkg-config --cflags libavcodec x11 x11-xcb xcb xcb-icccm)
LIBS += -lrt $(shell pkg-config --libs libavcodec x11 x11-xcb xcb xcb-icccm) LIBS += -lrt $(shell pkg-config --libs libavcodec x11 x11-xcb xcb xcb-icccm)
### The version number of this plugin (taken from the main source file):
VERSION = $(shell grep 'static const char \*const VERSION *=' $(PLUGIN).cpp | awk '{ print $$7 }' | sed -e 's/[";]//g')
GIT_REV = $(shell git describe --always 2>/dev/null)
### The directory environment:
# Use package data if installed...otherwise assume we're under the VDR source directory:
PKGCFG = $(if $(VDRDIR),$(shell pkg-config --variable=$(1) $(VDRDIR)/vdr.pc),$(shell pkg-config --variable=$(1) vdr || pkg-config --variable=$(1) ../../../vdr.pc))
LIBDIR = $(call PKGCFG,libdir)
LOCDIR = $(call PKGCFG,locdir)
PLGCFG = $(call PKGCFG,plgcfg)
#
TMPDIR ?= /tmp
### The compiler options:
export CFLAGS = $(call PKGCFG,cflags)
export CXXFLAGS = $(call PKGCFG,cxxflags)
ifeq ($(CFLAGS),)
$(error CFLAGS not set)
endif
ifeq ($(CXXFLAGS),)
$(error CXXFLAGS not set)
endif
### The version number of VDR's plugin API:
APIVERSION = $(call PKGCFG,apiversion)
### Allow user defined options to overwrite defaults:
-include $(PLGCFG)
### The name of the distribution archive:
ARCHIVE = $(PLUGIN)-$(VERSION)
PACKAGE = vdr-$(ARCHIVE)
### The name of the shared object file:
SOFILE = libvdr-$(PLUGIN).so
### Includes and Defines (add further entries here): ### Includes and Defines (add further entries here):
INCLUDES += INCLUDES +=

188
Makefile-pre1.7.36 Normal file
View File

@ -0,0 +1,188 @@
#
# Makefile for a Video Disk Recorder plugin
#
# $Id$
# The official name of this plugin.
# This name will be used in the '-P...' option of VDR to load the plugin.
# By default the main source file also carries this name.
# IMPORTANT: the presence of this macro is important for the Make.config
# file. So it must be defined, even if it is not used here!
#
PLUGIN = softhddevice
### The version number of this plugin (taken from the main source file):
VERSION = $(shell grep 'static const char \*const VERSION *=' $(PLUGIN).cpp | awk '{ print $$7 }' | sed -e 's/[";]//g')
GIT_REV = $(shell git describe --always 2>/dev/null)
### Configuration (edit this for your needs)
CONFIG := #-DDEBUG #-DOSD_DEBUG
CONFIG += -DAV_INFO -DAV_INFO_TIME=3000 # debug a/v sync
CONFIG += -DUSE_PIP # PIP support
#CONFIG += -DHAVE_PTHREAD_NAME # supports new pthread_setname_np
#CONFIG += -DNO_TS_AUDIO # disable ts audio parser
#CONFIG += -DUSE_TS_VIDEO # build new ts video parser
# use ffmpeg libswresample
CONFIG += $(shell pkg-config --exists libswresample && echo "-DUSE_SWRESAMPLE")
CONFIG += -DUSE_SCREENSAVER # use functions to disable screensaver
CONFIG += $(shell pkg-config --exists vdpau && echo "-DUSE_VDPAU")
CONFIG += $(shell pkg-config --exists libva && echo "-DUSE_VAAPI")
CONFIG += $(shell pkg-config --exists alsa && echo "-DUSE_ALSA")
CONFIG += -DUSE_OSS
### The C++ compiler and options:
CC ?= gcc
CXX ?= g++
CFLAGS ?= -g -O2 -W -Wall -Wextra -Winit-self \
-Wdeclaration-after-statement \
-ftree-vectorize -msse3 -flax-vector-conversions -fPIC
CXXFLAGS ?= -g -O2 -W -Wall -Wextra -Werror=overloaded-virtual -fPIC
### The directory environment:
VDRDIR ?= ../../..
LIBDIR ?= ../../lib
TMPDIR ?= /tmp
### Make sure that necessary options are included:
-include $(VDRDIR)/Make.global
### Allow user defined options to overwrite defaults:
-include $(VDRDIR)/Make.config
### The version number of VDR's plugin API (taken from VDR's "config.h"):
APIVERSION = $(shell sed -ne '/define APIVERSION/s/^.*"\(.*\)".*$$/\1/p' $(VDRDIR)/config.h)
### The name of the distribution archive:
ARCHIVE = $(PLUGIN)-$(VERSION)
PACKAGE = vdr-$(ARCHIVE)
### Includes, Defines and dependencies (add further entries here):
INCLUDES += -I$(VDRDIR)/include
DEFINES += $(CONFIG) -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"' \
$(if $(GIT_REV), -DGIT_REV='"$(GIT_REV)"')
_CFLAGS = $(DEFINES) $(INCLUDES) \
$(shell pkg-config --cflags libavcodec) \
`pkg-config --cflags x11 x11-xcb xcb xcb-xv xcb-shm xcb-dpms xcb-atom\
xcb-screensaver xcb-randr xcb-glx xcb-icccm xcb-keysyms`\
`pkg-config --cflags gl glu` \
$(if $(findstring USE_SWRESAMPLE,$(CONFIG)), \
$(shell pkg-config --cflags libswresample)) \
$(if $(findstring USE_VAAPI,$(CONFIG)), \
`pkg-config --cflags libva-x11 libva-glx libva`) \
$(if $(findstring USE_ALSA,$(CONFIG)), \
`pkg-config --cflags alsa`)
#override _CFLAGS += -Werror
override CXXFLAGS += $(_CFLAGS)
override CFLAGS += $(_CFLAGS)
LIBS += -lrt \
$(shell pkg-config --libs libavcodec) \
`pkg-config --libs x11 x11-xcb xcb xcb-xv xcb-shm xcb-dpms xcb-atom\
xcb-screensaver xcb-randr xcb-glx xcb-icccm xcb-keysyms`\
`pkg-config --libs gl glu` \
$(if $(findstring USE_SWRESAMPLE,$(CONFIG)), \
$(shell pkg-config --libs libswresample)) \
$(if $(findstring USE_VDPAU,$(CONFIG)), \
`pkg-config --libs vdpau`) \
$(if $(findstring USE_VAAPI,$(CONFIG)), \
`pkg-config --libs libva-x11 libva-glx libva`) \
$(if $(findstring USE_ALSA,$(CONFIG)), \
`pkg-config --libs alsa`)
### The object files (add further files here):
OBJS = $(PLUGIN).o softhddev.o video.o audio.o codec.o ringbuffer.o
SRCS = $(wildcard $(OBJS:.o=.c)) $(PLUGIN).cpp
### The main target:
all: libvdr-$(PLUGIN).so i18n
### Implicit rules:
#
#%.o: %.cpp
# $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $<
### Dependencies:
MAKEDEP = $(CC) -MM -MG
DEPFILE = .dependencies
$(DEPFILE): Makefile
@$(MAKEDEP) $(DEFINES) $(INCLUDES) $(SRCS) >$@
$(OBJS): Makefile
-include $(DEPFILE)
### Internationalization (I18N):
PODIR = po
LOCALEDIR = $(VDRDIR)/locale
I18Npo = $(wildcard $(PODIR)/*.po)
I18Nmsgs = $(addprefix $(LOCALEDIR)/, $(addsuffix /LC_MESSAGES/vdr-$(PLUGIN).mo, $(notdir $(foreach file, $(I18Npo), $(basename $(file))))))
I18Npot = $(PODIR)/$(PLUGIN).pot
%.mo: %.po
msgfmt -c -o $@ $<
$(I18Npot): $(wildcard *.cpp) $(wildcard *.c)
xgettext -C -cTRANSLATORS --no-wrap --no-location -k -ktr -ktrNOOP \
-k_ -k_N --package-name=VDR --package-version=$(VDRVERSION) \
--msgid-bugs-address='<see README>' -o $@ $^
%.po: $(I18Npot)
msgmerge -U --no-wrap --no-location --backup=none -q $@ $<
@touch $@
$(I18Nmsgs): $(LOCALEDIR)/%/LC_MESSAGES/vdr-$(PLUGIN).mo: $(PODIR)/%.mo
@mkdir -p $(dir $@)
cp $< $@
.PHONY: i18n
i18n: $(I18Nmsgs) $(I18Npot)
### Targets:
libvdr-$(PLUGIN).so: $(OBJS) Makefile
$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared -fPIC $(OBJS) -o $@ $(LIBS)
@cp --remove-destination $@ $(LIBDIR)/$@.$(APIVERSION)
dist: $(I18Npo) clean
@-rm -rf $(TMPDIR)/$(ARCHIVE)
@mkdir $(TMPDIR)/$(ARCHIVE)
@cp -a * $(TMPDIR)/$(ARCHIVE)
@tar czf $(PACKAGE).tgz -C $(TMPDIR) $(ARCHIVE)
@-rm -rf $(TMPDIR)/$(ARCHIVE)
@echo Distribution package created as $(PACKAGE).tgz
clean:
@-rm -f $(OBJS) $(DEPFILE) *.so *.tgz core* *~ $(PODIR)/*.mo $(PODIR)/*.pot
install: libvdr-$(PLUGIN).so
cp --remove-destination libvdr-$(PLUGIN).so \
/usr/lib/vdr/plugins/libvdr-$(PLUGIN).so.$(APIVERSION)
HDRS= $(wildcard *.h)
indent:
for i in $(SRCS) $(HDRS); do \
indent $$i; \
unexpand -a $$i | sed -e s/constconst/const/ > $$i.up; \
mv $$i.up $$i; \
done
video_test: video.c Makefile
$(CC) -DVIDEO_TEST -DVERSION='"$(VERSION)"' $(CFLAGS) $(LDFLAGS) $< $(LIBS) \
-o $@

View File

@ -20,14 +20,14 @@ $Id$
A software and GPU emulated HD output device plugin for VDR. A software and GPU emulated HD output device plugin for VDR.
o Video decoder CPU / VDPAU o Video decoder CPU / VA-API / VDPAU
o Video output VDPAU o Video output VA-API / VDPAU
o Audio FFMpeg / Alsa / Analog o Audio FFMpeg / Alsa / Analog
o Audio FFMpeg / Alsa / Digital o Audio FFMpeg / Alsa / Digital
o Audio FFMpeg / OSS / Analog o Audio FFMpeg / OSS / Analog
o HDMI/SPDIF pass-through o HDMI/SPDIF pass-through
o Software volume, compression, normalize and channel resample o Software volume, compression, normalize and channel resample
o VDR ScaleVideo API o YaepgHD support / new >1.7.33 VDR ScaleVideo API support
o Software deinterlacer Bob (VA-API only) o Software deinterlacer Bob (VA-API only)
o Autocrop o Autocrop
o Grab image (VDPAU only) o Grab image (VDPAU only)
@ -36,11 +36,10 @@ A software and GPU emulated HD output device plugin for VDR.
o atmo light support with plugin http://github.com/durchflieger/DFAtmo o atmo light support with plugin http://github.com/durchflieger/DFAtmo
o PIP (Picture-in-Picture) (VDPAU only) o PIP (Picture-in-Picture) (VDPAU only)
o planned: Remove VA-API decoder and output support o planned: Video decoder VA-API Branch: vaapi-ext/staging
o planned: Video decoder OpenMax o planned: Video output XvBA / Opengl / Xv
o planned: Video output Opengl / Xv o planned: VA-API grab image
o planned: Improved software deinterlacer (yadif or/and ffmpeg filters) o planned: Improved Software Deinterlacer (yadif or/and ffmpeg filters)
o XvBa support is no longer planned (use future Radeon UVD VDPAU)
To compile you must have the 'requires' installed. To compile you must have the 'requires' installed.
@ -84,12 +83,14 @@ Setup: environment
if set don't use the hardware decoders if set don't use the hardware decoders
NO_MPEG_HW=1 NO_MPEG_HW=1
if set don't use the hardware decoder for mpeg1/2 if set don't use the hardware decoder for mpeg1/2
STUDIO_LEVELS=1
if set use studio levels with vdpau (deprecated use setup)
only if alsa is configured only if alsa is configured
ALSA_DEVICE=default ALSA_DEVICE=default
alsa PCM device name alsa PCM device name
ALSA_PASSTHROUGH_DEVICE= ALSA_PASSTHROUGH_DEVICE=
alsa pass-though (AC-3,E-AC-3,DTS,...) device name alsa pass-though (AC3,EAC3,DTS,...) device name
ALSA_MIXER=default ALSA_MIXER=default
alsa control device name alsa control device name
ALSA_MIXER_CHANNEL=PCM ALSA_MIXER_CHANNEL=PCM
@ -99,7 +100,7 @@ Setup: environment
OSS_AUDIODEV=/dev/dsp OSS_AUDIODEV=/dev/dsp
oss dsp device name oss dsp device name
OSS_PASSTHROUGHDEV= OSS_PASSTHROUGHDEV=
oss pass-though (AC-3,E-AC-3,DTS,...) device name oss pass-though (AC3,EAC3,DTS,...) device name
OSS_MIXERDEV=/dev/mixer OSS_MIXERDEV=/dev/mixer
oss mixer device name oss mixer device name
OSS_MIXER_CHANNEL=pcm OSS_MIXER_CHANNEL=pcm
@ -129,7 +130,7 @@ Setup: /etc/vdr/setup.conf
softhddevice.<res>.Deinterlace = 0 softhddevice.<res>.Deinterlace = 0
0 = bob, 1 = weave, 2 = temporal, 3 = temporal_spatial, 4 = software 0 = bob, 1 = weave, 2 = temporal, 3 = temporal_spatial, 4 = software
(only 0, 1, 4 supported with VA-API) (only 0, 1 supported with vaapi)
softhddevice.<res>.SkipChromaDeinterlace = 0 softhddevice.<res>.SkipChromaDeinterlace = 0
0 = disabled, 1 = enabled (for slower cards, poor qualität) 0 = disabled, 1 = enabled (for slower cards, poor qualität)
@ -233,10 +234,6 @@ Setup: /etc/vdr/setup.conf
0 disable black picture during channel switch 0 disable black picture during channel switch
1 enable black picture during channel switch 1 enable black picture during channel switch
softhddevice.ClearOnSwitch = 0
0 keep video und audio buffers during channel switch
1 clear video and audio buffers on channel switch
softhddevice.Video4to3DisplayFormat = 1 softhddevice.Video4to3DisplayFormat = 1
0 pan and scan 0 pan and scan
1 letter box 1 letter box
@ -321,7 +318,6 @@ Keymacros:
@softhddevice Blue 1 2 toggle pass-through @softhddevice Blue 1 2 toggle pass-through
@softhddevice Blue 1 3 decrease audio delay by 10ms @softhddevice Blue 1 3 decrease audio delay by 10ms
@softhddevice Blue 1 4 increase audio delay by 10ms @softhddevice Blue 1 4 increase audio delay by 10ms
@softhddevice Blue 1 5 toggle ac3 mixdown
@softhddevice Blue 2 0 disable fullscreen @softhddevice Blue 2 0 disable fullscreen
@softhddevice Blue 2 1 enable fullscreen @softhddevice Blue 2 1 enable fullscreen
@softhddevice Blue 2 2 toggle fullscreen @softhddevice Blue 2 2 toggle fullscreen
@ -357,7 +353,7 @@ Requires:
media-video/ffmpeg (version >=0.7) media-video/ffmpeg (version >=0.7)
Complete solution to record, convert and stream audio and Complete solution to record, convert and stream audio and
video. Includes libavcodec and libswresample. video. Includes libavcodec.
http://ffmpeg.org http://ffmpeg.org
media-libs/alsa-lib media-libs/alsa-lib
Advanced Linux Sound Architecture Library Advanced Linux Sound Architecture Library
@ -365,7 +361,7 @@ Requires:
or or
kernel support for oss/oss4 or alsa oss emulation kernel support for oss/oss4 or alsa oss emulation
x11-libs/libva (deprecated) x11-libs/libva
Video Acceleration (VA) API for Linux Video Acceleration (VA) API for Linux
http://www.freedesktop.org/wiki/Software/vaapi http://www.freedesktop.org/wiki/Software/vaapi
x11-libs/libva-intel-driver x11-libs/libva-intel-driver

10
Todo
View File

@ -1,6 +1,6 @@
@file Todo @brief A software HD output device for VDR @file Todo @brief A software HD output device for VDR
Copyright (c) 2011 - 2013 by Johns. All Rights Reserved. Copyright (c) 2011, 2012 by Johns. All Rights Reserved.
Contributor(s): Contributor(s):
@ -19,9 +19,6 @@ GNU Affero General Public License for more details.
$Id: $ $Id: $
missing: missing:
documentation of the PIP hotkeys.
svdrp help page missing PIP hotkeys.
svdrp stat: add X11 crashed status.
more software deinterlace (yadif, ...) more software deinterlace (yadif, ...)
more software decoder with software deinterlace more software decoder with software deinterlace
suspend output / energie saver: stop and restart X11 suspend output / energie saver: stop and restart X11
@ -43,15 +40,11 @@ video:
check start with 24Hz display rate check start with 24Hz display rate
crash with ffmpeg without vaapi and vdpau. crash with ffmpeg without vaapi and vdpau.
still-picture of PES recordings should use VideoMpegEnqueue. still-picture of PES recordings should use VideoMpegEnqueue.
convert PIX_FMT_... PixelFormat to new names AV_PIX_FMT_..., AVPixelFormat.
atmo service support 3D grab
no warnings during still picture
vdpau: vdpau:
software deinterlace path not working. software deinterlace path not working.
OSD looses transparency, during channel switch. OSD looses transparency, during channel switch.
OSD looses transparency, while moving cut marks. OSD looses transparency, while moving cut marks.
ffmpeg >=1.2 supports same API like VA-API.
libva: libva:
yaepghd (VaapiSetOutputPosition) support yaepghd (VaapiSetOutputPosition) support
@ -128,7 +121,6 @@ unsorted:
svdrp prim: support plugin names for device numbers. svdrp prim: support plugin names for device numbers.
Workaround exists: hangup PipVideoStream -> Vdpau_get_format -> xcb -> poll Workaround exists: hangup PipVideoStream -> Vdpau_get_format -> xcb -> poll
+ lock DecoderLockMutex + lock DecoderLockMutex
check compiletime and runtime ffmpeg/libav version during init.
future features (not planed for 1.0 - 1.5) future features (not planed for 1.0 - 1.5)

152
audio.c
View File

@ -1,7 +1,7 @@
/// ///
/// @file audio.c @brief Audio module /// @file audio.c @brief Audio module
/// ///
/// Copyright (c) 2009 - 2014 by Johns. All Rights Reserved. /// Copyright (c) 2009 - 2013 by Johns. All Rights Reserved.
/// ///
/// Contributor(s): /// Contributor(s):
/// ///
@ -88,7 +88,7 @@
#endif #endif
#endif #endif
#include "iatomic.h" // portable atomic_t #include <alsa/iatomic.h> // portable atomic_t
#include "ringbuffer.h" #include "ringbuffer.h"
#include "misc.h" #include "misc.h"
@ -123,8 +123,6 @@ static const AudioModule NoopModule; ///< forward definition of noop module
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
char AudioAlsaDriverBroken; ///< disable broken driver message char AudioAlsaDriverBroken; ///< disable broken driver message
char AudioAlsaNoCloseOpen; ///< disable alsa close/open fix
char AudioAlsaCloseOpenDelay; ///< enable alsa close/open delay fix
static const char *AudioModuleName; ///< which audio module to use static const char *AudioModuleName; ///< which audio module to use
@ -132,7 +130,6 @@ static const char *AudioModuleName; ///< which audio module to use
static const AudioModule *AudioUsedModule = &NoopModule; static const AudioModule *AudioUsedModule = &NoopModule;
static const char *AudioPCMDevice; ///< PCM device name static const char *AudioPCMDevice; ///< PCM device name
static const char *AudioPassthroughDevice; ///< Passthrough device name static const char *AudioPassthroughDevice; ///< Passthrough device name
static char AudioAppendAES; ///< flag automatic append AES
static const char *AudioMixerDevice; ///< mixer device name static const char *AudioMixerDevice; ///< mixer device name
static const char *AudioMixerChannel; ///< mixer channel name static const char *AudioMixerChannel; ///< mixer channel name
static char AudioDoingInit; ///> flag in init, reduce error static char AudioDoingInit; ///> flag in init, reduce error
@ -149,7 +146,6 @@ static int AudioBufferTime = 336; ///< audio buffer time in ms
static pthread_t AudioThread; ///< audio play thread static pthread_t AudioThread; ///< audio play thread
static pthread_mutex_t AudioMutex; ///< audio condition mutex static pthread_mutex_t AudioMutex; ///< audio condition mutex
static pthread_cond_t AudioStartCond; ///< condition variable static pthread_cond_t AudioStartCond; ///< condition variable
static char AudioThreadStop; ///< stop audio thread
#else #else
static const int AudioThread; ///< dummy audio thread static const int AudioThread; ///< dummy audio thread
#endif #endif
@ -490,7 +486,7 @@ static void AudioSurround2Stereo(const int16_t * in, int in_chan, int frames,
r += in[3] * 200; // Rs r += in[3] * 200; // Rs
l += in[4] * 300; // C l += in[4] * 300; // C
r += in[4] * 300; r += in[4] * 300;
l += in[5] * 100; // LFE l += in[5] * 300; // LFE
r += in[5] * 100; r += in[5] * 100;
break; break;
case 7: // 7.0 case 7: // 7.0
@ -624,7 +620,7 @@ static void AudioResample(const int16_t * in, int in_chan, int frames,
typedef struct _audio_ring_ring_ typedef struct _audio_ring_ring_
{ {
char FlushBuffers; ///< flag: flush buffers char FlushBuffers; ///< flag: flush buffers
char Passthrough; ///< flag: use pass-through (AC-3, ...) char Passthrough; ///< flag: use pass-through (AC3, ...)
int16_t PacketSize; ///< packet size int16_t PacketSize; ///< packet size
unsigned HwSampleRate; ///< hardware sample rate in Hz unsigned HwSampleRate; ///< hardware sample rate in Hz
unsigned HwChannels; ///< hardware number of channels unsigned HwChannels; ///< hardware number of channels
@ -646,7 +642,7 @@ static unsigned AudioStartThreshold; ///< start play, if filled
** **
** @param sample_rate sample-rate frequency ** @param sample_rate sample-rate frequency
** @param channels number of channels ** @param channels number of channels
** @param passthrough use /pass-through (AC-3, ...) device ** @param passthrough use /pass-through (AC3, ...) device
** **
** @retval -1 error ** @retval -1 error
** @retval 0 okay ** @retval 0 okay
@ -682,7 +678,8 @@ static int AudioRingAdd(unsigned sample_rate, int channels, int passthrough)
} }
AudioRingWrite = (AudioRingWrite + 1) % AUDIO_RING_MAX; AudioRingWrite = (AudioRingWrite + 1) % AUDIO_RING_MAX;
AudioRing[AudioRingWrite].FlushBuffers = 0; // FIXME: don't flush buffers here
AudioRing[AudioRingWrite].FlushBuffers = 1;
AudioRing[AudioRingWrite].Passthrough = passthrough; AudioRing[AudioRingWrite].Passthrough = passthrough;
AudioRing[AudioRingWrite].PacketSize = 0; AudioRing[AudioRingWrite].PacketSize = 0;
AudioRing[AudioRingWrite].InSampleRate = sample_rate; AudioRing[AudioRingWrite].InSampleRate = sample_rate;
@ -692,9 +689,6 @@ static int AudioRingAdd(unsigned sample_rate, int channels, int passthrough)
AudioRing[AudioRingWrite].PTS = INT64_C(0x8000000000000000); AudioRing[AudioRingWrite].PTS = INT64_C(0x8000000000000000);
RingBufferReset(AudioRing[AudioRingWrite].RingBuffer); RingBufferReset(AudioRing[AudioRingWrite].RingBuffer);
Debug(3, "audio: %d ring buffer prepared\n",
atomic_read(&AudioRingFilled) + 1);
atomic_inc(&AudioRingFilled); atomic_inc(&AudioRingFilled);
#ifdef USE_AUDIO_THREAD #ifdef USE_AUDIO_THREAD
@ -842,7 +836,7 @@ static int AlsaPlayRingbuffer(void)
if (!avail) { // full or buffer empty if (!avail) { // full or buffer empty
break; break;
} }
// muting pass-through AC-3, can produce disturbance // muting pass-through ac3, can produce disturbance
if (AudioMute || (AudioSoftVolume if (AudioMute || (AudioSoftVolume
&& !AudioRing[AudioRingRead].Passthrough)) { && !AudioRing[AudioRingRead].Passthrough)) {
// FIXME: quick&dirty cast // FIXME: quick&dirty cast
@ -943,6 +937,7 @@ static int AlsaThread(void)
return -1; return -1;
} }
for (;;) { for (;;) {
pthread_testcancel();
if (AudioPaused) { if (AudioPaused) {
return 1; return 1;
} }
@ -990,7 +985,7 @@ static int AlsaThread(void)
/** /**
** Open alsa pcm device. ** Open alsa pcm device.
** **
** @param passthrough use pass-through (AC-3, ...) device ** @param passthrough use pass-through (AC3, ...) device
*/ */
static snd_pcm_t *AlsaOpenPCM(int passthrough) static snd_pcm_t *AlsaOpenPCM(int passthrough)
{ {
@ -1008,26 +1003,6 @@ static snd_pcm_t *AlsaOpenPCM(int passthrough)
Info(_("audio/alsa: using %sdevice '%s'\n"), Info(_("audio/alsa: using %sdevice '%s'\n"),
passthrough ? "pass-through " : "", device); passthrough ? "pass-through " : "", device);
} }
//
// for AC3 pass-through try to set the non-audio bit, use AES0=6
//
if (passthrough && AudioAppendAES) {
#if 0
// FIXME: not yet finished
char *buf;
const char *s;
int n;
n = strlen(device);
buf = alloca(n + sizeof(":AES0=6") + 1);
strcpy(buf, device);
if (!(s = strchr(buf, ':'))) {
// no alsa parameters
strcpy(buf + n, ":AES=6");
}
Debug(3, "audio/alsa: try '%s'\n", buf);
#endif
}
// open none blocking; if device is already used, we don't want wait // open none blocking; if device is already used, we don't want wait
if ((err = if ((err =
snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK,
@ -1193,7 +1168,7 @@ static int64_t AlsaGetDelay(void)
** **
** @param freq sample frequency ** @param freq sample frequency
** @param channels number of channels ** @param channels number of channels
** @param passthrough use pass-through (AC-3, ...) device ** @param passthrough use pass-through (AC3, ...) device
** **
** @retval 0 everything ok ** @retval 0 everything ok
** @retval 1 didn't support frequency/channels combination ** @retval 1 didn't support frequency/channels combination
@ -1212,23 +1187,17 @@ static int AlsaSetup(int *freq, int *channels, int passthrough)
// FIXME: if open fails for fe. pass-through, we never recover // FIXME: if open fails for fe. pass-through, we never recover
return -1; return -1;
} }
if (!AudioAlsaNoCloseOpen) { // close+open to fix HDMI no sound bug if (1) { // close+open to fix HDMI no sound bug
snd_pcm_t *handle; snd_pcm_t *handle;
handle = AlsaPCMHandle; handle = AlsaPCMHandle;
// no lock needed, thread exit in main loop only // FIXME: need lock
//Debug(3, "audio: %s [\n", __FUNCTION__);
AlsaPCMHandle = NULL; // other threads should check handle AlsaPCMHandle = NULL; // other threads should check handle
snd_pcm_close(handle); snd_pcm_close(handle);
if (AudioAlsaCloseOpenDelay) {
usleep(50 * 1000); // 50ms delay for alsa recovery
}
// FIXME: can use multiple retries
if (!(handle = AlsaOpenPCM(passthrough))) { if (!(handle = AlsaOpenPCM(passthrough))) {
return -1; return -1;
} }
AlsaPCMHandle = handle; AlsaPCMHandle = handle;
//Debug(3, "audio: %s ]\n", __FUNCTION__);
} }
for (;;) { for (;;) {
@ -1237,13 +1206,6 @@ static int AlsaSetup(int *freq, int *channels, int passthrough)
AlsaUseMmap ? SND_PCM_ACCESS_MMAP_INTERLEAVED : AlsaUseMmap ? SND_PCM_ACCESS_MMAP_INTERLEAVED :
SND_PCM_ACCESS_RW_INTERLEAVED, *channels, *freq, 1, SND_PCM_ACCESS_RW_INTERLEAVED, *channels, *freq, 1,
96 * 1000))) { 96 * 1000))) {
// try reduced buffer size (needed for sunxi)
// FIXME: alternativ make this configurable
if ((err =
snd_pcm_set_params(AlsaPCMHandle, SND_PCM_FORMAT_S16,
AlsaUseMmap ? SND_PCM_ACCESS_MMAP_INTERLEAVED :
SND_PCM_ACCESS_RW_INTERLEAVED, *channels, *freq, 1,
72 * 1000))) {
/* /*
if ( err == -EBADFD ) { if ( err == -EBADFD ) {
@ -1260,7 +1222,6 @@ static int AlsaSetup(int *freq, int *channels, int passthrough)
// FIXME: must stop sound, AudioChannels ... invalid // FIXME: must stop sound, AudioChannels ... invalid
return -1; return -1;
} }
}
break; break;
} }
@ -1558,6 +1519,7 @@ static int OssThread(void)
for (;;) { for (;;) {
struct pollfd fds[1]; struct pollfd fds[1];
pthread_testcancel();
if (AudioPaused) { if (AudioPaused) {
return 1; return 1;
} }
@ -1599,7 +1561,7 @@ static int OssThread(void)
/** /**
** Open OSS pcm device. ** Open OSS pcm device.
** **
** @param passthrough use pass-through (AC-3, ...) device ** @param passthrough use pass-through (AC3, ...) device
*/ */
static int OssOpenPCM(int passthrough) static int OssOpenPCM(int passthrough)
{ {
@ -1763,7 +1725,7 @@ static int64_t OssGetDelay(void)
** **
** @param sample_rate sample rate/frequency ** @param sample_rate sample rate/frequency
** @param channels number of channels ** @param channels number of channels
** @param passthrough use pass-through (AC-3, ...) device ** @param passthrough use pass-through (AC3, ...) device
** **
** @retval 0 everything ok ** @retval 0 everything ok
** @retval 1 didn't support frequency/channels combination ** @retval 1 didn't support frequency/channels combination
@ -1781,7 +1743,7 @@ static int OssSetup(int *sample_rate, int *channels, int passthrough)
return -1; return -1;
} }
if (1) { // close+open for pcm / AC-3 if (1) { // close+open for pcm / ac3
int fildes; int fildes;
fildes = OssPcmFildes; fildes = OssPcmFildes;
@ -1970,7 +1932,7 @@ static void NoopSetVolume( __attribute__ ((unused))
** **
** @param freq sample frequency ** @param freq sample frequency
** @param channels number of channels ** @param channels number of channels
** @param passthrough use pass-through (AC-3, ...) device ** @param passthrough use pass-through (AC3, ...) device
*/ */
static int NoopSetup( __attribute__ ((unused)) static int NoopSetup( __attribute__ ((unused))
int *channels, __attribute__ ((unused)) int *channels, __attribute__ ((unused))
@ -2059,12 +2021,6 @@ static void *AudioPlayHandlerThread(void *dummy)
{ {
Debug(3, "audio: play thread started\n"); Debug(3, "audio: play thread started\n");
for (;;) { for (;;) {
// check if we should stop the thread
if (AudioThreadStop) {
Debug(3, "audio: play thread stopped\n");
return PTHREAD_CANCELED;
}
Debug(3, "audio: wait on start condition\n"); Debug(3, "audio: wait on start condition\n");
pthread_mutex_lock(&AudioMutex); pthread_mutex_lock(&AudioMutex);
AudioRunning = 0; AudioRunning = 0;
@ -2075,42 +2031,35 @@ static void *AudioPlayHandlerThread(void *dummy)
pthread_mutex_unlock(&AudioMutex); pthread_mutex_unlock(&AudioMutex);
Debug(3, "audio: ----> %dms start\n", (AudioUsedBytes() * 1000) Debug(3, "audio: ----> %dms start\n", (AudioUsedBytes() * 1000)
/ (!AudioRing[AudioRingWrite].HwSampleRate + / (!AudioRing[AudioRingRead].HwSampleRate +
!AudioRing[AudioRingWrite].HwChannels + !AudioRing[AudioRingRead].HwChannels +
AudioRing[AudioRingWrite].HwSampleRate * AudioRing[AudioRingRead].HwSampleRate *
AudioRing[AudioRingWrite].HwChannels * AudioBytesProSample)); AudioRing[AudioRingRead].HwChannels * AudioBytesProSample));
do { do {
int filled; int filled;
int read; int read;
int flush; int flush;
int err; int err;
int i;
// check if we should stop the thread
if (AudioThreadStop) {
Debug(3, "audio: play thread stopped\n");
return PTHREAD_CANCELED;
}
// look if there is a flush command in the queue // look if there is a flush command in the queue
flush = 0; flush = 0;
filled = atomic_read(&AudioRingFilled); filled = atomic_read(&AudioRingFilled);
read = AudioRingRead; read = AudioRingRead;
i = filled; while (filled--) {
while (i--) {
read = (read + 1) % AUDIO_RING_MAX; read = (read + 1) % AUDIO_RING_MAX;
if (AudioRing[read].FlushBuffers) { if (AudioRing[read].FlushBuffers) {
AudioRing[read].FlushBuffers = 0; AudioRing[read].FlushBuffers = 0;
AudioRingRead = read; AudioRingRead = read;
atomic_set(&AudioRingFilled, filled);
// handle all flush in queue // handle all flush in queue
flush = filled - i; flush = 1;
} }
} }
if (flush) { if (flush) {
Debug(3, "audio: flush %d ring buffer(s)\n", flush); Debug(3, "audio: flush\n");
AudioUsedModule->FlushBuffers(); AudioUsedModule->FlushBuffers();
atomic_sub(flush, &AudioRingFilled);
if (AudioNextRing()) { if (AudioNextRing()) {
Debug(3, "audio: break after flush\n"); Debug(3, "audio: break after flush\n");
break; break;
@ -2118,10 +2067,7 @@ static void *AudioPlayHandlerThread(void *dummy)
Debug(3, "audio: continue after flush\n"); Debug(3, "audio: continue after flush\n");
} }
// try to play some samples // try to play some samples
err = 0;
if (RingBufferUsedBytes(AudioRing[AudioRingRead].RingBuffer)) {
err = AudioUsedModule->Thread(); err = AudioUsedModule->Thread();
}
// underrun, check if new ring buffer is available // underrun, check if new ring buffer is available
if (!err) { if (!err) {
int passthrough; int passthrough;
@ -2176,7 +2122,6 @@ static void *AudioPlayHandlerThread(void *dummy)
*/ */
static void AudioInitThread(void) static void AudioInitThread(void)
{ {
AudioThreadStop = 0;
pthread_mutex_init(&AudioMutex, NULL); pthread_mutex_init(&AudioMutex, NULL);
pthread_cond_init(&AudioStartCond, NULL); pthread_cond_init(&AudioStartCond, NULL);
pthread_create(&AudioThread, NULL, AudioPlayHandlerThread, NULL); pthread_create(&AudioThread, NULL, AudioPlayHandlerThread, NULL);
@ -2190,12 +2135,10 @@ static void AudioExitThread(void)
{ {
void *retval; void *retval;
Debug(3, "audio: %s\n", __FUNCTION__);
if (AudioThread) { if (AudioThread) {
AudioThreadStop = 1; if (pthread_cancel(AudioThread)) {
AudioRunning = 1; // wakeup thread, if needed Error(_("audio: can't queue cancel play thread\n"));
pthread_cond_signal(&AudioStartCond); }
if (pthread_join(AudioThread, &retval) || retval != PTHREAD_CANCELED) { if (pthread_join(AudioThread, &retval) || retval != PTHREAD_CANCELED) {
Error(_("audio: can't cancel play thread\n")); Error(_("audio: can't cancel play thread\n"));
} }
@ -2473,22 +2416,6 @@ void AudioFlushBuffers(void)
int old; int old;
int i; int i;
if (atomic_read(&AudioRingFilled) >= AUDIO_RING_MAX) {
// wait for space in ring buffer, should never happen
for (i = 0; i < 24 * 2; ++i) {
if (atomic_read(&AudioRingFilled) < AUDIO_RING_MAX) {
break;
}
Debug(3, "audio: flush out of ring buffers\n");
usleep(1 * 1000); // avoid hot polling
}
if (atomic_read(&AudioRingFilled) >= AUDIO_RING_MAX) {
// FIXME: We can set the flush flag in the last wrote ring buffer
Error(_("audio: flush out of ring buffers\n"));
return;
}
}
old = AudioRingWrite; old = AudioRingWrite;
AudioRingWrite = (AudioRingWrite + 1) % AUDIO_RING_MAX; AudioRingWrite = (AudioRingWrite + 1) % AUDIO_RING_MAX;
AudioRing[AudioRingWrite].FlushBuffers = 1; AudioRing[AudioRingWrite].FlushBuffers = 1;
@ -2506,13 +2433,12 @@ void AudioFlushBuffers(void)
atomic_inc(&AudioRingFilled); atomic_inc(&AudioRingFilled);
// FIXME: wait for flush complete needed? // FIXME: wait for flush complete?
for (i = 0; i < 24 * 2; ++i) { for (i = 0; i < 24 * 2; ++i) {
if (!AudioRunning) { // wakeup thread to flush buffers if (!AudioRunning) { // wakeup thread to flush buffers
AudioRunning = 1; AudioRunning = 1;
pthread_cond_signal(&AudioStartCond); pthread_cond_signal(&AudioStartCond);
} }
// FIXME: waiting on zero isn't correct, but currently works
if (!atomic_read(&AudioRingFilled)) { if (!atomic_read(&AudioRingFilled)) {
break; break;
} }
@ -2644,7 +2570,7 @@ void AudioSetVolume(int volume)
** **
** @param freq sample frequency ** @param freq sample frequency
** @param channels number of channels ** @param channels number of channels
** @param passthrough use pass-through (AC-3, ...) device ** @param passthrough use pass-through (AC3, ...) device
** **
** @retval 0 everything ok ** @retval 0 everything ok
** @retval 1 didn't support frequency/channels combination ** @retval 1 didn't support frequency/channels combination
@ -2824,20 +2750,6 @@ void AudioSetChannel(const char *channel)
AudioMixerChannel = channel; AudioMixerChannel = channel;
} }
/**
** Set automatic AES flag handling.
**
** @param onoff turn setting AES flag on or off
*/
void AudioSetAutoAES(int onoff)
{
if (onoff < 0) {
AudioAppendAES ^= 1;
} else {
AudioAppendAES = onoff;
}
}
/** /**
** Initialize audio output module. ** Initialize audio output module.
** **
@ -3017,8 +2929,6 @@ void AudioExit(void)
{ {
const AudioModule *module; const AudioModule *module;
Debug(3, "audio: %s\n", __FUNCTION__);
#ifdef USE_AUDIO_THREAD #ifdef USE_AUDIO_THREAD
if (AudioUsedModule->Thread) { // supports threads if (AudioUsedModule->Thread) { // supports threads
AudioExitThread(); AudioExitThread();

View File

@ -1,7 +1,7 @@
/// ///
/// @file audio.h @brief Audio module headerfile /// @file audio.h @brief Audio module headerfile
/// ///
/// Copyright (c) 2009 - 2014 by Johns. All Rights Reserved. /// Copyright (c) 2009 - 2013 by Johns. All Rights Reserved.
/// ///
/// Contributor(s): /// Contributor(s):
/// ///
@ -52,7 +52,6 @@ extern void AudioSetDevice(const char *); ///< set PCM audio device
/// set pass-through device /// set pass-through device
extern void AudioSetPassthroughDevice(const char *); extern void AudioSetPassthroughDevice(const char *);
extern void AudioSetChannel(const char *); ///< set mixer channel extern void AudioSetChannel(const char *); ///< set mixer channel
extern void AudioSetAutoAES(int); ///< set automatic AES flag handling
extern void AudioInit(void); ///< setup audio module extern void AudioInit(void); ///< setup audio module
extern void AudioExit(void); ///< cleanup and exit audio module extern void AudioExit(void); ///< cleanup and exit audio module
@ -61,7 +60,5 @@ extern void AudioExit(void); ///< cleanup and exit audio module
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
extern char AudioAlsaDriverBroken; ///< disable broken driver message extern char AudioAlsaDriverBroken; ///< disable broken driver message
extern char AudioAlsaNoCloseOpen; ///< disable alsa close/open fix
extern char AudioAlsaCloseOpenDelay; ///< enable alsa close/open delay fix
/// @} /// @}

305
codec.c
View File

@ -1,7 +1,7 @@
/// ///
/// @file codec.c @brief Codec functions /// @file codec.c @brief Codec functions
/// ///
/// Copyright (c) 2009 - 2015 by Johns. All Rights Reserved. /// Copyright (c) 2009 - 2013 by Johns. All Rights Reserved.
/// ///
/// Contributor(s): /// Contributor(s):
/// ///
@ -38,12 +38,8 @@
#define USE_AC3_DRIFT_CORRECTION #define USE_AC3_DRIFT_CORRECTION
/// use ffmpeg libswresample API (autodected, Makefile) /// use ffmpeg libswresample API (autodected, Makefile)
#define noUSE_SWRESAMPLE #define noUSE_SWRESAMPLE
/// use libav libavresample API (autodected, Makefile)
#define noUSE_AVRESAMPLE
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> #include <unistd.h>
#ifdef __FreeBSD__ #ifdef __FreeBSD__
#include <sys/endian.h> #include <sys/endian.h>
@ -58,16 +54,8 @@
#define _(str) gettext(str) ///< gettext shortcut #define _(str) gettext(str) ///< gettext shortcut
#define _N(str) str ///< gettext_noop shortcut #define _N(str) str ///< gettext_noop shortcut
#include <alsa/iatomic.h>
#include <libavcodec/avcodec.h> #include <libavcodec/avcodec.h>
#include <libavutil/mem.h>
// support old ffmpeg versions <1.0
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,18,102)
#define AVCodecID CodecID
#define AV_CODEC_ID_AC3 CODEC_ID_AC3
#define AV_CODEC_ID_EAC3 CODEC_ID_EAC3
#define AV_CODEC_ID_MPEG2VIDEO CODEC_ID_MPEG2VIDEO
#define AV_CODEC_ID_H264 CODEC_ID_H264
#endif
#include <libavcodec/vaapi.h> #include <libavcodec/vaapi.h>
#ifdef USE_VDPAU #ifdef USE_VDPAU
#include <libavcodec/vdpau.h> #include <libavcodec/vdpau.h>
@ -75,10 +63,6 @@
#ifdef USE_SWRESAMPLE #ifdef USE_SWRESAMPLE
#include <libswresample/swresample.h> #include <libswresample/swresample.h>
#endif #endif
#ifdef USE_AVRESAMPLE
#include <libavresample/avresample.h>
#include <libavutil/opt.h>
#endif
#ifndef __USE_GNU #ifndef __USE_GNU
#define __USE_GNU #define __USE_GNU
@ -88,22 +72,11 @@
#ifdef MAIN_H #ifdef MAIN_H
#include MAIN_H #include MAIN_H
#endif #endif
#include "iatomic.h"
#include "misc.h" #include "misc.h"
#include "video.h" #include "video.h"
#include "audio.h" #include "audio.h"
#include "codec.h" #include "codec.h"
//----------------------------------------------------------------------------
// correct is AV_VERSION_INT(56,35,101) but some gentoo i* think
// they must change it.
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56,26,100)
/// ffmpeg 2.6 started to show artifacts after channel switch
/// to SDTV channels
#define FFMPEG_WORKAROUND_ARTIFACTS 1
#endif
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Global // Global
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -116,9 +89,6 @@
/// ///
static pthread_mutex_t CodecLockMutex; static pthread_mutex_t CodecLockMutex;
/// Flag prefer fast channel switch
char CodecUsePossibleDefectFrames;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Video // Video
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -140,9 +110,6 @@ struct _video_decoder_
int GetFormatDone; ///< flag get format called! int GetFormatDone; ///< flag get format called!
AVCodec *VideoCodec; ///< video codec AVCodec *VideoCodec; ///< video codec
AVCodecContext *VideoCtx; ///< video codec context AVCodecContext *VideoCtx; ///< video codec context
#ifdef FFMPEG_WORKAROUND_ARTIFACTS
int FirstKeyFrame; ///< flag first frame
#endif
AVFrame *Frame; ///< decoded video frame AVFrame *Frame; ///< decoded video frame
}; };
@ -227,9 +194,7 @@ static int Codec_get_buffer(AVCodecContext * video_ctx, AVFrame * frame)
//Debug(3, "codec: use surface %#010x\n", surface); //Debug(3, "codec: use surface %#010x\n", surface);
#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52,48,101)
frame->type = FF_BUFFER_TYPE_USER; frame->type = FF_BUFFER_TYPE_USER;
#endif
#if LIBAVCODEC_VERSION_INT <= AV_VERSION_INT(53,46,0) #if LIBAVCODEC_VERSION_INT <= AV_VERSION_INT(53,46,0)
frame->age = 256 * 256 * 256 * 64; frame->age = 256 * 256 * 256 * 64;
#endif #endif
@ -239,14 +204,12 @@ static int Codec_get_buffer(AVCodecContext * video_ctx, AVFrame * frame)
frame->data[2] = NULL; frame->data[2] = NULL;
frame->data[3] = NULL; frame->data[3] = NULL;
#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52,66,100)
// reordered frames // reordered frames
if (video_ctx->pkt) { if (video_ctx->pkt) {
frame->pkt_pts = video_ctx->pkt->pts; frame->pkt_pts = video_ctx->pkt->pts;
} else { } else {
frame->pkt_pts = AV_NOPTS_VALUE; frame->pkt_pts = AV_NOPTS_VALUE;
} }
#endif
return 0; return 0;
} }
#endif #endif
@ -258,9 +221,7 @@ static int Codec_get_buffer(AVCodecContext * video_ctx, AVFrame * frame)
//Debug(3, "codec: use surface %#010x\n", surface); //Debug(3, "codec: use surface %#010x\n", surface);
#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52,48,101)
frame->type = FF_BUFFER_TYPE_USER; frame->type = FF_BUFFER_TYPE_USER;
#endif
#if LIBAVCODEC_VERSION_INT <= AV_VERSION_INT(53,46,0) #if LIBAVCODEC_VERSION_INT <= AV_VERSION_INT(53,46,0)
frame->age = 256 * 256 * 256 * 64; frame->age = 256 * 256 * 256 * 64;
#endif #endif
@ -268,14 +229,12 @@ static int Codec_get_buffer(AVCodecContext * video_ctx, AVFrame * frame)
frame->data[0] = (void *)(size_t) surface; frame->data[0] = (void *)(size_t) surface;
frame->data[3] = (void *)(size_t) surface; frame->data[3] = (void *)(size_t) surface;
#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52,66,100)
// reordered frames // reordered frames
if (video_ctx->pkt) { if (video_ctx->pkt) {
frame->pkt_pts = video_ctx->pkt->pts; frame->pkt_pts = video_ctx->pkt->pts;
} else { } else {
frame->pkt_pts = AV_NOPTS_VALUE; frame->pkt_pts = AV_NOPTS_VALUE;
} }
#endif
return 0; return 0;
} }
//Debug(3, "codec: fallback to default get_buffer\n"); //Debug(3, "codec: fallback to default get_buffer\n");
@ -420,39 +379,22 @@ void CodecVideoDelDecoder(VideoDecoder * decoder)
** Open video decoder. ** Open video decoder.
** **
** @param decoder private video decoder ** @param decoder private video decoder
** @param codec_id video codec id ** @param name video codec name
** @param codec_id video codec id, used if name == NULL
*/ */
void CodecVideoOpen(VideoDecoder * decoder, int codec_id) void CodecVideoOpen(VideoDecoder * decoder, const char *name, int codec_id)
{ {
AVCodec *video_codec; AVCodec *video_codec;
const char *name;
Debug(3, "codec: using video codec ID %#06x (%s)\n", codec_id, Debug(3, "codec: using video codec %s or ID %#06x\n", name, codec_id);
avcodec_get_name(codec_id));
if (decoder->VideoCtx) { if (decoder->VideoCtx) {
Error(_("codec: missing close\n")); Error(_("codec: missing close\n"));
} }
#if 1
// FIXME: old vdpau API: should be updated to new API
name = NULL;
if (!strcasecmp(VideoGetDriverName(), "vdpau")) {
switch (codec_id) {
case AV_CODEC_ID_MPEG2VIDEO:
name = VideoHardwareDecoder < 0 ? "mpegvideo_vdpau" : NULL;
break;
case AV_CODEC_ID_H264:
name = VideoHardwareDecoder ? "h264_vdpau" : NULL;
break;
}
}
if (name && (video_codec = avcodec_find_decoder_by_name(name))) { if (name && (video_codec = avcodec_find_decoder_by_name(name))) {
Debug(3, "codec: vdpau decoder found\n"); Debug(3, "codec: vdpau decoder found\n");
} else } else if (!(video_codec = avcodec_find_decoder(codec_id))) {
#endif
if (!(video_codec = avcodec_find_decoder(codec_id))) {
Fatal(_("codec: codec ID %#06x not found\n"), codec_id); Fatal(_("codec: codec ID %#06x not found\n"), codec_id);
// FIXME: none fatal // FIXME: none fatal
} }
@ -491,8 +433,8 @@ void CodecVideoOpen(VideoDecoder * decoder, int codec_id)
decoder->VideoCtx->opaque = decoder; // our structure decoder->VideoCtx->opaque = decoder; // our structure
Debug(3, "codec: video '%s'\n", decoder->VideoCodec->long_name); Debug(3, "codec: video '%s'\n", decoder->VideoCtx->codec_name);
if (codec_id == AV_CODEC_ID_H264) { if (codec_id == CODEC_ID_H264) {
// 2.53 Ghz CPU is too slow for this codec at 1080i // 2.53 Ghz CPU is too slow for this codec at 1080i
//decoder->VideoCtx->skip_loop_filter = AVDISCARD_ALL; //decoder->VideoCtx->skip_loop_filter = AVDISCARD_ALL;
//decoder->VideoCtx->skip_loop_filter = AVDISCARD_BIDIR; //decoder->VideoCtx->skip_loop_filter = AVDISCARD_BIDIR;
@ -534,7 +476,7 @@ void CodecVideoOpen(VideoDecoder * decoder, int codec_id)
} else { } else {
decoder->VideoCtx->get_format = Codec_get_format; decoder->VideoCtx->get_format = Codec_get_format;
decoder->VideoCtx->hwaccel_context = decoder->VideoCtx->hwaccel_context =
VideoGetHwAccelContext(decoder->HwDecoder); VideoGetVaapiContext(decoder->HwDecoder);
} }
// our pixel format video hardware decoder hook // our pixel format video hardware decoder hook
@ -554,20 +496,11 @@ void CodecVideoOpen(VideoDecoder * decoder, int codec_id)
// //
// Prepare frame buffer for decoder // Prepare frame buffer for decoder
// //
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56,28,1)
if (!(decoder->Frame = av_frame_alloc())) {
Fatal(_("codec: can't allocate video decoder frame buffer\n"));
}
#else
if (!(decoder->Frame = avcodec_alloc_frame())) { if (!(decoder->Frame = avcodec_alloc_frame())) {
Fatal(_("codec: can't allocate video decoder frame buffer\n")); Fatal(_("codec: can't allocate decoder frame\n"));
} }
#endif
// reset buggy ffmpeg/libav flag // reset buggy ffmpeg/libav flag
decoder->GetFormatDone = 0; decoder->GetFormatDone = 0;
#ifdef FFMPEG_WORKAROUND_ARTIFACTS
decoder->FirstKeyFrame = 1;
#endif
} }
/** /**
@ -578,17 +511,12 @@ void CodecVideoOpen(VideoDecoder * decoder, int codec_id)
void CodecVideoClose(VideoDecoder * video_decoder) void CodecVideoClose(VideoDecoder * video_decoder)
{ {
// FIXME: play buffered data // FIXME: play buffered data
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56,28,1)
av_frame_free(&video_decoder->Frame); // callee does checks
#else
av_freep(&video_decoder->Frame); av_freep(&video_decoder->Frame);
#endif
if (video_decoder->VideoCtx) { if (video_decoder->VideoCtx) {
pthread_mutex_lock(&CodecLockMutex); pthread_mutex_lock(&CodecLockMutex);
avcodec_close(video_decoder->VideoCtx); avcodec_close(video_decoder->VideoCtx);
av_freep(&video_decoder->VideoCtx);
pthread_mutex_unlock(&CodecLockMutex); pthread_mutex_unlock(&CodecLockMutex);
av_freep(&video_decoder->VideoCtx);
} }
} }
@ -659,22 +587,8 @@ void CodecVideoDecode(VideoDecoder * decoder, const AVPacket * avpkt)
} }
if (got_frame) { // frame completed if (got_frame) { // frame completed
#ifdef FFMPEG_WORKAROUND_ARTIFACTS
if (!CodecUsePossibleDefectFrames && decoder->FirstKeyFrame) {
decoder->FirstKeyFrame++;
if (frame->key_frame) {
Debug(3, "codec: key frame after %d frames\n",
decoder->FirstKeyFrame);
decoder->FirstKeyFrame = 0;
}
} else {
//DisplayPts(video_ctx, frame); //DisplayPts(video_ctx, frame);
VideoRenderFrame(decoder->HwDecoder, video_ctx, frame); VideoRenderFrame(decoder->HwDecoder, video_ctx, frame);
}
#else
//DisplayPts(video_ctx, frame);
VideoRenderFrame(decoder->HwDecoder, video_ctx, frame);
#endif
} else { } else {
// some frames are needed for references, interlaced frames ... // some frames are needed for references, interlaced frames ...
// could happen with h264 dvb streams, just drop data. // could happen with h264 dvb streams, just drop data.
@ -703,11 +617,6 @@ void CodecVideoDecode(VideoDecoder * decoder, const AVPacket * avpkt)
} }
} }
#endif #endif
// new AVFrame API
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56,28,1)
av_frame_unref(frame);
#endif
} }
/** /**
@ -748,22 +657,15 @@ struct _audio_decoder_
int HwSampleRate; ///< hw sample rate int HwSampleRate; ///< hw sample rate
int HwChannels; ///< hw channels int HwChannels; ///< hw channels
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56,28,1) #ifndef USE_SWRESAMPLE
AVFrame *Frame; ///< decoded audio frame buffer ReSampleContext *ReSample; ///< audio resampling context
#endif
#if !defined(USE_SWRESAMPLE) && !defined(USE_AVRESAMPLE)
ReSampleContext *ReSample; ///< old resampling context
#endif #endif
#ifdef USE_SWRESAMPLE #ifdef USE_SWRESAMPLE
#if LIBSWRESAMPLE_VERSION_INT < AV_VERSION_INT(0, 15, 100) #if LIBSWRESAMPLE_VERSION_INT < AV_VERSION_INT(0, 15, 100)
struct SwrContext *Resample; ///< ffmpeg software resample context struct SwrContext *Resample; ///< audio software resample context
#else #else
SwrContext *Resample; ///< ffmpeg software resample context SwrContext *Resample; ///< audio software resample context
#endif #endif
#endif
#ifdef USE_AVRESAMPLE
AVAudioResampleContext *Resample; ///< libav software resample context
#endif #endif
uint16_t Spdif[24576 / 2]; ///< SPDIF output buffer uint16_t Spdif[24576 / 2]; ///< SPDIF output buffer
@ -778,7 +680,7 @@ struct _audio_decoder_
int DriftCorr; ///< audio drift correction value int DriftCorr; ///< audio drift correction value
int DriftFrac; ///< audio drift fraction for ac3 int DriftFrac; ///< audio drift fraction for ac3
#if !defined(USE_SWRESAMPLE) && !defined(USE_AVRESAMPLE) #ifndef USE_SWRESAMPLE
struct AVResampleContext *AvResample; ///< second audio resample context struct AVResampleContext *AvResample; ///< second audio resample context
#define MAX_CHANNELS 8 ///< max number of channels supported #define MAX_CHANNELS 8 ///< max number of channels supported
int16_t *Buffer[MAX_CHANNELS]; ///< deinterleave sample buffers int16_t *Buffer[MAX_CHANNELS]; ///< deinterleave sample buffers
@ -801,7 +703,7 @@ enum IEC61937
#ifdef USE_AUDIO_DRIFT_CORRECTION #ifdef USE_AUDIO_DRIFT_CORRECTION
#define CORRECT_PCM 1 ///< do PCM audio-drift correction #define CORRECT_PCM 1 ///< do PCM audio-drift correction
#define CORRECT_AC3 2 ///< do AC-3 audio-drift correction #define CORRECT_AC3 2 ///< do AC3 audio-drift correction
static char CodecAudioDrift; ///< flag: enable audio-drift correction static char CodecAudioDrift; ///< flag: enable audio-drift correction
#else #else
static const int CodecAudioDrift = 0; static const int CodecAudioDrift = 0;
@ -828,11 +730,6 @@ AudioDecoder *CodecAudioNewDecoder(void)
if (!(audio_decoder = calloc(1, sizeof(*audio_decoder)))) { if (!(audio_decoder = calloc(1, sizeof(*audio_decoder)))) {
Fatal(_("codec: can't allocate audio decoder\n")); Fatal(_("codec: can't allocate audio decoder\n"));
} }
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56,28,1)
if (!(audio_decoder->Frame = av_frame_alloc())) {
Fatal(_("codec: can't allocate audio decoder frame buffer\n"));
}
#endif
return audio_decoder; return audio_decoder;
} }
@ -844,9 +741,6 @@ AudioDecoder *CodecAudioNewDecoder(void)
*/ */
void CodecAudioDelDecoder(AudioDecoder * decoder) void CodecAudioDelDecoder(AudioDecoder * decoder)
{ {
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56,28,1)
av_frame_free(&decoder->Frame); // callee does checks
#endif
free(decoder); free(decoder);
} }
@ -854,16 +748,19 @@ void CodecAudioDelDecoder(AudioDecoder * decoder)
** Open audio decoder. ** Open audio decoder.
** **
** @param audio_decoder private audio decoder ** @param audio_decoder private audio decoder
** @param codec_id audio codec id ** @param name audio codec name
** @param codec_id audio codec id, used if name == NULL
*/ */
void CodecAudioOpen(AudioDecoder * audio_decoder, int codec_id) void CodecAudioOpen(AudioDecoder * audio_decoder, const char *name,
int codec_id)
{ {
AVCodec *audio_codec; AVCodec *audio_codec;
Debug(3, "codec: using audio codec ID %#06x (%s)\n", codec_id, Debug(3, "codec: using audio codec %s or ID %#06x\n", name, codec_id);
avcodec_get_name(codec_id));
if (!(audio_codec = avcodec_find_decoder(codec_id))) { if (name && (audio_codec = avcodec_find_decoder_by_name(name))) {
Debug(3, "codec: audio decoder '%s' found\n", name);
} else if (!(audio_codec = avcodec_find_decoder(codec_id))) {
Fatal(_("codec: codec ID %#06x not found\n"), codec_id); Fatal(_("codec: codec ID %#06x not found\n"), codec_id);
// FIXME: errors aren't fatal // FIXME: errors aren't fatal
} }
@ -874,14 +771,14 @@ void CodecAudioOpen(AudioDecoder * audio_decoder, int codec_id)
} }
if (CodecDownmix) { if (CodecDownmix) {
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(53,61,100) #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(53,61,100) || FF_API_REQUEST_CHANNELS
audio_decoder->AudioCtx->request_channels = 2; audio_decoder->AudioCtx->request_channels = 2;
#endif #endif
audio_decoder->AudioCtx->request_channel_layout = audio_decoder->AudioCtx->request_channel_layout =
AV_CH_LAYOUT_STEREO_DOWNMIX; AV_CH_LAYOUT_STEREO_DOWNMIX;
} }
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53,61,100) #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53,61,100)
// this has no effect (with ffmpeg and libav) // this has no effect
// audio_decoder->AudioCtx->request_sample_fmt = AV_SAMPLE_FMT_S16; // audio_decoder->AudioCtx->request_sample_fmt = AV_SAMPLE_FMT_S16;
#endif #endif
pthread_mutex_lock(&CodecLockMutex); pthread_mutex_lock(&CodecLockMutex);
@ -908,7 +805,7 @@ void CodecAudioOpen(AudioDecoder * audio_decoder, int codec_id)
} }
#endif #endif
pthread_mutex_unlock(&CodecLockMutex); pthread_mutex_unlock(&CodecLockMutex);
Debug(3, "codec: audio '%s'\n", audio_decoder->AudioCodec->long_name); Debug(3, "codec: audio '%s'\n", audio_decoder->AudioCtx->codec_name);
if (audio_codec->capabilities & CODEC_CAP_TRUNCATED) { if (audio_codec->capabilities & CODEC_CAP_TRUNCATED) {
Debug(3, "codec: audio can use truncated packets\n"); Debug(3, "codec: audio can use truncated packets\n");
@ -930,7 +827,7 @@ void CodecAudioOpen(AudioDecoder * audio_decoder, int codec_id)
void CodecAudioClose(AudioDecoder * audio_decoder) void CodecAudioClose(AudioDecoder * audio_decoder)
{ {
// FIXME: output any buffered data // FIXME: output any buffered data
#if !defined(USE_SWRESAMPLE) && !defined(USE_AVRESAMPLE) #ifndef USE_SWRESAMPLE
if (audio_decoder->AvResample) { if (audio_decoder->AvResample) {
int ch; int ch;
@ -955,24 +852,19 @@ void CodecAudioClose(AudioDecoder * audio_decoder)
if (audio_decoder->Resample) { if (audio_decoder->Resample) {
swr_free(&audio_decoder->Resample); swr_free(&audio_decoder->Resample);
} }
#endif
#ifdef USE_AVRESAMPLE
if (audio_decoder->Resample) {
avresample_free(&audio_decoder->Resample);
}
#endif #endif
if (audio_decoder->AudioCtx) { if (audio_decoder->AudioCtx) {
pthread_mutex_lock(&CodecLockMutex); pthread_mutex_lock(&CodecLockMutex);
avcodec_close(audio_decoder->AudioCtx); avcodec_close(audio_decoder->AudioCtx);
av_freep(&audio_decoder->AudioCtx);
pthread_mutex_unlock(&CodecLockMutex); pthread_mutex_unlock(&CodecLockMutex);
av_freep(&audio_decoder->AudioCtx);
} }
} }
/** /**
** Set audio drift correction. ** Set audio drift correction.
** **
** @param mask enable mask (PCM, AC-3) ** @param mask enable mask (PCM, AC3)
*/ */
void CodecSetAudioDrift(int mask) void CodecSetAudioDrift(int mask)
{ {
@ -985,7 +877,7 @@ void CodecSetAudioDrift(int mask)
/** /**
** Set audio pass-through. ** Set audio pass-through.
** **
** @param mask enable mask (PCM, AC-3, E-AC-3) ** @param mask enable mask (PCM, AC3, EAC3)
*/ */
void CodecSetAudioPassthrough(int mask) void CodecSetAudioPassthrough(int mask)
{ {
@ -1086,8 +978,8 @@ static int CodecAudioUpdateHelper(AudioDecoder * audio_decoder,
av_get_sample_fmt_name(audio_ctx->sample_fmt), audio_ctx->sample_rate, av_get_sample_fmt_name(audio_ctx->sample_fmt), audio_ctx->sample_rate,
audio_ctx->channels, CodecPassthrough & CodecPCM ? " PCM" : "", audio_ctx->channels, CodecPassthrough & CodecPCM ? " PCM" : "",
CodecPassthrough & CodecMPA ? " MPA" : "", CodecPassthrough & CodecMPA ? " MPA" : "",
CodecPassthrough & CodecAC3 ? " AC-3" : "", CodecPassthrough & CodecAC3 ? " AC3" : "",
CodecPassthrough & CodecEAC3 ? " E-AC-3" : "", CodecPassthrough & CodecEAC3 ? " EAC3" : "",
CodecPassthrough ? " pass-through" : ""); CodecPassthrough ? " pass-through" : "");
*passthrough = 0; *passthrough = 0;
@ -1098,11 +990,11 @@ static int CodecAudioUpdateHelper(AudioDecoder * audio_decoder,
audio_decoder->Passthrough = CodecPassthrough; audio_decoder->Passthrough = CodecPassthrough;
// SPDIF/HDMI pass-through // SPDIF/HDMI pass-through
if ((CodecPassthrough & CodecAC3 && audio_ctx->codec_id == AV_CODEC_ID_AC3) if ((CodecPassthrough & CodecAC3 && audio_ctx->codec_id == CODEC_ID_AC3)
|| (CodecPassthrough & CodecEAC3 || (CodecPassthrough & CodecEAC3
&& audio_ctx->codec_id == AV_CODEC_ID_EAC3)) { && audio_ctx->codec_id == CODEC_ID_EAC3)) {
if (audio_ctx->codec_id == AV_CODEC_ID_EAC3) { if (audio_ctx->codec_id == CODEC_ID_EAC3) {
// E-AC-3 over HDMI some receivers need HBR // EAC3 over HDMI some receivers need HBR
audio_decoder->HwSampleRate *= 4; audio_decoder->HwSampleRate *= 4;
} }
audio_decoder->HwChannels = 2; audio_decoder->HwChannels = 2;
@ -1115,9 +1007,9 @@ static int CodecAudioUpdateHelper(AudioDecoder * audio_decoder,
AudioSetup(&audio_decoder->HwSampleRate, AudioSetup(&audio_decoder->HwSampleRate,
&audio_decoder->HwChannels, *passthrough))) { &audio_decoder->HwChannels, *passthrough))) {
// try E-AC-3 none HBR // try EAC3 none HBR
audio_decoder->HwSampleRate /= 4; audio_decoder->HwSampleRate /= 4;
if (audio_ctx->codec_id != AV_CODEC_ID_EAC3 if (audio_ctx->codec_id != CODEC_ID_EAC3
|| (err = || (err =
AudioSetup(&audio_decoder->HwSampleRate, AudioSetup(&audio_decoder->HwSampleRate,
&audio_decoder->HwChannels, *passthrough))) { &audio_decoder->HwChannels, *passthrough))) {
@ -1152,7 +1044,7 @@ static int CodecAudioPassthroughHelper(AudioDecoder * audio_decoder,
audio_ctx = audio_decoder->AudioCtx; audio_ctx = audio_decoder->AudioCtx;
// SPDIF/HDMI passthrough // SPDIF/HDMI passthrough
if (CodecPassthrough & CodecAC3 && audio_ctx->codec_id == AV_CODEC_ID_AC3) { if (CodecPassthrough & CodecAC3 && audio_ctx->codec_id == CODEC_ID_AC3) {
uint16_t *spdif; uint16_t *spdif;
int spdif_sz; int spdif_sz;
@ -1202,8 +1094,7 @@ static int CodecAudioPassthroughHelper(AudioDecoder * audio_decoder,
AudioEnqueue(spdif, spdif_sz); AudioEnqueue(spdif, spdif_sz);
return 1; return 1;
} }
if (CodecPassthrough & CodecEAC3 if (CodecPassthrough & CodecEAC3 && audio_ctx->codec_id == CODEC_ID_EAC3) {
&& audio_ctx->codec_id == AV_CODEC_ID_EAC3) {
uint16_t *spdif; uint16_t *spdif;
int spdif_sz; int spdif_sz;
int repeat; int repeat;
@ -1256,7 +1147,7 @@ static int CodecAudioPassthroughHelper(AudioDecoder * audio_decoder,
return 0; return 0;
} }
#if !defined(USE_SWRESAMPLE) && !defined(USE_AVRESAMPLE) #ifndef USE_SWRESAMPLE
/** /**
** Set/update audio pts clock. ** Set/update audio pts clock.
@ -1332,9 +1223,9 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
corr = (10 * audio_decoder->HwSampleRate * drift) / (90 * 1000); corr = (10 * audio_decoder->HwSampleRate * drift) / (90 * 1000);
// SPDIF/HDMI passthrough // SPDIF/HDMI passthrough
if ((CodecAudioDrift & CORRECT_AC3) && (!(CodecPassthrough & CodecAC3) if ((CodecAudioDrift & CORRECT_AC3) && (!(CodecPassthrough & CodecAC3)
|| audio_decoder->AudioCtx->codec_id != AV_CODEC_ID_AC3) || audio_decoder->AudioCtx->codec_id != CODEC_ID_AC3)
&& (!(CodecPassthrough & CodecEAC3) && (!(CodecPassthrough & CodecEAC3)
|| audio_decoder->AudioCtx->codec_id != AV_CODEC_ID_EAC3)) { || audio_decoder->AudioCtx->codec_id != CODEC_ID_EAC3)) {
audio_decoder->DriftCorr = -corr; audio_decoder->DriftCorr = -corr;
} }
@ -1658,7 +1549,7 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
#endif #endif
#if defined(USE_SWRESAMPLE) || defined(USE_AVRESAMPLE) #ifdef USE_SWRESAMPLE
/** /**
** Set/update audio pts clock. ** Set/update audio pts clock.
@ -1668,7 +1559,6 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
*/ */
static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts) static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
{ {
#ifdef USE_AUDIO_DRIFT_CORRECTION
struct timespec nowtime; struct timespec nowtime;
int64_t delay; int64_t delay;
int64_t tim_diff; int64_t tim_diff;
@ -1735,9 +1625,9 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
corr = (10 * audio_decoder->HwSampleRate * drift) / (90 * 1000); corr = (10 * audio_decoder->HwSampleRate * drift) / (90 * 1000);
// SPDIF/HDMI passthrough // SPDIF/HDMI passthrough
if ((CodecAudioDrift & CORRECT_AC3) && (!(CodecPassthrough & CodecAC3) if ((CodecAudioDrift & CORRECT_AC3) && (!(CodecPassthrough & CodecAC3)
|| audio_decoder->AudioCtx->codec_id != AV_CODEC_ID_AC3) || audio_decoder->AudioCtx->codec_id != CODEC_ID_AC3)
&& (!(CodecPassthrough & CodecEAC3) && (!(CodecPassthrough & CodecEAC3)
|| audio_decoder->AudioCtx->codec_id != AV_CODEC_ID_EAC3)) { || audio_decoder->AudioCtx->codec_id != CODEC_ID_EAC3)) {
audio_decoder->DriftCorr = -corr; audio_decoder->DriftCorr = -corr;
} }
@ -1748,7 +1638,6 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
} }
} }
#ifdef USE_SWRESAMPLE
if (audio_decoder->Resample && audio_decoder->DriftCorr) { if (audio_decoder->Resample && audio_decoder->DriftCorr) {
int distance; int distance;
@ -1763,18 +1652,6 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
Debug(3, "codec/audio: swr_set_compensation failed\n"); Debug(3, "codec/audio: swr_set_compensation failed\n");
} }
} }
#endif
#ifdef USE_AVRESAMPLE
if (audio_decoder->Resample && audio_decoder->DriftCorr) {
int distance;
distance = (pts_diff * audio_decoder->HwSampleRate) / (900 * 1000);
if (avresample_set_compensation(audio_decoder->Resample,
audio_decoder->DriftCorr / 10, distance)) {
Debug(3, "codec/audio: swr_set_compensation failed\n");
}
}
#endif
if (1) { if (1) {
static int c; static int c;
@ -1783,9 +1660,6 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
audio_decoder->DriftCorr, drift * 1000 / 90, corr); audio_decoder->DriftCorr, drift * 1000 / 90, corr);
} }
} }
#else
AudioSetClock(pts);
#endif
} }
/** /**
@ -1817,7 +1691,6 @@ static void CodecAudioUpdateFormat(AudioDecoder * audio_decoder)
} }
#endif #endif
#ifdef USE_SWRESAMPLE
audio_decoder->Resample = audio_decoder->Resample =
swr_alloc_set_opts(audio_decoder->Resample, audio_ctx->channel_layout, swr_alloc_set_opts(audio_decoder->Resample, audio_ctx->channel_layout,
AV_SAMPLE_FMT_S16, audio_decoder->HwSampleRate, AV_SAMPLE_FMT_S16, audio_decoder->HwSampleRate,
@ -1828,33 +1701,6 @@ static void CodecAudioUpdateFormat(AudioDecoder * audio_decoder)
} else { } else {
Error(_("codec/audio: can't setup resample\n")); Error(_("codec/audio: can't setup resample\n"));
} }
#endif
#ifdef USE_AVRESAMPLE
if (!(audio_decoder->Resample = avresample_alloc_context())) {
Error(_("codec/audio: can't setup resample\n"));
return;
}
av_opt_set_int(audio_decoder->Resample, "in_channel_layout",
audio_ctx->channel_layout, 0);
av_opt_set_int(audio_decoder->Resample, "in_sample_fmt",
audio_ctx->sample_fmt, 0);
av_opt_set_int(audio_decoder->Resample, "in_sample_rate",
audio_ctx->sample_rate, 0);
av_opt_set_int(audio_decoder->Resample, "out_channel_layout",
audio_ctx->channel_layout, 0);
av_opt_set_int(audio_decoder->Resample, "out_sample_fmt",
AV_SAMPLE_FMT_S16, 0);
av_opt_set_int(audio_decoder->Resample, "out_sample_rate",
audio_decoder->HwSampleRate, 0);
if (avresample_open(audio_decoder->Resample)) {
avresample_free(&audio_decoder->Resample);
audio_decoder->Resample = NULL;
Error(_("codec/audio: can't open resample\n"));
return;
}
#endif
} }
/** /**
@ -1870,31 +1716,16 @@ static void CodecAudioUpdateFormat(AudioDecoder * audio_decoder)
void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt) void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
{ {
AVCodecContext *audio_ctx; AVCodecContext *audio_ctx;
AVFrame frame;
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56,28,1)
AVFrame frame[1];
#else
AVFrame *frame;
#endif
int got_frame; int got_frame;
int n; int n;
audio_ctx = audio_decoder->AudioCtx; audio_ctx = audio_decoder->AudioCtx;
// FIXME: don't need to decode pass-through codecs // FIXME: don't need to decode pass-through codecs
frame.data[0] = NULL;
// new AVFrame API n = avcodec_decode_audio4(audio_ctx, &frame, &got_frame,
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56,28,1)
avcodec_get_frame_defaults(frame);
#else
frame = audio_decoder->Frame;
av_frame_unref(frame);
#endif
got_frame = 0;
n = avcodec_decode_audio4(audio_ctx, frame, &got_frame,
(AVPacket *) avpkt); (AVPacket *) avpkt);
if (n != avpkt->size) { if (n != avpkt->size) {
if (n == AVERROR(EAGAIN)) { if (n == AVERROR(EAGAIN)) {
Error(_("codec/audio: latm\n")); Error(_("codec/audio: latm\n"));
@ -1936,7 +1767,7 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
data_sz = data_sz =
av_samples_get_buffer_size(&plane_sz, audio_ctx->channels, av_samples_get_buffer_size(&plane_sz, audio_ctx->channels,
frame->nb_samples, audio_ctx->sample_fmt, 1); frame.nb_samples, audio_ctx->sample_fmt, 1);
fprintf(stderr, "codec/audio: sample_fmt %s\n", fprintf(stderr, "codec/audio: sample_fmt %s\n",
av_get_sample_fmt_name(audio_ctx->sample_fmt)); av_get_sample_fmt_name(audio_ctx->sample_fmt));
av_get_channel_layout_string(strbuf, 32, audio_ctx->channels, av_get_channel_layout_string(strbuf, 32, audio_ctx->channels,
@ -1944,9 +1775,9 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
fprintf(stderr, "codec/audio: layout %s\n", strbuf); fprintf(stderr, "codec/audio: layout %s\n", strbuf);
fprintf(stderr, fprintf(stderr,
"codec/audio: channels %d samples %d plane %d data %d\n", "codec/audio: channels %d samples %d plane %d data %d\n",
audio_ctx->channels, frame->nb_samples, plane_sz, data_sz); audio_ctx->channels, frame.nb_samples, plane_sz, data_sz);
} }
#ifdef USE_SWRESAMPLE
if (audio_decoder->Resample) { if (audio_decoder->Resample) {
uint8_t outbuf[8192 * 2 * 8]; uint8_t outbuf[8192 * 2 * 8];
uint8_t *out[1]; uint8_t *out[1];
@ -1954,7 +1785,7 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
out[0] = outbuf; out[0] = outbuf;
n = swr_convert(audio_decoder->Resample, out, n = swr_convert(audio_decoder->Resample, out,
sizeof(outbuf) / (2 * audio_decoder->HwChannels), sizeof(outbuf) / (2 * audio_decoder->HwChannels),
(const uint8_t **)frame->extended_data, frame->nb_samples); (const uint8_t **)frame.extended_data, frame.nb_samples);
if (n > 0) { if (n > 0) {
if (!(audio_decoder->Passthrough & CodecPCM)) { if (!(audio_decoder->Passthrough & CodecPCM)) {
CodecReorderAudioFrame((int16_t *) outbuf, CodecReorderAudioFrame((int16_t *) outbuf,
@ -1965,30 +1796,6 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
} }
return; return;
} }
#endif
#ifdef USE_AVRESAMPLE
if (audio_decoder->Resample) {
uint8_t outbuf[8192 * 2 * 8];
uint8_t *out[1];
out[0] = outbuf;
n = avresample_convert(audio_decoder->Resample, out, 0,
sizeof(outbuf) / (2 * audio_decoder->HwChannels),
(uint8_t **) frame->extended_data, 0, frame->nb_samples);
// FIXME: set out_linesize, in_linesize correct
if (n > 0) {
if (!(audio_decoder->Passthrough & CodecPCM)) {
CodecReorderAudioFrame((int16_t *) outbuf,
n * 2 * audio_decoder->HwChannels,
audio_decoder->HwChannels);
}
AudioEnqueue(outbuf, n * 2 * audio_decoder->HwChannels);
}
return;
}
#endif
#ifdef DEBUG #ifdef DEBUG
// should be never reached // should be never reached
fprintf(stderr, "oops\n"); fprintf(stderr, "oops\n");

15
codec.h
View File

@ -1,7 +1,7 @@
/// ///
/// @file codec.h @brief Codec module headerfile /// @file codec.h @brief Codec module headerfile
/// ///
/// Copyright (c) 2009 - 2013, 2015 by Johns. All Rights Reserved. /// Copyright (c) 2009 - 2013 by Johns. All Rights Reserved.
/// ///
/// Contributor(s): /// Contributor(s):
/// ///
@ -30,7 +30,7 @@
#define CodecPCM 0x01 ///< PCM bit mask #define CodecPCM 0x01 ///< PCM bit mask
#define CodecMPA 0x02 ///< MPA bit mask (planned) #define CodecMPA 0x02 ///< MPA bit mask (planned)
#define CodecAC3 0x04 ///< AC-3 bit mask #define CodecAC3 0x04 ///< AC-3 bit mask
#define CodecEAC3 0x08 ///< E-AC-3 bit mask #define CodecEAC3 0x08 ///< EAC-3 bit mask
#define CodecDTS 0x10 ///< DTS bit mask (planned) #define CodecDTS 0x10 ///< DTS bit mask (planned)
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -43,13 +43,6 @@ typedef struct _video_decoder_ VideoDecoder;
/// Audio decoder typedef. /// Audio decoder typedef.
typedef struct _audio_decoder_ AudioDecoder; typedef struct _audio_decoder_ AudioDecoder;
//----------------------------------------------------------------------------
// Variables
//----------------------------------------------------------------------------
/// Flag prefer fast xhannel switch
extern char CodecUsePossibleDefectFrames;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Prototypes // Prototypes
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -61,7 +54,7 @@ extern VideoDecoder *CodecVideoNewDecoder(VideoHwDecoder *);
extern void CodecVideoDelDecoder(VideoDecoder *); extern void CodecVideoDelDecoder(VideoDecoder *);
/// Open video codec. /// Open video codec.
extern void CodecVideoOpen(VideoDecoder *, int); extern void CodecVideoOpen(VideoDecoder *, const char *, int);
/// Close video codec. /// Close video codec.
extern void CodecVideoClose(VideoDecoder *); extern void CodecVideoClose(VideoDecoder *);
@ -79,7 +72,7 @@ extern AudioDecoder *CodecAudioNewDecoder(void);
extern void CodecAudioDelDecoder(AudioDecoder *); extern void CodecAudioDelDecoder(AudioDecoder *);
/// Open audio codec. /// Open audio codec.
extern void CodecAudioOpen(AudioDecoder *, int); extern void CodecAudioOpen(AudioDecoder *, const char *, int);
/// Close audio codec. /// Close audio codec.
extern void CodecAudioClose(AudioDecoder *); extern void CodecAudioClose(AudioDecoder *);

View File

@ -1,97 +0,0 @@
///
/// @file iatomic.h @brief Misc function header file
///
/// Copyright (c) 2014 by Johns. All Rights Reserved.
///
/// Contributor(s):
///
/// License: AGPLv3
///
/// This program is free software: you can redistribute it and/or modify
/// it under the terms of the GNU Affero General Public License as
/// published by the Free Software Foundation, either version 3 of the
/// License.
///
/// This program 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 Affero General Public License for more details.
///
/// $Id$
//////////////////////////////////////////////////////////////////////////////
/// @addtogroup iatomic
/// @{
#define GCC_VERSION (__GNUC__ * 10000 \
+ __GNUC_MINOR__ * 100 \
+ __GNUC_PATCHLEVEL__)
// gcc before 4.7 didn't support atomic builtins,
// use alsa atomic functions.
#if GCC_VERSION < 40700
#include <alsa/iatomic.h>
#else
//////////////////////////////////////////////////////////////////////////////
// Defines
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// Declares
//////////////////////////////////////////////////////////////////////////////
///
/// atomic type, 24 bit useable,
///
typedef volatile int atomic_t;
//////////////////////////////////////////////////////////////////////////////
// Prototypes
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// Inlines
//////////////////////////////////////////////////////////////////////////////
///
/// Set atomic value.
///
#define atomic_set(ptr, val) \
__atomic_store_n(ptr, val, __ATOMIC_SEQ_CST)
///
/// Read atomic value.
///
#define atomic_read(ptr) \
__atomic_load_n(ptr, __ATOMIC_SEQ_CST)
///
/// Increment atomic value.
///
#define atomic_inc(ptr) \
__atomic_add_fetch(ptr, 1, __ATOMIC_SEQ_CST)
///
/// Decrement atomic value.
///
#define atomic_dec(ptr) \
__atomic_sub_fetch(ptr, 1, __ATOMIC_SEQ_CST)
///
/// Add to atomic value.
///
#define atomic_add(val, ptr) \
__atomic_add_fetch(ptr, val, __ATOMIC_SEQ_CST)
///
/// Subtract from atomic value.
///
#define atomic_sub(val, ptr) \
__atomic_sub_fetch(ptr, val, __ATOMIC_SEQ_CST)
#endif
/// @}

View File

@ -7,10 +7,10 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: VDR \n" "Project-Id-Version: VDR \n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2015-10-20 14:39+0200\n" "POT-Creation-Date: 2013-03-09 19:20+0100\n"
"PO-Revision-Date: blabla\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: blabla\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: blabla\n" "Language-Team: LANGUAGE <LL@li.org>\n"
"Language: german\n" "Language: german\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n" "Content-Type: text/plain; charset=utf-8\n"
@ -229,6 +229,9 @@ msgstr ""
msgid "audio: can't set channels %d sample-rate %dHz\n" msgid "audio: can't set channels %d sample-rate %dHz\n"
msgstr "" msgstr ""
msgid "audio: can't queue cancel play thread\n"
msgstr ""
msgid "audio: can't cancel play thread\n" msgid "audio: can't cancel play thread\n"
msgstr "" msgstr ""
@ -236,9 +239,6 @@ msgstr ""
msgid "audio: can't place %d samples in ring buffer\n" msgid "audio: can't place %d samples in ring buffer\n"
msgstr "" msgstr ""
msgid "audio: flush out of ring buffers\n"
msgstr ""
#, c-format #, c-format
msgid "audio: '%s' output module used\n" msgid "audio: '%s' output module used\n"
msgstr "" msgstr ""
@ -270,15 +270,12 @@ msgstr ""
msgid "codec: can't open video codec!\n" msgid "codec: can't open video codec!\n"
msgstr "" msgstr ""
msgid "codec: can't allocate video decoder frame buffer\n" msgid "codec: can't allocate decoder frame\n"
msgstr "" msgstr ""
msgid "codec: can't allocate audio decoder\n" msgid "codec: can't allocate audio decoder\n"
msgstr "" msgstr ""
msgid "codec: can't allocate audio decoder frame buffer\n"
msgstr ""
msgid "codec: can't allocate audio codec context\n" msgid "codec: can't allocate audio codec context\n"
msgstr "" msgstr ""
@ -309,9 +306,6 @@ msgstr ""
msgid "codec/audio: can't setup resample\n" msgid "codec/audio: can't setup resample\n"
msgstr "" msgstr ""
msgid "codec/audio: can't open resample\n"
msgstr ""
msgid "codec/audio: latm\n" msgid "codec/audio: latm\n"
msgstr "" msgstr ""
@ -390,10 +384,6 @@ msgstr ""
msgid "[softhddev] invalid PES video packet\n" msgid "[softhddev] invalid PES video packet\n"
msgstr "" msgstr ""
#, c-format
msgid "[softhddev] %d invalid PES video packet(s)\n"
msgstr ""
msgid "[softhddev] empty video packet\n" msgid "[softhddev] empty video packet\n"
msgstr "" msgstr ""
@ -489,9 +479,6 @@ msgstr "OSD Höhe"
msgid "Suspend" msgid "Suspend"
msgstr "Unterbrechen" msgstr "Unterbrechen"
msgid "Detach from main menu entry"
msgstr "Detach durch Hauptmenüeintrag"
msgid "Suspend closes video+audio" msgid "Suspend closes video+audio"
msgstr "Unterbrechen schließt Video+Audio" msgstr "Unterbrechen schließt Video+Audio"
@ -501,9 +488,6 @@ msgstr "Unterbrechen stoppt X11"
msgid "Video" msgid "Video"
msgstr "Video" msgstr "Video"
msgid "Enable Screensaver(DPMS) at black screen"
msgstr "Bildschirmschoner(DPMS) bei schwarzen Bild aktivieren"
msgid "Video background color (RGB)" msgid "Video background color (RGB)"
msgstr "Video Hintergrundfrabe (RGB)" msgstr "Video Hintergrundfrabe (RGB)"
@ -522,9 +506,6 @@ msgstr "Sanftanlauf A/V Sync"
msgid "Black during channel switch" msgid "Black during channel switch"
msgstr "Schwarz während Kanalwechsel" msgstr "Schwarz während Kanalwechsel"
msgid "Clear decoder on channel switch"
msgstr "Decoder bei Kanalwechsel leeren"
msgid "Brightness (-1000..1000) (vdpau)" msgid "Brightness (-1000..1000) (vdpau)"
msgstr "Helligkeit (-1000..1000) (vdpau)" msgstr "Helligkeit (-1000..1000) (vdpau)"
@ -606,11 +587,11 @@ msgstr ""
msgid " AC-3 pass-through" msgid " AC-3 pass-through"
msgstr "" msgstr ""
msgid " E-AC-3 pass-through" msgid " EAC-3 pass-through"
msgstr "" msgstr ""
msgid "Enable (E-)AC-3 (decoder) downmix" msgid "Enable (E)AC-3 (decoder) downmix"
msgstr "Aktiviere (E-)AC-3 (decoder) downmix" msgstr ""
msgid "Volume control" msgid "Volume control"
msgstr "Lautstärkesteuerung" msgstr "Lautstärkesteuerung"
@ -639,9 +620,6 @@ msgstr "Reduziere Steropegel (/1000)"
msgid "Audio buffer size (ms)" msgid "Audio buffer size (ms)"
msgstr "Audio Puffergröße (ms)" msgstr "Audio Puffergröße (ms)"
msgid "Enable automatic AES"
msgstr "Aktiviere automatiche AES"
msgid "Picture-In-Picture" msgid "Picture-In-Picture"
msgstr "Bild in Bild (PIP)" msgstr "Bild in Bild (PIP)"
@ -649,7 +627,7 @@ msgid "Pip X (%)"
msgstr "PIP X (%)" msgstr "PIP X (%)"
msgid "Pip Y (%)" msgid "Pip Y (%)"
msgstr "PIP Y (%)" msgstr "PIP X (%)"
msgid "Pip Width (%)" msgid "Pip Width (%)"
msgstr "PIP Breite (%)" msgstr "PIP Breite (%)"
@ -694,7 +672,7 @@ msgid "Alternative Video Height (%)"
msgstr "Alternative Videohöhe (%)" msgstr "Alternative Videohöhe (%)"
#, c-format #, c-format
msgid "[softhddev]pip: invalid PES packet %d\n" msgid "[softhddev]pip: invalid pes packet %d\n"
msgstr "" msgstr ""
msgid "[softhddev]pip: pes buffer too small\n" msgid "[softhddev]pip: pes buffer too small\n"
@ -706,9 +684,6 @@ msgstr ""
msgid "Channel not available!" msgid "Channel not available!"
msgstr "Kanal nicht verfügbar!" msgstr "Kanal nicht verfügbar!"
msgid "Detach SoftHdDevice"
msgstr ""
msgid "Suspend SoftHdDevice" msgid "Suspend SoftHdDevice"
msgstr "Unterbreche SoftHdDevice" msgstr "Unterbreche SoftHdDevice"
@ -756,12 +731,6 @@ msgstr ""
msgid "audio delay changed to %d" msgid "audio delay changed to %d"
msgstr "" msgstr ""
msgid "surround downmix enabled"
msgstr ""
msgid "surround downmix disabled"
msgstr ""
msgid "auto-crop disabled and freezed" msgid "auto-crop disabled and freezed"
msgstr "" msgstr ""
@ -926,9 +895,6 @@ msgstr ""
msgid "unsupported" msgid "unsupported"
msgstr "" msgstr ""
msgid "video/glx: glx error\n"
msgstr ""
#, c-format #, c-format
msgid "video/vaapi: unsupported pixel format %d\n" msgid "video/vaapi: unsupported pixel format %d\n"
msgstr "" msgstr ""
@ -1002,20 +968,14 @@ msgstr ""
msgid "video: output buffer full, dropping frame (%d/%d)\n" msgid "video: output buffer full, dropping frame (%d/%d)\n"
msgstr "" msgstr ""
#, c-format msgid "video/vaapi: can't create a surface\n"
msgid "video/vaapi: can't create a surface: %s\n"
msgstr "" msgstr ""
#, c-format #, c-format
msgid "video/vaapi: can't associate subpicture: %s\n" msgid "video/vaapi: vaDeriveImage failed %d\n"
msgstr "" msgstr ""
#, c-format msgid "video/vaapi: can't map the image!\n"
msgid "video/vaapi: can't create image: %s\n"
msgstr ""
#, c-format
msgid "video/vaapi: can't map the image: %s\n"
msgstr "" msgstr ""
msgid "video/vaapi: can't unmap the image!\n" msgid "video/vaapi: can't unmap the image!\n"
@ -1030,10 +990,6 @@ msgstr ""
msgid "video/vaapi: can't get source image\n" msgid "video/vaapi: can't get source image\n"
msgstr "" msgstr ""
#, c-format
msgid "video/vaapi: vaDeriveImage failed %d\n"
msgstr ""
#, c-format #, c-format
msgid "video/vaapi: can't put image: %d!\n" msgid "video/vaapi: can't put image: %d!\n"
msgstr "" msgstr ""
@ -1041,9 +997,6 @@ msgstr ""
msgid "video/vaapi: stream <-> surface size mismatch\n" msgid "video/vaapi: stream <-> surface size mismatch\n"
msgstr "" msgstr ""
msgid "video/vaapi: can't map the image!\n"
msgstr ""
#, c-format #, c-format
msgid "video/vaapi: can't put image err:%d!\n" msgid "video/vaapi: can't put image err:%d!\n"
msgstr "" msgstr ""
@ -1071,7 +1024,7 @@ msgstr ""
msgid "video/vaapi: can't find a supported subpicture format" msgid "video/vaapi: can't find a supported subpicture format"
msgstr "" msgstr ""
msgid "video/vaapi: supports unscaled osd\n" msgid "video/vaapi: vaapi supports unscaled osd\n"
msgstr "" msgstr ""
msgid "video/vaapi: can't create osd image\n" msgid "video/vaapi: can't create osd image\n"
@ -1312,9 +1265,6 @@ msgstr ""
msgid "video/vdpau: can't put video surface bits: %s\n" msgid "video/vdpau: can't put video surface bits: %s\n"
msgstr "" msgstr ""
msgid "video: get hwaccel context, not supported\n"
msgstr ""
#, c-format #, c-format
msgid "video/vdpau: can't render bitmap surface: %s\n" msgid "video/vdpau: can't render bitmap surface: %s\n"
msgstr "" msgstr ""
@ -1327,10 +1277,6 @@ msgstr ""
msgid "video/vdpau: can't render mixer: %s\n" msgid "video/vdpau: can't render mixer: %s\n"
msgstr "" msgstr ""
#, c-format
msgid "video/vdpau: can't query status: %s\n"
msgstr ""
#, c-format #, c-format
msgid "video/vdpau: can't block queue: %s\n" msgid "video/vdpau: can't block queue: %s\n"
msgstr "" msgstr ""
@ -1385,6 +1331,9 @@ msgstr ""
msgid "video: repeated pict %d found, but not handled\n" msgid "video: repeated pict %d found, but not handled\n"
msgstr "" msgstr ""
msgid "video/vaapi: get vaapi context, without vaapi enabled\n"
msgstr ""
#, c-format #, c-format
msgid "video/vdpau: decoder rendering failed: %s\n" msgid "video/vdpau: decoder rendering failed: %s\n"
msgstr "" msgstr ""
@ -1406,10 +1355,6 @@ msgstr ""
msgid "video: Can't connect to X11 server on '%s'\n" msgid "video: Can't connect to X11 server on '%s'\n"
msgstr "" msgstr ""
#, c-format
msgid "video: Can't initialize X11 thread support on '%s'\n"
msgstr ""
msgid "video: Can't convert XLIB display to XCB connection\n" msgid "video: Can't convert XLIB display to XCB connection\n"
msgstr "" msgstr ""

View File

@ -1,7 +1,7 @@
/// ///
/// @file ringbuffer.c @brief Ringbuffer module /// @file ringbuffer.c @brief Ringbuffer module
/// ///
/// Copyright (c) 2009, 2011, 2014 by Johns. All Rights Reserved. /// Copyright (c) 2009, 2011 by Johns. All Rights Reserved.
/// ///
/// Contributor(s): /// Contributor(s):
/// ///
@ -30,7 +30,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "iatomic.h" #include <alsa/iatomic.h>
#include "ringbuffer.h" #include "ringbuffer.h"
/// ring buffer structure /// ring buffer structure

View File

@ -1,7 +1,7 @@
/// ///
/// @file softhddev.c @brief A software HD device plugin for VDR. /// @file softhddev.c @brief A software HD device plugin for VDR.
/// ///
/// Copyright (c) 2011 - 2015 by Johns. All Rights Reserved. /// Copyright (c) 2011 - 2013 by Johns. All Rights Reserved.
/// ///
/// Contributor(s): /// Contributor(s):
/// ///
@ -22,7 +22,6 @@
#define noUSE_SOFTLIMIT ///< add soft buffer limits to Play.. #define noUSE_SOFTLIMIT ///< add soft buffer limits to Play..
#define noUSE_PIP ///< include PIP support + new API #define noUSE_PIP ///< include PIP support + new API
#define noDUMP_TRICKSPEED ///< dump raw trickspeed packets
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -32,38 +31,21 @@
#include <fcntl.h> #include <fcntl.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <inttypes.h> #include <inttypes.h>
#include <unistd.h> #include <unistd.h>
#include <string.h>
#include <libintl.h> #include <libintl.h>
#define _(str) gettext(str) ///< gettext shortcut #define _(str) gettext(str) ///< gettext shortcut
#define _N(str) str ///< gettext_noop shortcut #define _N(str) str ///< gettext_noop shortcut
#include <libavcodec/avcodec.h> #include <libavcodec/avcodec.h>
#include <libavutil/mem.h>
// support old ffmpeg versions <1.0
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,18,102)
#define AVCodecID CodecID
#define AV_CODEC_ID_AAC CODEC_ID_AAC
#define AV_CODEC_ID_AAC_LATM CODEC_ID_AAC_LATM
#define AV_CODEC_ID_AC3 CODEC_ID_AC3
#define AV_CODEC_ID_EAC3 CODEC_ID_EAC3
#define AV_CODEC_ID_H264 CODEC_ID_H264
#define AV_CODEC_ID_MP2 CODEC_ID_MP2
#define AV_CODEC_ID_MPEG2VIDEO CODEC_ID_MPEG2VIDEO
#define AV_CODEC_ID_NONE CODEC_ID_NONE
#define AV_CODEC_ID_PCM_DVD CODEC_ID_PCM_DVD
#endif
#ifndef __USE_GNU #ifndef __USE_GNU
#define __USE_GNU #define __USE_GNU
#endif #endif
#include <pthread.h> #include <pthread.h>
#include "iatomic.h" // portable atomic_t
#include "misc.h" #include "misc.h"
#include "softhddev.h" #include "softhddev.h"
@ -80,10 +62,15 @@ static void DumpMpeg(const uint8_t * data, int size);
// Variables // Variables
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
#ifdef USE_VDPAU
static char VdpauDecoder = 1; ///< vdpau decoder used
#else
#define VdpauDecoder 0 ///< no vdpau decoder configured
#endif
extern int ConfigAudioBufferTime; ///< config size ms of audio buffer extern int ConfigAudioBufferTime; ///< config size ms of audio buffer
extern int ConfigVideoClearOnSwitch; //< clear decoder on channel switch
char ConfigStartX11Server; ///< flag start the x11 server char ConfigStartX11Server; ///< flag start the x11 server
static signed char ConfigStartSuspended; ///< flag to start in suspend mode static char ConfigStartSuspended; ///< flag to start in suspend mode
static char ConfigFullscreen; ///< fullscreen modus static char ConfigFullscreen; ///< fullscreen modus
static const char *X11ServerArguments; ///< default command arguments static const char *X11ServerArguments; ///< default command arguments
static char ConfigStillDecoder; ///< hw/sw decoder for still picture static char ConfigStillDecoder; ///< hw/sw decoder for still picture
@ -99,7 +86,7 @@ static volatile char StreamFreezed; ///< stream freezed
static volatile char NewAudioStream; ///< new audio stream static volatile char NewAudioStream; ///< new audio stream
static volatile char SkipAudio; ///< skip audio stream static volatile char SkipAudio; ///< skip audio stream
static AudioDecoder *MyAudioDecoder; ///< audio decoder static AudioDecoder *MyAudioDecoder; ///< audio decoder
static enum AVCodecID AudioCodecID; ///< current codec id static enum CodecID AudioCodecID; ///< current codec id
static int AudioChannelID; ///< current audio channel id static int AudioChannelID; ///< current audio channel id
static VideoStream *AudioSyncStream; ///< video stream for audio/video sync static VideoStream *AudioSyncStream; ///< video stream for audio/video sync
@ -309,7 +296,7 @@ static int LatmCheck(const uint8_t * data, int size)
} }
/// ///
/// Possible AC-3 frame sizes. /// Possible AC3 frame sizes.
/// ///
/// from ATSC A/52 table 5.18 frame size code table. /// from ATSC A/52 table 5.18 frame size code table.
/// ///
@ -327,9 +314,9 @@ const uint16_t Ac3FrameSizeTable[38][3] = {
}; };
/// ///
/// Fast check for (E-)AC-3 audio. /// Fast check for (E)AC3 audio.
/// ///
/// 5 bytes 0x0B77xxxxxx AC-3 audio /// 5 bytes 0x0B77xxxxxx AC3 audio
/// ///
static inline int FastAc3Check(const uint8_t * p) static inline int FastAc3Check(const uint8_t * p)
{ {
@ -343,7 +330,7 @@ static inline int FastAc3Check(const uint8_t * p)
} }
/// ///
/// Check for (E-)AC-3 audio. /// Check for (E)AC-3 audio.
/// ///
/// 0x0B77xxxxxx already checked. /// 0x0B77xxxxxx already checked.
/// ///
@ -354,7 +341,7 @@ static inline int FastAc3Check(const uint8_t * p)
/// @retval 0 no valid AC-3 audio /// @retval 0 no valid AC-3 audio
/// @retval >0 valid AC-3 audio /// @retval >0 valid AC-3 audio
/// ///
/// o AC-3 Header /// o AC3 Header
/// AAAAAAAA AAAAAAAA BBBBBBBB BBBBBBBB CCDDDDDD EEEEEFFF /// AAAAAAAA AAAAAAAA BBBBBBBB BBBBBBBB CCDDDDDD EEEEEFFF
/// ///
/// o a 16x Frame sync, always 0x0B77 /// o a 16x Frame sync, always 0x0B77
@ -364,7 +351,7 @@ static inline int FastAc3Check(const uint8_t * p)
/// o e 5x Bitstream ID /// o e 5x Bitstream ID
/// o f 3x Bitstream mode /// o f 3x Bitstream mode
/// ///
/// o E-AC-3 Header /// o EAC3 Header
/// AAAAAAAA AAAAAAAA BBCCCDDD DDDDDDDD EEFFGGGH IIIII... /// AAAAAAAA AAAAAAAA BBCCCDDD DDDDDDDD EEFFGGGH IIIII...
/// ///
/// o a 16x Frame sync, always 0x0B77 /// o a 16x Frame sync, always 0x0B77
@ -378,17 +365,17 @@ static int Ac3Check(const uint8_t * data, int size)
{ {
int frame_size; int frame_size;
if (size < 5) { // need 5 bytes to see if AC-3/E-AC-3 if (size < 5) { // need 5 bytes to see if AC3/EAC3
return -5; return -5;
} }
if (data[5] > (10 << 3)) { // E-AC-3 if (data[5] > (10 << 3)) { // EAC3
if ((data[4] & 0xF0) == 0xF0) { // invalid fscod fscod2 if ((data[4] & 0xF0) == 0xF0) { // invalid fscod fscod2
return 0; return 0;
} }
frame_size = ((data[2] & 0x03) << 8) + data[3] + 1; frame_size = ((data[2] & 0x03) << 8) + data[3] + 1;
frame_size *= 2; frame_size *= 2;
} else { // AC-3 } else { // AC3
int fscod; int fscod;
int frmsizcod; int frmsizcod;
@ -630,7 +617,7 @@ static void PesParse(PesDemux * pesdx, const uint8_t * data, int size,
#if 0 #if 0
// Played with PlayAudio // Played with PlayAudio
// FIXME: need 0x80 -- 0xA0 state // FIXME: need 0x80 -- 0xA0 state
if (AudioCodecID == AV_CODEC_ID_NONE) { if (AudioCodecID == CODEC_ID_NONE) {
if ((*p & 0xF0) == 0x80) { // AC-3 & DTS if ((*p & 0xF0) == 0x80) { // AC-3 & DTS
Debug(3, "pesdemux: dvd ac-3\n"); Debug(3, "pesdemux: dvd ac-3\n");
} else if ((*p & 0xFF) == 0xA0) { // LPCM } else if ((*p & 0xFF) == 0xA0) { // LPCM
@ -664,8 +651,8 @@ static void PesParse(PesDemux * pesdx, const uint8_t * data, int size,
unsigned codec_id; unsigned codec_id;
// 4 bytes 0xFFExxxxx Mpeg audio // 4 bytes 0xFFExxxxx Mpeg audio
// 5 bytes 0x0B77xxxxxx AC-3 audio // 5 bytes 0x0B77xxxxxx AC3 audio
// 6 bytes 0x0B77xxxxxxxx E-AC-3 audio // 6 bytes 0x0B77xxxxxxxx EAC3 audio
// 3 bytes 0x56Exxx AAC LATM audio // 3 bytes 0x56Exxx AAC LATM audio
// 7/9 bytes 0xFFFxxxxxxxxxxx ADTS audio // 7/9 bytes 0xFFFxxxxxxxxxxx ADTS audio
// PCM audio can't be found // PCM audio can't be found
@ -673,22 +660,22 @@ static void PesParse(PesDemux * pesdx, const uint8_t * data, int size,
r = 0; r = 0;
if (!r && FastMpegCheck(q)) { if (!r && FastMpegCheck(q)) {
r = MpegCheck(q, n); r = MpegCheck(q, n);
codec_id = AV_CODEC_ID_MP2; codec_id = CODEC_ID_MP2;
} }
if (!r && FastAc3Check(q)) { if (!r && FastAc3Check(q)) {
r = Ac3Check(q, n); r = Ac3Check(q, n);
codec_id = AV_CODEC_ID_AC3; codec_id = CODEC_ID_AC3;
if (r > 0 && q[5] > (10 << 3)) { if (r > 0 && q[5] > (10 << 3)) {
codec_id = AV_CODEC_ID_EAC3; codec_id = CODEC_ID_EAC3;
} }
} }
if (!r && FastLatmCheck(q)) { if (!r && FastLatmCheck(q)) {
r = LatmCheck(q, n); r = LatmCheck(q, n);
codec_id = AV_CODEC_ID_AAC_LATM; codec_id = CODEC_ID_AAC_LATM;
} }
if (!r && FastAdtsCheck(q)) { if (!r && FastAdtsCheck(q)) {
r = AdtsCheck(q, n); r = AdtsCheck(q, n);
codec_id = AV_CODEC_ID_AAC; codec_id = CODEC_ID_AAC;
} }
if (r < 0) { // need more bytes if (r < 0) { // need more bytes
break; break;
@ -701,7 +688,7 @@ static void PesParse(PesDemux * pesdx, const uint8_t * data, int size,
Debug(3, "pesdemux: new codec %#06x -> %#06x\n", Debug(3, "pesdemux: new codec %#06x -> %#06x\n",
AudioCodecID, codec_id); AudioCodecID, codec_id);
CodecAudioClose(MyAudioDecoder); CodecAudioClose(MyAudioDecoder);
CodecAudioOpen(MyAudioDecoder, codec_id); CodecAudioOpen(MyAudioDecoder, NULL, codec_id);
AudioCodecID = codec_id; AudioCodecID = codec_id;
} }
av_init_packet(avpkt); av_init_packet(avpkt);
@ -718,7 +705,7 @@ static void PesParse(PesDemux * pesdx, const uint8_t * data, int size,
//pesdx->State = PES_MPEG_DECODE; //pesdx->State = PES_MPEG_DECODE;
break; break;
} }
if (AudioCodecID != AV_CODEC_ID_NONE) { if (AudioCodecID != CODEC_ID_NONE) {
// shouldn't happen after we have a vaild codec // shouldn't happen after we have a vaild codec
// detected // detected
Debug(4, "pesdemux: skip @%d %02x\n", pesdx->Skip, Debug(4, "pesdemux: skip @%d %02x\n", pesdx->Skip,
@ -844,7 +831,7 @@ static void PesParse(PesDemux * pesdx, const uint8_t * data, int size,
int bits_per_sample; int bits_per_sample;
const uint8_t *q; const uint8_t *q;
if (AudioCodecID != AV_CODEC_ID_PCM_DVD) { if (AudioCodecID != CODEC_ID_PCM_DVD) {
q = pesdx->Header; q = pesdx->Header;
Debug(3, "pesdemux: LPCM %d sr:%d bits:%d chan:%d\n", Debug(3, "pesdemux: LPCM %d sr:%d bits:%d chan:%d\n",
@ -874,8 +861,8 @@ static void PesParse(PesDemux * pesdx, const uint8_t * data, int size,
(q[5] & 0x7) + 1); (q[5] & 0x7) + 1);
// FIXME: support resample // FIXME: support resample
} }
//CodecAudioOpen(MyAudioDecoder, AV_CODEC_ID_PCM_DVD); //CodecAudioOpen(MyAudioDecoder, NULL, CODEC_ID_PCM_DVD);
AudioCodecID = AV_CODEC_ID_PCM_DVD; AudioCodecID = CODEC_ID_PCM_DVD;
} }
pesdx->State = PES_LPCM_PAYLOAD; pesdx->State = PES_LPCM_PAYLOAD;
pesdx->Index = 0; pesdx->Index = 0;
@ -1036,7 +1023,7 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id)
CodecAudioClose(MyAudioDecoder); CodecAudioClose(MyAudioDecoder);
AudioFlushBuffers(); AudioFlushBuffers();
AudioSetBufferTime(ConfigAudioBufferTime); AudioSetBufferTime(ConfigAudioBufferTime);
AudioCodecID = AV_CODEC_ID_NONE; AudioCodecID = CODEC_ID_NONE;
AudioChannelID = -1; AudioChannelID = -1;
NewAudioStream = 0; NewAudioStream = 0;
} }
@ -1094,8 +1081,7 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id)
if (AudioChannelID != id) { // id changed audio track changed if (AudioChannelID != id) { // id changed audio track changed
AudioChannelID = id; AudioChannelID = id;
AudioCodecID = AV_CODEC_ID_NONE; AudioCodecID = CODEC_ID_NONE;
Debug(3, "audio/demux: new channel id\n");
} }
// Private stream + LPCM ID // Private stream + LPCM ID
if ((id & 0xF0) == 0xA0) { if ((id & 0xF0) == 0xA0) {
@ -1103,7 +1089,7 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id)
Error(_("[softhddev] invalid LPCM audio packet %d bytes\n"), size); Error(_("[softhddev] invalid LPCM audio packet %d bytes\n"), size);
return size; return size;
} }
if (AudioCodecID != AV_CODEC_ID_PCM_DVD) { if (AudioCodecID != CODEC_ID_PCM_DVD) {
static int samplerates[] = { 48000, 96000, 44100, 32000 }; static int samplerates[] = { 48000, 96000, 44100, 32000 };
int samplerate; int samplerate;
int channels; int channels;
@ -1137,8 +1123,8 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id)
(p[5] & 0x7) + 1); (p[5] & 0x7) + 1);
// FIXME: support resample // FIXME: support resample
} }
//CodecAudioOpen(MyAudioDecoder, AV_CODEC_ID_PCM_DVD); //CodecAudioOpen(MyAudioDecoder, NULL, CODEC_ID_PCM_DVD);
AudioCodecID = AV_CODEC_ID_PCM_DVD; AudioCodecID = CODEC_ID_PCM_DVD;
} }
if (AudioAvPkt->pts != (int64_t) AV_NOPTS_VALUE) { if (AudioAvPkt->pts != (int64_t) AV_NOPTS_VALUE) {
@ -1154,7 +1140,7 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id)
if ((id & 0xF0) == 0x80 && (p[0] & 0xF0) == 0x80) { if ((id & 0xF0) == 0x80 && (p[0] & 0xF0) == 0x80) {
p += 4; p += 4;
n -= 4; // skip track header n -= 4; // skip track header
if (AudioCodecID == AV_CODEC_ID_NONE) { if (AudioCodecID == CODEC_ID_NONE) {
// FIXME: ConfigAudioBufferTime + x // FIXME: ConfigAudioBufferTime + x
AudioSetBufferTime(400); AudioSetBufferTime(400);
} }
@ -1171,25 +1157,25 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id)
// 4 bytes 0xFFExxxxx Mpeg audio // 4 bytes 0xFFExxxxx Mpeg audio
// 3 bytes 0x56Exxx AAC LATM audio // 3 bytes 0x56Exxx AAC LATM audio
// 5 bytes 0x0B77xxxxxx AC-3 audio // 5 bytes 0x0B77xxxxxx AC3 audio
// 6 bytes 0x0B77xxxxxxxx E-AC-3 audio // 6 bytes 0x0B77xxxxxxxx EAC3 audio
// 7/9 bytes 0xFFFxxxxxxxxxxx ADTS audio // 7/9 bytes 0xFFFxxxxxxxxxxx ADTS audio
// PCM audio can't be found // PCM audio can't be found
r = 0; r = 0;
codec_id = AV_CODEC_ID_NONE; // keep compiler happy codec_id = CODEC_ID_NONE; // keep compiler happy
if (id != 0xbd && FastMpegCheck(p)) { if (id != 0xbd && FastMpegCheck(p)) {
r = MpegCheck(p, n); r = MpegCheck(p, n);
codec_id = AV_CODEC_ID_MP2; codec_id = CODEC_ID_MP2;
} }
if (id != 0xbd && !r && FastLatmCheck(p)) { if (id != 0xbd && !r && FastLatmCheck(p)) {
r = LatmCheck(p, n); r = LatmCheck(p, n);
codec_id = AV_CODEC_ID_AAC_LATM; codec_id = CODEC_ID_AAC_LATM;
} }
if ((id == 0xbd || (id & 0xF0) == 0x80) && !r && FastAc3Check(p)) { if ((id == 0xbd || (id & 0xF0) == 0x80) && !r && FastAc3Check(p)) {
r = Ac3Check(p, n); r = Ac3Check(p, n);
codec_id = AV_CODEC_ID_AC3; codec_id = CODEC_ID_AC3;
if (r > 0 && p[5] > (10 << 3)) { if (r > 0 && p[5] > (10 << 3)) {
codec_id = AV_CODEC_ID_EAC3; codec_id = CODEC_ID_EAC3;
} }
/* faster ac3 detection at end of pes packet (no improvemnts) /* faster ac3 detection at end of pes packet (no improvemnts)
if (AudioCodecID == codec_id && -r - 2 == n) { if (AudioCodecID == codec_id && -r - 2 == n) {
@ -1199,7 +1185,7 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id)
} }
if (id != 0xbd && !r && FastAdtsCheck(p)) { if (id != 0xbd && !r && FastAdtsCheck(p)) {
r = AdtsCheck(p, n); r = AdtsCheck(p, n);
codec_id = AV_CODEC_ID_AAC; codec_id = CODEC_ID_AAC;
} }
if (r < 0) { // need more bytes if (r < 0) { // need more bytes
break; break;
@ -1210,7 +1196,7 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id)
// new codec id, close and open new // new codec id, close and open new
if (AudioCodecID != codec_id) { if (AudioCodecID != codec_id) {
CodecAudioClose(MyAudioDecoder); CodecAudioClose(MyAudioDecoder);
CodecAudioOpen(MyAudioDecoder, codec_id); CodecAudioOpen(MyAudioDecoder, NULL, codec_id);
AudioCodecID = codec_id; AudioCodecID = codec_id;
} }
av_init_packet(avpkt); av_init_packet(avpkt);
@ -1267,7 +1253,7 @@ int PlayTsAudio(const uint8_t * data, int size)
AudioFlushBuffers(); AudioFlushBuffers();
// max time between audio packets 200ms + 24ms hw buffer // max time between audio packets 200ms + 24ms hw buffer
AudioSetBufferTime(ConfigAudioBufferTime); AudioSetBufferTime(ConfigAudioBufferTime);
AudioCodecID = AV_CODEC_ID_NONE; AudioCodecID = CODEC_ID_NONE;
AudioChannelID = -1; AudioChannelID = -1;
NewAudioStream = 0; NewAudioStream = 0;
PesReset(PesDemuxAudio); PesReset(PesDemuxAudio);
@ -1299,19 +1285,12 @@ void SetVolumeDevice(int volume)
AudioSetVolume((volume * 1000) / 255); AudioSetVolume((volume * 1000) / 255);
} }
/**
*** Resets channel ID (restarts audio).
**/
void ResetChannelId(void)
{
AudioChannelID = -1;
Debug(3, "audio/demux: reset channel id\n");
}
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// Video // Video
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
#include <alsa/iatomic.h> // portable atomic_t
#define VIDEO_BUFFER_SIZE (512 * 1024) ///< video PES buffer default size #define VIDEO_BUFFER_SIZE (512 * 1024) ///< video PES buffer default size
#define VIDEO_PACKET_MAX 192 ///< max number of video packets #define VIDEO_PACKET_MAX 192 ///< max number of video packets
@ -1324,8 +1303,8 @@ struct __video_stream__
VideoDecoder *Decoder; ///< video decoder VideoDecoder *Decoder; ///< video decoder
pthread_mutex_t DecoderLockMutex; ///< video decoder lock mutex pthread_mutex_t DecoderLockMutex; ///< video decoder lock mutex
enum AVCodecID CodecID; ///< current codec id enum CodecID CodecID; ///< current codec id
enum AVCodecID LastCodecID; ///< last codec id enum CodecID LastCodecID; ///< last codec id
volatile char NewStream; ///< flag new video stream volatile char NewStream; ///< flag new video stream
volatile char ClosingStream; ///< flag closing video stream volatile char ClosingStream; ///< flag closing video stream
@ -1337,9 +1316,6 @@ struct __video_stream__
volatile char ClearBuffers; ///< command clear video buffers volatile char ClearBuffers; ///< command clear video buffers
volatile char ClearClose; ///< clear video buffers for close volatile char ClearClose; ///< clear video buffers for close
int InvalidPesCounter; ///< counter of invalid PES packets
enum AVCodecID CodecIDRb[VIDEO_PACKET_MAX]; ///< codec ids in ring buffer
AVPacket PacketRb[VIDEO_PACKET_MAX]; ///< PES packet ring buffer AVPacket PacketRb[VIDEO_PACKET_MAX]; ///< PES packet ring buffer
int StartCodeState; ///< last three bytes start code state int StartCodeState; ///< last three bytes start code state
@ -1466,9 +1442,9 @@ static void VideoResetPacket(VideoStream * stream)
stream->StartCodeState = 0; // reset start code state stream->StartCodeState = 0; // reset start code state
stream->CodecIDRb[stream->PacketWrite] = AV_CODEC_ID_NONE;
avpkt = &stream->PacketRb[stream->PacketWrite]; avpkt = &stream->PacketRb[stream->PacketWrite];
avpkt->stream_index = 0; avpkt->stream_index = 0;
avpkt->priv = NULL;
avpkt->pts = AV_NOPTS_VALUE; avpkt->pts = AV_NOPTS_VALUE;
avpkt->dts = AV_NOPTS_VALUE; avpkt->dts = AV_NOPTS_VALUE;
} }
@ -1485,7 +1461,7 @@ static void VideoNextPacket(VideoStream * stream, int codec_id)
avpkt = &stream->PacketRb[stream->PacketWrite]; avpkt = &stream->PacketRb[stream->PacketWrite];
if (!avpkt->stream_index) { // ignore empty packets if (!avpkt->stream_index) { // ignore empty packets
if (codec_id != AV_CODEC_ID_NONE) { if (codec_id != CODEC_ID_NONE) {
return; return;
} }
Debug(3, "video: possible stream change loss\n"); Debug(3, "video: possible stream change loss\n");
@ -1495,7 +1471,7 @@ static void VideoNextPacket(VideoStream * stream, int codec_id)
// no free slot available drop last packet // no free slot available drop last packet
Error(_("video: no empty slot in packet ringbuffer\n")); Error(_("video: no empty slot in packet ringbuffer\n"));
avpkt->stream_index = 0; avpkt->stream_index = 0;
if (codec_id == AV_CODEC_ID_NONE) { if (codec_id == CODEC_ID_NONE) {
Debug(3, "video: possible stream change loss\n"); Debug(3, "video: possible stream change loss\n");
} }
return; return;
@ -1503,7 +1479,7 @@ static void VideoNextPacket(VideoStream * stream, int codec_id)
// clear area for decoder, always enough space allocated // clear area for decoder, always enough space allocated
memset(avpkt->data + avpkt->stream_index, 0, FF_INPUT_BUFFER_PADDING_SIZE); memset(avpkt->data + avpkt->stream_index, 0, FF_INPUT_BUFFER_PADDING_SIZE);
stream->CodecIDRb[stream->PacketWrite] = codec_id; avpkt->priv = (void *)(size_t) codec_id;
//DumpH264(avpkt->data, avpkt->stream_index); //DumpH264(avpkt->data, avpkt->stream_index);
// advance packet write // advance packet write
@ -1563,7 +1539,7 @@ static void VideoMpegEnqueue(VideoStream * stream, int64_t pts,
fprintf(stderr, "last: %d start\n", stream->StartCodeState); fprintf(stderr, "last: %d start\n", stream->StartCodeState);
#endif #endif
stream->PacketRb[stream->PacketWrite].stream_index -= 3; stream->PacketRb[stream->PacketWrite].stream_index -= 3;
VideoNextPacket(stream, AV_CODEC_ID_MPEG2VIDEO); VideoNextPacket(stream, CODEC_ID_MPEG2VIDEO);
VideoEnqueue(stream, pts, startcode, 3); VideoEnqueue(stream, pts, startcode, 3);
first = p[0] == 0xb3; first = p[0] == 0xb3;
p++; p++;
@ -1580,7 +1556,7 @@ static void VideoMpegEnqueue(VideoStream * stream, int64_t pts,
fprintf(stderr, "last: %d start\n", stream->StartCodeState); fprintf(stderr, "last: %d start\n", stream->StartCodeState);
#endif #endif
stream->PacketRb[stream->PacketWrite].stream_index -= 2; stream->PacketRb[stream->PacketWrite].stream_index -= 2;
VideoNextPacket(stream, AV_CODEC_ID_MPEG2VIDEO); VideoNextPacket(stream, CODEC_ID_MPEG2VIDEO);
VideoEnqueue(stream, pts, startcode, 2); VideoEnqueue(stream, pts, startcode, 2);
first = p[1] == 0xb3; first = p[1] == 0xb3;
p += 2; p += 2;
@ -1597,7 +1573,7 @@ static void VideoMpegEnqueue(VideoStream * stream, int64_t pts,
fprintf(stderr, "last: %d start\n", stream->StartCodeState); fprintf(stderr, "last: %d start\n", stream->StartCodeState);
#endif #endif
stream->PacketRb[stream->PacketWrite].stream_index -= 1; stream->PacketRb[stream->PacketWrite].stream_index -= 1;
VideoNextPacket(stream, AV_CODEC_ID_MPEG2VIDEO); VideoNextPacket(stream, CODEC_ID_MPEG2VIDEO);
VideoEnqueue(stream, pts, startcode, 1); VideoEnqueue(stream, pts, startcode, 1);
first = p[2] == 0xb3; first = p[2] == 0xb3;
p += 3; p += 3;
@ -1630,7 +1606,7 @@ static void VideoMpegEnqueue(VideoStream * stream, int64_t pts,
*/ */
// first packet goes only upto picture header // first packet goes only upto picture header
VideoEnqueue(stream, pts, data, p - data); VideoEnqueue(stream, pts, data, p - data);
VideoNextPacket(stream, AV_CODEC_ID_MPEG2VIDEO); VideoNextPacket(stream, CODEC_ID_MPEG2VIDEO);
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "fix\r"); fprintf(stderr, "fix\r");
#endif #endif
@ -1749,41 +1725,23 @@ static void FixPacketForFFMpeg(VideoDecoder * vdecoder, AVPacket * avpkt)
#endif #endif
/**
** Open video stream.
**
** @param stream video stream
*/
static void VideoStreamOpen(VideoStream * stream)
{
stream->SkipStream = 1;
stream->CodecID = AV_CODEC_ID_NONE;
stream->LastCodecID = AV_CODEC_ID_NONE;
if ((stream->HwDecoder = VideoNewHwDecoder(stream))) {
stream->Decoder = CodecVideoNewDecoder(stream->HwDecoder);
VideoPacketInit(stream);
stream->SkipStream = 0;
}
}
/** /**
** Close video stream. ** Close video stream.
** **
** @param stream video stream ** @param stream video stream
** @param delhw flag delete hardware decoder
** **
** @note must be called from the video thread, otherwise xcb has a ** @note must be called from the video thread, othewise xcb has a
** deadlock. ** deadlock.
*/ */
static void VideoStreamClose(VideoStream * stream, int delhw) static void VideoStreamClose(VideoStream * stream)
{ {
// FIXME: use this function to close the main video stream!
stream->SkipStream = 1; stream->SkipStream = 1;
if (stream->Decoder) { if (stream->Decoder) {
VideoDecoder *decoder; VideoDecoder *decoder;
decoder = stream->Decoder; decoder = stream->Decoder;
// FIXME: remove this lock for main stream close // FIXME: this lock shouldn't be necessary now
pthread_mutex_lock(&stream->DecoderLockMutex); pthread_mutex_lock(&stream->DecoderLockMutex);
stream->Decoder = NULL; // lock read thread stream->Decoder = NULL; // lock read thread
pthread_mutex_unlock(&stream->DecoderLockMutex); pthread_mutex_unlock(&stream->DecoderLockMutex);
@ -1791,16 +1749,13 @@ static void VideoStreamClose(VideoStream * stream, int delhw)
CodecVideoDelDecoder(decoder); CodecVideoDelDecoder(decoder);
} }
if (stream->HwDecoder) { if (stream->HwDecoder) {
if (delhw) {
VideoDelHwDecoder(stream->HwDecoder); VideoDelHwDecoder(stream->HwDecoder);
}
stream->HwDecoder = NULL; stream->HwDecoder = NULL;
// FIXME: CodecVideoClose calls/uses hw decoder // FIXME: CodecVideoClose calls/uses hw decoder
} }
VideoPacketExit(stream); VideoPacketExit(stream);
stream->NewStream = 1; stream->NewStream = 1;
stream->InvalidPesCounter = 0;
} }
/** /**
@ -1823,14 +1778,13 @@ int VideoPollInput(VideoStream * stream)
} }
if (stream->Close) { // close stream request if (stream->Close) { // close stream request
VideoStreamClose(stream, 1); VideoStreamClose(stream);
stream->Close = 0; stream->Close = 0;
return 1; return 1;
} }
if (stream->ClearBuffers) { // clear buffer request if (stream->ClearBuffers) { // clear buffer request
atomic_set(&stream->PacketsFilled, 0); atomic_set(&stream->PacketsFilled, 0);
stream->PacketRead = stream->PacketWrite; stream->PacketRead = stream->PacketWrite;
// FIXME: ->Decoder already checked
if (stream->Decoder) { if (stream->Decoder) {
CodecVideoFlushBuffers(stream->Decoder); CodecVideoFlushBuffers(stream->Decoder);
VideoResetStart(stream->HwDecoder); VideoResetStart(stream->HwDecoder);
@ -1867,14 +1821,13 @@ int VideoDecodeInput(VideoStream * stream)
} }
if (stream->Close) { // close stream request if (stream->Close) { // close stream request
VideoStreamClose(stream, 1); VideoStreamClose(stream);
stream->Close = 0; stream->Close = 0;
return 1; return 1;
} }
if (stream->ClearBuffers) { // clear buffer request if (stream->ClearBuffers) { // clear buffer request
atomic_set(&stream->PacketsFilled, 0); atomic_set(&stream->PacketsFilled, 0);
stream->PacketRead = stream->PacketWrite; stream->PacketRead = stream->PacketWrite;
// FIXME: ->Decoder already checked
if (stream->Decoder) { if (stream->Decoder) {
CodecVideoFlushBuffers(stream->Decoder); CodecVideoFlushBuffers(stream->Decoder);
VideoResetStart(stream->HwDecoder); VideoResetStart(stream->HwDecoder);
@ -1900,8 +1853,9 @@ int VideoDecodeInput(VideoStream * stream)
// flush buffers, if close is in the queue // flush buffers, if close is in the queue
for (f = 0; f < filled; ++f) { for (f = 0; f < filled; ++f) {
if (stream->CodecIDRb[(stream->PacketRead + f) % VIDEO_PACKET_MAX] avpkt =
== AV_CODEC_ID_NONE) { &stream->PacketRb[(stream->PacketRead + f) % VIDEO_PACKET_MAX];
if ((int)(size_t) avpkt->priv == CODEC_ID_NONE) {
if (f) { if (f) {
Debug(3, "video: cleared upto close\n"); Debug(3, "video: cleared upto close\n");
atomic_sub(f, &stream->PacketsFilled); atomic_sub(f, &stream->PacketsFilled);
@ -1920,27 +1874,30 @@ int VideoDecodeInput(VideoStream * stream)
// handle queued commands // handle queued commands
// //
avpkt = &stream->PacketRb[stream->PacketRead]; avpkt = &stream->PacketRb[stream->PacketRead];
switch (stream->CodecIDRb[stream->PacketRead]) { switch ((int)(size_t) avpkt->priv) {
case AV_CODEC_ID_NONE: case CODEC_ID_NONE:
stream->ClosingStream = 0; stream->ClosingStream = 0;
if (stream->LastCodecID != AV_CODEC_ID_NONE) { if (stream->LastCodecID != CODEC_ID_NONE) {
stream->LastCodecID = AV_CODEC_ID_NONE; stream->LastCodecID = CODEC_ID_NONE;
CodecVideoClose(stream->Decoder); CodecVideoClose(stream->Decoder);
goto skip; goto skip;
} }
// FIXME: look if more close are in the queue // FIXME: look if more close are in the queue
// size can be zero // size can be zero
goto skip; goto skip;
case AV_CODEC_ID_MPEG2VIDEO: case CODEC_ID_MPEG2VIDEO:
if (stream->LastCodecID != AV_CODEC_ID_MPEG2VIDEO) { if (stream->LastCodecID != CODEC_ID_MPEG2VIDEO) {
stream->LastCodecID = AV_CODEC_ID_MPEG2VIDEO; stream->LastCodecID = CODEC_ID_MPEG2VIDEO;
CodecVideoOpen(stream->Decoder, AV_CODEC_ID_MPEG2VIDEO); CodecVideoOpen(stream->Decoder, VideoHardwareDecoder < 0
&& VdpauDecoder ? "mpegvideo_vdpau" : NULL,
CODEC_ID_MPEG2VIDEO);
} }
break; break;
case AV_CODEC_ID_H264: case CODEC_ID_H264:
if (stream->LastCodecID != AV_CODEC_ID_H264) { if (stream->LastCodecID != CODEC_ID_H264) {
stream->LastCodecID = AV_CODEC_ID_H264; stream->LastCodecID = CODEC_ID_H264;
CodecVideoOpen(stream->Decoder, AV_CODEC_ID_H264); CodecVideoOpen(stream->Decoder, VideoHardwareDecoder
&& VdpauDecoder ? "h264_vdpau" : NULL, CODEC_ID_H264);
} }
break; break;
default: default:
@ -1969,7 +1926,7 @@ int VideoDecodeInput(VideoStream * stream)
//fprintf(stderr, "]\n"); //fprintf(stderr, "]\n");
#else #else
// old version // old version
if (stream->LastCodecID == AV_CODEC_ID_MPEG2VIDEO) { if (stream->LastCodecID == CODEC_ID_MPEG2VIDEO) {
FixPacketForFFMpeg(stream->Decoder, avpkt); FixPacketForFFMpeg(stream->Decoder, avpkt);
} else { } else {
CodecVideoDecode(stream->Decoder, avpkt); CodecVideoDecode(stream->Decoder, avpkt);
@ -2004,6 +1961,9 @@ int VideoGetBuffers(const VideoStream * stream)
static void StartVideo(void) static void StartVideo(void)
{ {
VideoInit(X11DisplayName); VideoInit(X11DisplayName);
#ifdef USE_VDPAU
VdpauDecoder = !strcasecmp(VideoGetDriverName(), "vdpau");
#endif
if (ConfigFullscreen) { if (ConfigFullscreen) {
// FIXME: not good looking, mapped and then resized. // FIXME: not good looking, mapped and then resized.
@ -2011,8 +1971,17 @@ static void StartVideo(void)
} }
VideoOsdInit(); VideoOsdInit();
if (!MyVideoStream->Decoder) { if (!MyVideoStream->Decoder) {
VideoStreamOpen(MyVideoStream); MyVideoStream->SkipStream = 1;
MyVideoStream->CodecID = CODEC_ID_NONE;
MyVideoStream->LastCodecID = CODEC_ID_NONE;
if ((MyVideoStream->HwDecoder = VideoNewHwDecoder(MyVideoStream))) {
MyVideoStream->Decoder =
CodecVideoNewDecoder(MyVideoStream->HwDecoder);
VideoPacketInit(MyVideoStream);
AudioSyncStream = MyVideoStream; AudioSyncStream = MyVideoStream;
MyVideoStream->SkipStream = 0;
}
} }
} }
@ -2024,10 +1993,6 @@ static void StopVideo(void)
VideoOsdExit(); VideoOsdExit();
VideoExit(); VideoExit();
AudioSyncStream = NULL; AudioSyncStream = NULL;
#if 1
// FIXME: done by exit: VideoDelHwDecoder(MyVideoStream->HwDecoder);
VideoStreamClose(MyVideoStream, 0);
#else
MyVideoStream->SkipStream = 1; MyVideoStream->SkipStream = 1;
if (MyVideoStream->Decoder) { if (MyVideoStream->Decoder) {
VideoDecoder *decoder; VideoDecoder *decoder;
@ -2047,8 +2012,6 @@ static void StopVideo(void)
VideoPacketExit(MyVideoStream); VideoPacketExit(MyVideoStream);
MyVideoStream->NewStream = 1; MyVideoStream->NewStream = 1;
MyVideoStream->InvalidPesCounter = 0;
#endif
} }
#ifdef DEBUG #ifdef DEBUG
@ -2170,26 +2133,17 @@ int PlayVideo3(VideoStream * stream, const uint8_t * data, int size)
Debug(3, "video: new video stream lost\n"); Debug(3, "video: new video stream lost\n");
return 0; return 0;
} }
VideoNextPacket(stream, AV_CODEC_ID_NONE); VideoNextPacket(stream, CODEC_ID_NONE);
stream->CodecID = AV_CODEC_ID_NONE; stream->CodecID = CODEC_ID_NONE;
stream->ClosingStream = 1; stream->ClosingStream = 1;
stream->NewStream = 0; stream->NewStream = 0;
} }
// must be a PES start code // must be a PES start code
// FIXME: Valgrind-3.8.1 has a problem with this code // FIXME: Valgrind-3.8.1 has a problem with this code
if (size < 9 || !data || data[0] || data[1] || data[2] != 0x01) { if (size < 9 || !data || data[0] || data[1] || data[2] != 0x01) {
if (!stream->InvalidPesCounter++) {
Error(_("[softhddev] invalid PES video packet\n")); Error(_("[softhddev] invalid PES video packet\n"));
}
return size; return size;
} }
if (stream->InvalidPesCounter) {
if (stream->InvalidPesCounter > 1) {
Error(_("[softhddev] %d invalid PES video packet(s)\n"),
stream->InvalidPesCounter);
}
stream->InvalidPesCounter = 0;
}
// 0xBE, filler, padding stream // 0xBE, filler, padding stream
if (data[3] == PES_PADDING_STREAM) { // from DVD plugin if (data[3] == PES_PADDING_STREAM) { // from DVD plugin
return size; return size;
@ -2243,26 +2197,8 @@ int PlayVideo3(VideoStream * stream, const uint8_t * data, int size)
if ((data[6] & 0xC0) == 0x80 && z >= 2 && check[0] == 0x01 if ((data[6] & 0xC0) == 0x80 && z >= 2 && check[0] == 0x01
&& check[1] == 0x09 && !check[3] && !check[4]) { && check[1] == 0x09 && !check[3] && !check[4]) {
// old PES HDTV recording z == 2 -> stronger check! // old PES HDTV recording z == 2 -> stronger check!
if (stream->CodecID == AV_CODEC_ID_H264) { if (stream->CodecID == CODEC_ID_H264) {
#ifdef DUMP_TRICKSPEED #if 0
if (stream->TrickSpeed) {
char buf[1024];
int fd;
static int FrameCounter;
snprintf(buf, sizeof(buf), "frame_%06d_%08d.raw", getpid(),
FrameCounter++);
if ((fd =
open(buf, O_WRONLY | O_CLOEXEC | O_CREAT | O_TRUNC,
0666)) >= 0) {
if (write(fd, data + 9 + n, size - 9 - n)) {
// this construct is to remove the annoying warning
}
close(fd);
}
}
#endif
#ifdef H264_EOS_TRICKSPEED
// this should improve ffwd+frew, but produce crash in ffmpeg // this should improve ffwd+frew, but produce crash in ffmpeg
// with some streams // with some streams
if (stream->TrickSpeed && pts != (int64_t) AV_NOPTS_VALUE) { if (stream->TrickSpeed && pts != (int64_t) AV_NOPTS_VALUE) {
@ -2273,16 +2209,16 @@ int PlayVideo3(VideoStream * stream, const uint8_t * data, int size)
// 1-5=SLICE 6=SEI 7=SPS 8=PPS // 1-5=SLICE 6=SEI 7=SPS 8=PPS
// NAL SPS sequence parameter set // NAL SPS sequence parameter set
if ((check[7] & 0x1F) == 0x07) { if ((check[7] & 0x1F) == 0x07) {
VideoNextPacket(stream, AV_CODEC_ID_H264); VideoNextPacket(CODEC_ID_H264);
VideoEnqueue(stream, AV_NOPTS_VALUE, seq_end_h264, VideoEnqueue(AV_NOPTS_VALUE, seq_end_h264,
sizeof(seq_end_h264)); sizeof(seq_end_h264));
} }
} }
#endif #endif
VideoNextPacket(stream, AV_CODEC_ID_H264); VideoNextPacket(stream, CODEC_ID_H264);
} else { } else {
Debug(3, "video: h264 detected\n"); Debug(3, "video: h264 detected\n");
stream->CodecID = AV_CODEC_ID_H264; stream->CodecID = CODEC_ID_H264;
} }
// SKIP PES header (ffmpeg supports short start code) // SKIP PES header (ffmpeg supports short start code)
VideoEnqueue(stream, pts, check - 2, l + 2); VideoEnqueue(stream, pts, check - 2, l + 2);
@ -2290,11 +2226,11 @@ int PlayVideo3(VideoStream * stream, const uint8_t * data, int size)
} }
// PES start code 0x00 0x00 0x01 0x00|0xb3 // PES start code 0x00 0x00 0x01 0x00|0xb3
if (z > 1 && check[0] == 0x01 && (!check[1] || check[1] == 0xb3)) { if (z > 1 && check[0] == 0x01 && (!check[1] || check[1] == 0xb3)) {
if (stream->CodecID == AV_CODEC_ID_MPEG2VIDEO) { if (stream->CodecID == CODEC_ID_MPEG2VIDEO) {
VideoNextPacket(stream, AV_CODEC_ID_MPEG2VIDEO); VideoNextPacket(stream, CODEC_ID_MPEG2VIDEO);
} else { } else {
Debug(3, "video: mpeg2 detected ID %02x\n", check[3]); Debug(3, "video: mpeg2 detected ID %02x\n", check[3]);
stream->CodecID = AV_CODEC_ID_MPEG2VIDEO; stream->CodecID = CODEC_ID_MPEG2VIDEO;
} }
#ifdef noDEBUG // pip pes packet has no lenght #ifdef noDEBUG // pip pes packet has no lenght
if (ValidateMpeg(data, size)) { if (ValidateMpeg(data, size)) {
@ -2310,12 +2246,12 @@ int PlayVideo3(VideoStream * stream, const uint8_t * data, int size)
return size; return size;
} }
// this happens when vdr sends incomplete packets // this happens when vdr sends incomplete packets
if (stream->CodecID == AV_CODEC_ID_NONE) { if (stream->CodecID == CODEC_ID_NONE) {
Debug(3, "video: not detected\n"); Debug(3, "video: not detected\n");
return size; return size;
} }
#ifdef USE_PIP #ifdef USE_PIP
if (stream->CodecID == AV_CODEC_ID_MPEG2VIDEO) { if (stream->CodecID == CODEC_ID_MPEG2VIDEO) {
// SKIP PES header // SKIP PES header
VideoMpegEnqueue(stream, pts, data + 9 + n, size - 9 - n); VideoMpegEnqueue(stream, pts, data + 9 + n, size - 9 - n);
#ifndef USE_MPEG_COMPLETE #ifndef USE_MPEG_COMPLETE
@ -2339,10 +2275,10 @@ int PlayVideo3(VideoStream * stream, const uint8_t * data, int size)
// incomplete packets produce artefacts after channel switch // incomplete packets produce artefacts after channel switch
// packet < 65526 is the last split packet, detect it here for // packet < 65526 is the last split packet, detect it here for
// better latency // better latency
if (size < 65526 && stream->CodecID == AV_CODEC_ID_MPEG2VIDEO) { if (size < 65526 && stream->CodecID == CODEC_ID_MPEG2VIDEO) {
// mpeg codec supports incomplete packets // mpeg codec supports incomplete packets
// waiting for a full complete packages, increases needed delays // waiting for a full complete packages, increases needed delays
VideoNextPacket(stream, AV_CODEC_ID_MPEG2VIDEO); VideoNextPacket(stream, CODEC_ID_MPEG2VIDEO);
} }
#endif #endif
@ -2466,48 +2402,43 @@ uint8_t *GrabImage(int *size, int jpeg, int quality, int width, int height)
*/ */
int SetPlayMode(int play_mode) int SetPlayMode(int play_mode)
{ {
switch (play_mode) { VideoDisplayWakeup();
case 0: // audio/video from decoder if (MyVideoStream->Decoder) { // tell video parser we have new stream
// tell video parser we get new stream if (MyVideoStream->ClearClose) { // replay clear buffers on close
if (MyVideoStream->Decoder && !MyVideoStream->SkipStream) {
// clear buffers on close configured always or replay only
if (ConfigVideoClearOnSwitch || MyVideoStream->ClearClose) {
Clear(); // flush all buffers Clear(); // flush all buffers
MyVideoStream->ClearClose = 0; MyVideoStream->ClearClose = 0;
} }
if (MyVideoStream->CodecID != AV_CODEC_ID_NONE) { if (MyVideoStream->CodecID != CODEC_ID_NONE) {
MyVideoStream->NewStream = 1; MyVideoStream->NewStream = 1;
MyVideoStream->InvalidPesCounter = 0;
// tell hw decoder we are closing stream // tell hw decoder we are closing stream
VideoSetClosing(MyVideoStream->HwDecoder); VideoSetClosing(MyVideoStream->HwDecoder);
VideoResetStart(MyVideoStream->HwDecoder); VideoResetStart(MyVideoStream->HwDecoder);
#ifdef DEBUG #ifdef DEBUG
VideoSwitch = GetMsTicks(); VideoSwitch = GetMsTicks();
Debug(3, "video: new stream start\n");
#endif #endif
} }
} }
if (MyAudioDecoder) { // tell audio parser we have new stream if (MyAudioDecoder) { // tell audio parser we have new stream
if (AudioCodecID != AV_CODEC_ID_NONE) { if (AudioCodecID != CODEC_ID_NONE) {
NewAudioStream = 1; NewAudioStream = 1;
} }
} }
break; switch (play_mode) {
case 0: // nothing
case 1: // audio/video from player case 1: // audio/video from player
VideoDisplayWakeup();
Play();
break; break;
case 2: // audio only from player, video from decoder case 2: // audio only
case 3: // audio only from player, no video (black screen)
Debug(3, "softhddev: FIXME: audio only, silence video errors\n"); Debug(3, "softhddev: FIXME: audio only, silence video errors\n");
VideoDisplayWakeup();
Play();
break; break;
case 4: // video only from player, audio from decoder case 3: // audio only, black screen
VideoDisplayWakeup(); Debug(3, "softhddev: FIXME: audio only, silence video errors\n");
Play(); break;
case 4: // video only
break; break;
} }
Play();
return 1; return 1;
} }
@ -2591,10 +2522,8 @@ void Clear(void)
VideoResetPacket(MyVideoStream); // terminate work VideoResetPacket(MyVideoStream); // terminate work
MyVideoStream->ClearBuffers = 1; MyVideoStream->ClearBuffers = 1;
if (!SkipAudio) {
AudioFlushBuffers(); AudioFlushBuffers();
//NewAudioStream = 1; //NewAudioStream = 1;
}
// FIXME: audio avcodec_flush_buffers, video is done by VideoClearBuffers // FIXME: audio avcodec_flush_buffers, video is done by VideoClearBuffers
// wait for empty buffers // wait for empty buffers
@ -2650,10 +2579,6 @@ void StillPicture(const uint8_t * data, int size)
int i; int i;
int old_video_hardware_decoder; int old_video_hardware_decoder;
// might be called in Suspended Mode
if (!MyVideoStream->Decoder || MyVideoStream->SkipStream) {
return;
}
// must be a PES start code // must be a PES start code
if (size < 9 || !data || data[0] || data[1] || data[2] != 0x01) { if (size < 9 || !data || data[0] || data[1] || data[2] != 0x01) {
Error(_("[softhddev] invalid still video packet\n")); Error(_("[softhddev] invalid still video packet\n"));
@ -2668,10 +2593,10 @@ void StillPicture(const uint8_t * data, int size)
// enable/disable hardware decoder for still picture // enable/disable hardware decoder for still picture
if (VideoHardwareDecoder != ConfigStillDecoder) { if (VideoHardwareDecoder != ConfigStillDecoder) {
VideoHardwareDecoder = ConfigStillDecoder; VideoHardwareDecoder = ConfigStillDecoder;
VideoNextPacket(MyVideoStream, AV_CODEC_ID_NONE); // close last stream VideoNextPacket(MyVideoStream, CODEC_ID_NONE); // close last stream
} }
if (MyVideoStream->CodecID == AV_CODEC_ID_NONE) { if (MyVideoStream->CodecID == CODEC_ID_NONE) {
// FIXME: should detect codec, see PlayVideo // FIXME: should detect codec, see PlayVideo
Error(_("[softhddev] no codec known for still picture\n")); Error(_("[softhddev] no codec known for still picture\n"));
} }
@ -2680,7 +2605,7 @@ void StillPicture(const uint8_t * data, int size)
#ifdef STILL_DEBUG #ifdef STILL_DEBUG
fprintf(stderr, "still-picture\n"); fprintf(stderr, "still-picture\n");
#endif #endif
for (i = 0; i < (MyVideoStream->CodecID == AV_CODEC_ID_MPEG2VIDEO ? 4 : 4); for (i = 0; i < (MyVideoStream->CodecID == CODEC_ID_MPEG2VIDEO ? 4 : 4);
++i) { ++i) {
const uint8_t *split; const uint8_t *split;
int n; int n;
@ -2720,13 +2645,13 @@ void StillPicture(const uint8_t * data, int size)
VideoNextPacket(MyVideoStream, MyVideoStream->CodecID); // terminate last packet VideoNextPacket(MyVideoStream, MyVideoStream->CodecID); // terminate last packet
} else { // ES packet } else { // ES packet
if (MyVideoStream->CodecID != AV_CODEC_ID_MPEG2VIDEO) { if (MyVideoStream->CodecID != CODEC_ID_MPEG2VIDEO) {
VideoNextPacket(MyVideoStream, AV_CODEC_ID_NONE); // close last stream VideoNextPacket(MyVideoStream, CODEC_ID_NONE); // close last stream
MyVideoStream->CodecID = AV_CODEC_ID_MPEG2VIDEO; MyVideoStream->CodecID = CODEC_ID_MPEG2VIDEO;
} }
VideoEnqueue(MyVideoStream, AV_NOPTS_VALUE, data, size); VideoEnqueue(MyVideoStream, AV_NOPTS_VALUE, data, size);
} }
if (MyVideoStream->CodecID == AV_CODEC_ID_H264) { if (MyVideoStream->CodecID == CODEC_ID_H264) {
VideoEnqueue(MyVideoStream, AV_NOPTS_VALUE, seq_end_h264, VideoEnqueue(MyVideoStream, AV_NOPTS_VALUE, seq_end_h264,
sizeof(seq_end_h264)); sizeof(seq_end_h264));
} else { } else {
@ -2747,7 +2672,7 @@ void StillPicture(const uint8_t * data, int size)
#endif #endif
if (VideoHardwareDecoder != old_video_hardware_decoder) { if (VideoHardwareDecoder != old_video_hardware_decoder) {
VideoHardwareDecoder = old_video_hardware_decoder; VideoHardwareDecoder = old_video_hardware_decoder;
VideoNextPacket(MyVideoStream, AV_CODEC_ID_NONE); // close last stream VideoNextPacket(MyVideoStream, CODEC_ID_NONE); // close last stream
} }
VideoSetTrickSpeed(MyVideoStream->HwDecoder, 0); VideoSetTrickSpeed(MyVideoStream->HwDecoder, 0);
} }
@ -2854,21 +2779,17 @@ void OsdClose(void)
/** /**
** Draw an OSD pixmap. ** Draw an OSD pixmap.
** **
** @param xi x-coordinate in argb image
** @param yi y-coordinate in argb image
** @paran height height in pixel in argb image
** @paran width width in pixel in argb image
** @param pitch pitch of argb image
** @param argb 32bit ARGB image data
** @param x x-coordinate on screen of argb image ** @param x x-coordinate on screen of argb image
** @param y y-coordinate on screen of argb image ** @param y y-coordinate on screen of argb image
** @paran height height in pixel of argb image
** @paran width width in pixel of argb image
** @param argb height * width 32bit ARGB image data
*/ */
void OsdDrawARGB(int xi, int yi, int height, int width, int pitch, void OsdDrawARGB(int x, int y, int height, int width, const uint8_t * argb)
const uint8_t * argb, int x, int y)
{ {
// wakeup display for showing remote learning dialog // wakeup display for showing remote learning dialog
VideoDisplayWakeup(); VideoDisplayWakeup();
VideoOsdDrawARGB(xi, yi, height, width, pitch, argb, x, y); VideoOsdDrawARGB(x, y, height, width, argb);
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -2894,10 +2815,7 @@ const char *CommandLineHelp(void)
"\tstill-hw-decoder\tenable hardware decoder for still-pictures\n" "\tstill-hw-decoder\tenable hardware decoder for still-pictures\n"
"\tstill-h264-hw-decoder\tenable h264 hw decoder for still-pictures\n" "\tstill-h264-hw-decoder\tenable h264 hw decoder for still-pictures\n"
"\talsa-driver-broken\tdisable broken alsa driver message\n" "\talsa-driver-broken\tdisable broken alsa driver message\n"
"\talsa-no-close-open\tdisable close open to fix alsa no sound bug\n"
"\talsa-close-open-delay\tenable close open delay to fix no sound bug\n"
"\tignore-repeat-pict\tdisable repeat pict message\n" "\tignore-repeat-pict\tdisable repeat pict message\n"
"\tuse-possible-defect-frames prefer faster channel switch\n"
" -D\t\tstart in detached mode\n"; " -D\t\tstart in detached mode\n";
} }
@ -2973,14 +2891,8 @@ int ProcessArgs(int argc, char *const argv[])
ConfigStillDecoder = 1; ConfigStillDecoder = 1;
} else if (!strcasecmp("alsa-driver-broken", optarg)) { } else if (!strcasecmp("alsa-driver-broken", optarg)) {
AudioAlsaDriverBroken = 1; AudioAlsaDriverBroken = 1;
} else if (!strcasecmp("alsa-no-close-open", optarg)) {
AudioAlsaNoCloseOpen = 1;
} else if (!strcasecmp("alsa-close-open-delay", optarg)) {
AudioAlsaCloseOpenDelay = 1;
} else if (!strcasecmp("ignore-repeat-pict", optarg)) { } else if (!strcasecmp("ignore-repeat-pict", optarg)) {
VideoIgnoreRepeatPict = 1; VideoIgnoreRepeatPict = 1;
} else if (!strcasecmp("use-possible-defect-frames", optarg)) {
CodecUsePossibleDefectFrames = 1;
} else { } else {
fprintf(stderr, _("Workaround '%s' unsupported\n"), fprintf(stderr, _("Workaround '%s' unsupported\n"),
optarg); optarg);
@ -3097,7 +3009,7 @@ static void StartXServer(void)
Debug(3, "x-setup: Starting X server '%s' '%s'\n", args[0], Debug(3, "x-setup: Starting X server '%s' '%s'\n", args[0],
X11ServerArguments); X11ServerArguments);
// fork // fork
if ((pid = fork())) { // parent if ((pid = vfork())) { // parent
X11ServerPid = pid; X11ServerPid = pid;
Debug(3, "x-setup: Started x-server pid=%d\n", X11ServerPid); Debug(3, "x-setup: Started x-server pid=%d\n", X11ServerPid);
@ -3210,7 +3122,7 @@ int Start(void)
AudioInit(); AudioInit();
av_new_packet(AudioAvPkt, AUDIO_BUFFER_SIZE); av_new_packet(AudioAvPkt, AUDIO_BUFFER_SIZE);
MyAudioDecoder = CodecAudioNewDecoder(); MyAudioDecoder = CodecAudioNewDecoder();
AudioCodecID = AV_CODEC_ID_NONE; AudioCodecID = CODEC_ID_NONE;
AudioChannelID = -1; AudioChannelID = -1;
if (!ConfigStartX11Server) { if (!ConfigStartX11Server) {
@ -3317,8 +3229,6 @@ void Suspend(int video, int audio, int dox11)
DelPip(); // must stop PIP DelPip(); // must stop PIP
#endif #endif
// FIXME: should not be correct, if not both are suspended!
// Move down into if (video) ...
MyVideoStream->SkipStream = 1; MyVideoStream->SkipStream = 1;
SkipAudio = 1; SkipAudio = 1;
@ -3365,7 +3275,7 @@ void Resume(void)
AudioInit(); AudioInit();
av_new_packet(AudioAvPkt, AUDIO_BUFFER_SIZE); av_new_packet(AudioAvPkt, AUDIO_BUFFER_SIZE);
MyAudioDecoder = CodecAudioNewDecoder(); MyAudioDecoder = CodecAudioNewDecoder();
AudioCodecID = AV_CODEC_ID_NONE; AudioCodecID = CODEC_ID_NONE;
AudioChannelID = -1; AudioChannelID = -1;
} }
@ -3465,7 +3375,16 @@ void PipStart(int x, int y, int width, int height, int pip_x, int pip_y,
} }
if (!PipVideoStream->Decoder) { if (!PipVideoStream->Decoder) {
VideoStreamOpen(PipVideoStream); PipVideoStream->SkipStream = 1;
PipVideoStream->CodecID = CODEC_ID_NONE;
PipVideoStream->LastCodecID = CODEC_ID_NONE;
if ((PipVideoStream->HwDecoder = VideoNewHwDecoder(PipVideoStream))) {
PipVideoStream->Decoder =
CodecVideoNewDecoder(PipVideoStream->HwDecoder);
VideoPacketInit(PipVideoStream);
PipVideoStream->SkipStream = 0;
}
} }
PipSetPosition(x, y, width, height, pip_x, pip_y, pip_width, pip_height); PipSetPosition(x, y, width, height, pip_x, pip_y, pip_width, pip_height);
} }
@ -3483,11 +3402,33 @@ void PipStop(void)
ScaleVideo(0, 0, 0, 0); ScaleVideo(0, 0, 0, 0);
#if 0
PipVideoStream->SkipStream = 1; // lock write thread
if (PipVideoStream->Decoder) {
VideoDecoder *decoder;
decoder = PipVideoStream->Decoder;
pthread_mutex_lock(&PipVideoStream->DecoderLockMutex);
PipVideoStream->Decoder = NULL; // lock read thread
pthread_mutex_unlock(&PipVideoStream->DecoderLockMutex);
CodecVideoClose(decoder);
CodecVideoDelDecoder(decoder);
}
if (PipVideoStream->HwDecoder) {
VideoDelHwDecoder(PipVideoStream->HwDecoder);
PipVideoStream->HwDecoder = NULL;
// FIXME: CodecVideoClose calls/uses hw decoder
}
VideoPacketExit(PipVideoStream);
PipVideoStream->NewStream = 1;
#else
PipVideoStream->Close = 1; PipVideoStream->Close = 1;
for (i = 0; PipVideoStream->Close && i < 50; ++i) { for (i = 0; PipVideoStream->Close && i < 50; ++i) {
usleep(1 * 1000); usleep(1 * 1000);
} }
Info("[softhddev]%s: pip close %dms\n", __FUNCTION__, i); Info("[softhddev]%s: pip close %dms\n", __FUNCTION__, i);
#endif
} }
/** /**

View File

@ -1,7 +1,7 @@
/// ///
/// @file softhddev.h @brief software HD device plugin header file. /// @file softhddev.h @brief software HD device plugin header file.
/// ///
/// Copyright (c) 2011 - 2015 by Johns. All Rights Reserved. /// Copyright (c) 2011 - 2013 by Johns. All Rights Reserved.
/// ///
/// Contributor(s): /// Contributor(s):
/// ///
@ -25,8 +25,7 @@ extern "C"
{ {
#endif #endif
/// C callback feed key press /// C callback feed key press
extern void FeedKeyPress(const char *, const char *, int, int, extern void FeedKeyPress(const char *, const char *, int, int);
const char *);
/// C plugin get osd size and ascpect /// C plugin get osd size and ascpect
extern void GetOsdSize(int *, int *, double *); extern void GetOsdSize(int *, int *, double *);
@ -34,8 +33,7 @@ extern "C"
/// C plugin close osd /// C plugin close osd
extern void OsdClose(void); extern void OsdClose(void);
/// C plugin draw osd pixmap /// C plugin draw osd pixmap
extern void OsdDrawARGB(int, int, int, int, int, const uint8_t *, int, extern void OsdDrawARGB(int, int, int, int, const uint8_t *);
int);
/// C plugin play audio packet /// C plugin play audio packet
extern int PlayAudio(const uint8_t *, int, uint8_t); extern int PlayAudio(const uint8_t *, int, uint8_t);
@ -43,8 +41,6 @@ extern "C"
extern int PlayTsAudio(const uint8_t *, int); extern int PlayTsAudio(const uint8_t *, int);
/// C plugin set audio volume /// C plugin set audio volume
extern void SetVolumeDevice(int); extern void SetVolumeDevice(int);
/// C plugin reset channel id (restarts audio)
extern void ResetChannelId(void);
/// C plugin play video packet /// C plugin play video packet
extern int PlayVideo(const uint8_t *, int); extern int PlayVideo(const uint8_t *, int);

View File

@ -1,7 +1,7 @@
/// ///
/// @file softhddevice.cpp @brief A software HD device plugin for VDR. /// @file softhddevice.cpp @brief A software HD device plugin for VDR.
/// ///
/// Copyright (c) 2011 - 2015 by Johns. All Rights Reserved. /// Copyright (c) 2011 - 2013 by Johns. All Rights Reserved.
/// ///
/// Contributor(s): /// Contributor(s):
/// ///
@ -47,19 +47,12 @@ extern "C"
#include "codec.h" #include "codec.h"
} }
#if APIVERSNUM >= 20301
#define MURKS ->
#else
#define MURKS .
#define LOCK_CHANNELS_READ do { } while (0)
#endif
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
/// vdr-plugin version number. /// vdr-plugin version number.
/// Makefile extracts the version number for generating the file name /// Makefile extracts the version number for generating the file name
/// for the distribution archive. /// for the distribution archive.
static const char *const VERSION = "0.6.1rc1" static const char *const VERSION = "0.6.0"
#ifdef GIT_REV #ifdef GIT_REV
"-GIT" GIT_REV "-GIT" GIT_REV
#endif #endif
@ -86,7 +79,6 @@ static const char *const Resolution[RESOLUTIONS] = {
static char ConfigMakePrimary; ///< config primary wanted static char ConfigMakePrimary; ///< config primary wanted
static char ConfigHideMainMenuEntry; ///< config hide main menu entry static char ConfigHideMainMenuEntry; ///< config hide main menu entry
static char ConfigDetachFromMainMenu; ///< detach from main menu entry instead of suspend
static char ConfigSuspendClose; ///< suspend should close devices static char ConfigSuspendClose; ///< suspend should close devices
static char ConfigSuspendX11; ///< suspend should stop x11 static char ConfigSuspendX11; ///< suspend should stop x11
@ -99,7 +91,6 @@ static char ConfigVideoStudioLevels; ///< config use studio levels
static char ConfigVideo60HzMode; ///< config use 60Hz display mode static char ConfigVideo60HzMode; ///< config use 60Hz display mode
static char ConfigVideoSoftStartSync; ///< config use softstart sync static char ConfigVideoSoftStartSync; ///< config use softstart sync
static char ConfigVideoBlackPicture; ///< config enable black picture mode static char ConfigVideoBlackPicture; ///< config enable black picture mode
char ConfigVideoClearOnSwitch; ///< config enable Clear on channel switch
static int ConfigVideoBrightness; ///< config video brightness static int ConfigVideoBrightness; ///< config video brightness
static int ConfigVideoContrast = 1000; ///< config video contrast static int ConfigVideoContrast = 1000; ///< config video contrast
@ -147,7 +138,6 @@ static char ConfigAudioCompression; ///< config use volume compression
static int ConfigAudioMaxCompression; ///< config max volume compression static int ConfigAudioMaxCompression; ///< config max volume compression
static int ConfigAudioStereoDescent; ///< config reduce stereo loudness static int ConfigAudioStereoDescent; ///< config reduce stereo loudness
int ConfigAudioBufferTime; ///< config size ms of audio buffer int ConfigAudioBufferTime; ///< config size ms of audio buffer
static int ConfigAudioAutoAES; ///< config automatic AES handling
static char *ConfigX11Display; ///< config x11 display static char *ConfigX11Display; ///< config x11 display
static char *ConfigAudioDevice; ///< config audio stereo device static char *ConfigAudioDevice; ///< config audio stereo device
@ -172,17 +162,13 @@ static int ConfigPipAltVideoWidth; ///< config pip alt. video width in %
static int ConfigPipAltVideoHeight = 50; ///< config pip alt. video height in % static int ConfigPipAltVideoHeight = 50; ///< config pip alt. video height in %
#endif #endif
#ifdef USE_SCREENSAVER
static char ConfigEnableDPMSatBlackScreen; ///< Enable DPMS(Screensaver) while displaying black screen(radio)
#endif
static volatile int DoMakePrimary; ///< switch primary device to this static volatile int DoMakePrimary; ///< switch primary device to this
#define SUSPEND_EXTERNAL -1 ///< play external suspend mode #define SUSPEND_EXTERNAL -1 ///< play external suspend mode
#define NOT_SUSPENDED 0 ///< not suspend mode #define NOT_SUSPENDED 0 ///< not suspend mode
#define SUSPEND_NORMAL 1 ///< normal suspend mode #define SUSPEND_NORMAL 1 ///< normal suspend mode
#define SUSPEND_DETACHED 2 ///< detached suspend mode #define SUSPEND_DETACHED 2 ///< detached suspend mode
static signed char SuspendMode; ///< suspend mode static char SuspendMode; ///< suspend mode
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -225,10 +211,9 @@ class cSoftRemote:public cRemote
** @param key pressed/released key name ** @param key pressed/released key name
** @param repeat repeated key flag ** @param repeat repeated key flag
** @param release released key flag ** @param release released key flag
** @param letter x11 character string (system setting locale)
*/ */
extern "C" void FeedKeyPress(const char *keymap, const char *key, int repeat, extern "C" void FeedKeyPress(const char *keymap, const char *key, int repeat,
int release, const char *letter) int release)
{ {
cRemote *remote; cRemote *remote;
cSoftRemote *csoft; cSoftRemote *csoft;
@ -251,18 +236,9 @@ extern "C" void FeedKeyPress(const char *keymap, const char *key, int repeat,
csoft = new cSoftRemote(keymap); csoft = new cSoftRemote(keymap);
} }
//dsyslog("[softhddev]%s %s, %s, %s\n", __FUNCTION__, keymap, key, letter); //dsyslog("[softhddev]%s %s, %s\n", __FUNCTION__, keymap, key);
if (key[1]) { // no single character if (key[1]) { // no single character
if (!csoft->Put(key, repeat, release) && letter csoft->Put(key, repeat, release);
&& !cRemote::IsLearning()) {
cCharSetConv conv;
unsigned code;
code = Utf8CharGet(conv.Convert(letter));
if (code <= 0xFF) {
cRemote::Put(KBDKEY(code)); // feed it for edit mode
}
}
} else if (!csoft->Put(key, repeat, release)) { } else if (!csoft->Put(key, repeat, release)) {
cRemote::Put(KBDKEY(key[0])); // feed it for edit mode cRemote::Put(KBDKEY(key[0])); // feed it for edit mode
} }
@ -279,12 +255,10 @@ class cSoftOsd:public cOsd
{ {
public: public:
static volatile char Dirty; ///< flag force redraw everything static volatile char Dirty; ///< flag force redraw everything
int OsdLevel; ///< current osd level FIXME: remove int OsdLevel; ///< current osd level
cSoftOsd(int, int, uint); ///< osd constructor cSoftOsd(int, int, uint); ///< osd constructor
virtual ~ cSoftOsd(void); ///< osd destructor virtual ~ cSoftOsd(void); ///< osd destructor
/// set the sub-areas to the given areas
virtual eOsdError SetAreas(const tArea *, int);
virtual void Flush(void); ///< commits all data to the hardware virtual void Flush(void); ///< commits all data to the hardware
virtual void SetActive(bool); ///< sets OSD to be the active one virtual void SetActive(bool); ///< sets OSD to be the active one
}; };
@ -310,6 +284,11 @@ void cSoftOsd::SetActive(bool on)
} }
cOsd::SetActive(on); cOsd::SetActive(on);
// ignore sub-title if menu is open
if (OsdLevel >= OSD_LEVEL_SUBTITLES && IsOpen()) {
return;
}
if (on) { if (on) {
Dirty = 1; Dirty = 1;
// only flush here if there are already bitmaps // only flush here if there are already bitmaps
@ -341,6 +320,7 @@ cSoftOsd::cSoftOsd(int left, int top, uint level)
#endif #endif
OsdLevel = level; OsdLevel = level;
SetActive(true);
} }
/** /**
@ -371,31 +351,6 @@ cSoftOsd::~cSoftOsd(void)
#endif #endif
} }
/**
+* Set the sub-areas to the given areas
*/
eOsdError cSoftOsd::SetAreas(const tArea * areas, int n)
{
#ifdef OSD_DEBUG
dsyslog("[softhddev]%s: %d areas \n", __FUNCTION__, n);
#endif
// clear old OSD, when new areas are set
if (!IsTrueColor()) {
cBitmap *bitmap;
int i;
for (i = 0; (bitmap = GetBitmap(i)); i++) {
bitmap->Clean();
}
}
if (Active()) {
VideoOsdClear();
Dirty = 1;
}
return cOsd::SetAreas(areas, n);
}
/** /**
** Actually commits all data to the OSD hardware. ** Actually commits all data to the OSD hardware.
*/ */
@ -411,6 +366,10 @@ void cSoftOsd::Flush(void)
if (!Active()) { // this osd is not active if (!Active()) { // this osd is not active
return; return;
} }
// don't draw sub-title if menu is active
if (OsdLevel >= OSD_LEVEL_SUBTITLES && IsOpen()) {
return;
}
#ifdef USE_YAEPG #ifdef USE_YAEPG
// support yaepghd, video window // support yaepghd, video window
if (vidWin.bpp) { if (vidWin.bpp) {
@ -426,6 +385,17 @@ void cSoftOsd::Flush(void)
} }
#endif #endif
//
// VDR draws subtitle without clearing the old
//
if (OsdLevel >= OSD_LEVEL_SUBTITLES) {
VideoOsdClear();
cSoftOsd::Dirty = 1;
#ifdef OSD_DEBUG
dsyslog("[softhddev]%s: subtitle clear\n", __FUNCTION__);
#endif
}
if (!IsTrueColor()) { if (!IsTrueColor()) {
cBitmap *bitmap; cBitmap *bitmap;
int i; int i;
@ -442,8 +412,6 @@ void cSoftOsd::Flush(void)
// draw all bitmaps // draw all bitmaps
for (i = 0; (bitmap = GetBitmap(i)); ++i) { for (i = 0; (bitmap = GetBitmap(i)); ++i) {
uint8_t *argb; uint8_t *argb;
int xs;
int ys;
int x; int x;
int y; int y;
int w; int w;
@ -462,52 +430,22 @@ void cSoftOsd::Flush(void)
} else if (!bitmap->Dirty(x1, y1, x2, y2)) { } else if (!bitmap->Dirty(x1, y1, x2, y2)) {
continue; // nothing dirty continue continue; // nothing dirty continue
} }
// convert and upload only visible dirty areas // convert and upload only dirty areas
xs = bitmap->X0() + Left();
ys = bitmap->Y0() + Top();
// FIXME: negtative position bitmaps
w = x2 - x1 + 1; w = x2 - x1 + 1;
h = y2 - y1 + 1; h = y2 - y1 + 1;
// clip to screen
if (1) { // just for the case it makes trouble if (1) { // just for the case it makes trouble
int width; int width;
int height; int height;
double video_aspect; double video_aspect;
if (xs < 0) {
if (xs + x1 < 0) {
x1 -= xs + x1;
w += xs + x1;
if (w <= 0) {
continue;
}
}
xs = 0;
}
if (ys < 0) {
if (ys + y1 < 0) {
y1 -= ys + y1;
h += ys + y1;
if (h <= 0) {
continue;
}
}
ys = 0;
}
::GetOsdSize(&width, &height, &video_aspect); ::GetOsdSize(&width, &height, &video_aspect);
if (w > width - xs - x1) { if (w > width) {
w = width - xs - x1; w = width;
if (w <= 0) { x2 = x1 + width - 1;
continue;
} }
x2 = x1 + w - 1; if (h > height) {
} h = height;
if (h > height - ys - y1) { y2 = y1 + height - 1;
h = height - ys - y1;
if (h <= 0) {
continue;
}
y2 = y1 + h - 1;
} }
} }
#ifdef DEBUG #ifdef DEBUG
@ -525,99 +463,40 @@ void cSoftOsd::Flush(void)
} }
#ifdef OSD_DEBUG #ifdef OSD_DEBUG
dsyslog("[softhddev]%s: draw %dx%d%+d%+d bm\n", __FUNCTION__, w, h, dsyslog("[softhddev]%s: draw %dx%d%+d%+d bm\n", __FUNCTION__, w, h,
xs + x1, ys + y1); Left() + bitmap->X0() + x1, Top() + bitmap->Y0() + y1);
#endif #endif
OsdDrawARGB(0, 0, w, h, w * sizeof(uint32_t), argb, xs + x1, OsdDrawARGB(Left() + bitmap->X0() + x1, Top() + bitmap->Y0() + y1,
ys + y1); w, h, argb);
bitmap->Clean(); bitmap->Clean();
// FIXME: reuse argb // FIXME: reuse argb
free(argb); free(argb);
} }
Dirty = 0; cSoftOsd::Dirty = 0;
return; return;
} }
LOCK_PIXMAPS; LOCK_PIXMAPS;
while ((pm = (dynamic_cast < cPixmapMemory * >(RenderPixmaps())))) { while ((pm = RenderPixmaps())) {
int xp;
int yp;
int stride;
int x; int x;
int y; int y;
int w; int w;
int h; int h;
x = pm->ViewPort().X(); x = Left() + pm->ViewPort().X();
y = pm->ViewPort().Y(); y = Top() + pm->ViewPort().Y();
w = pm->ViewPort().Width(); w = pm->ViewPort().Width();
h = pm->ViewPort().Height(); h = pm->ViewPort().Height();
stride = w * sizeof(tColor);
// clip to osd
xp = 0;
if (x < 0) {
xp = -x;
w -= xp;
x = 0;
}
yp = 0;
if (y < 0) {
yp = -y;
h -= yp;
y = 0;
}
if (w > Width() - x) {
w = Width() - x;
}
if (h > Height() - y) {
h = Height() - y;
}
x += Left();
y += Top();
// clip to screen
if (1) { // just for the case it makes trouble
// and it can happen!
int width;
int height;
double video_aspect;
if (x < 0) {
w += x;
xp += -x;
x = 0;
}
if (y < 0) {
h += y;
yp += -y;
y = 0;
}
::GetOsdSize(&width, &height, &video_aspect);
if (w > width - x) {
w = width - x;
}
if (h > height - y) {
h = height - y;
}
}
#ifdef OSD_DEBUG #ifdef OSD_DEBUG
dsyslog("[softhddev]%s: draw %dx%d%+d%+d*%d -> %+d%+d %p\n", dsyslog("[softhddev]%s: draw %dx%d%+d%+d %p\n", __FUNCTION__, w, h, x,
__FUNCTION__, w, h, xp, yp, stride, x, y, pm->Data()); y, pm->Data());
#endif #endif
OsdDrawARGB(xp, yp, w, h, stride, pm->Data(), x, y); OsdDrawARGB(x, y, w, h, pm->Data());
#if APIVERSNUM >= 20110
DestroyPixmap(pm);
#else
delete pm; delete pm;
#endif
} }
Dirty = 0; cSoftOsd::Dirty = 0;
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -701,7 +580,6 @@ class cMenuSetupSoft:public cMenuSetupPage
int General; int General;
int MakePrimary; int MakePrimary;
int HideMainMenuEntry; int HideMainMenuEntry;
int DetachFromMainMenu;
int OsdSize; int OsdSize;
int OsdWidth; int OsdWidth;
int OsdHeight; int OsdHeight;
@ -717,7 +595,6 @@ class cMenuSetupSoft:public cMenuSetupPage
int _60HzMode; int _60HzMode;
int SoftStartSync; int SoftStartSync;
int BlackPicture; int BlackPicture;
int ClearOnSwitch;
int Brightness; int Brightness;
int Contrast; int Contrast;
@ -753,7 +630,6 @@ class cMenuSetupSoft:public cMenuSetupPage
int AudioMaxCompression; int AudioMaxCompression;
int AudioStereoDescent; int AudioStereoDescent;
int AudioBufferTime; int AudioBufferTime;
int AudioAutoAES;
#ifdef USE_PIP #ifdef USE_PIP
int Pip; int Pip;
@ -775,9 +651,6 @@ class cMenuSetupSoft:public cMenuSetupPage
int PipAltVideoHeight; int PipAltVideoHeight;
#endif #endif
#ifdef USE_SCREENSAVER
int EnableDPMSatBlackScreen;
#endif
/// @} /// @}
private: private:
inline cOsdItem * CollapsedItem(const char *, int &, const char * = NULL); inline cOsdItem * CollapsedItem(const char *, int &, const char * = NULL);
@ -884,8 +757,6 @@ void cMenuSetupSoft::Create(void)
// suspend // suspend
// //
Add(SeparatorItem(tr("Suspend"))); Add(SeparatorItem(tr("Suspend")));
Add(new cMenuEditBoolItem(tr("Detach from main menu entry"),
&DetachFromMainMenu, trVDR("no"), trVDR("yes")));
Add(new cMenuEditBoolItem(tr("Suspend closes video+audio"), Add(new cMenuEditBoolItem(tr("Suspend closes video+audio"),
&SuspendClose, trVDR("no"), trVDR("yes"))); &SuspendClose, trVDR("no"), trVDR("yes")));
Add(new cMenuEditBoolItem(tr("Suspend stops x11"), &SuspendX11, Add(new cMenuEditBoolItem(tr("Suspend stops x11"), &SuspendX11,
@ -896,11 +767,6 @@ void cMenuSetupSoft::Create(void)
// //
Add(CollapsedItem(tr("Video"), Video)); Add(CollapsedItem(tr("Video"), Video));
if (Video) { if (Video) {
#ifdef USE_SCREENSAVER
Add(new
cMenuEditBoolItem(tr("Enable Screensaver(DPMS) at black screen"),
&EnableDPMSatBlackScreen, trVDR("no"), trVDR("yes")));
#endif
Add(new cMenuEditStraItem(trVDR("4:3 video display format"), Add(new cMenuEditStraItem(trVDR("4:3 video display format"),
&Video4to3DisplayFormat, 3, video_display_formats_4_3)); &Video4to3DisplayFormat, 3, video_display_formats_4_3));
Add(new cMenuEditStraItem(trVDR("16:9+other video display format"), Add(new cMenuEditStraItem(trVDR("16:9+other video display format"),
@ -919,8 +785,6 @@ void cMenuSetupSoft::Create(void)
trVDR("no"), trVDR("yes"))); trVDR("no"), trVDR("yes")));
Add(new cMenuEditBoolItem(tr("Black during channel switch"), Add(new cMenuEditBoolItem(tr("Black during channel switch"),
&BlackPicture, trVDR("no"), trVDR("yes"))); &BlackPicture, trVDR("no"), trVDR("yes")));
Add(new cMenuEditBoolItem(tr("Clear decoder on channel switch"),
&ClearOnSwitch, trVDR("no"), trVDR("yes")));
Add(new cMenuEditIntItem(tr("Brightness (-1000..1000) (vdpau)"), Add(new cMenuEditIntItem(tr("Brightness (-1000..1000) (vdpau)"),
&Brightness, -1000, 1000, tr("min"), tr("max"))); &Brightness, -1000, 1000, tr("min"), tr("max")));
@ -990,9 +854,9 @@ void cMenuSetupSoft::Create(void)
&AudioPassthroughPCM, trVDR("no"), trVDR("yes"))); &AudioPassthroughPCM, trVDR("no"), trVDR("yes")));
Add(new cMenuEditBoolItem(tr("\040\040AC-3 pass-through"), Add(new cMenuEditBoolItem(tr("\040\040AC-3 pass-through"),
&AudioPassthroughAC3, trVDR("no"), trVDR("yes"))); &AudioPassthroughAC3, trVDR("no"), trVDR("yes")));
Add(new cMenuEditBoolItem(tr("\040\040E-AC-3 pass-through"), Add(new cMenuEditBoolItem(tr("\040\040EAC-3 pass-through"),
&AudioPassthroughEAC3, trVDR("no"), trVDR("yes"))); &AudioPassthroughEAC3, trVDR("no"), trVDR("yes")));
Add(new cMenuEditBoolItem(tr("Enable (E-)AC-3 (decoder) downmix"), Add(new cMenuEditBoolItem(tr("Enable (E)AC-3 (decoder) downmix"),
&AudioDownmix, trVDR("no"), trVDR("yes"))); &AudioDownmix, trVDR("no"), trVDR("yes")));
Add(new cMenuEditBoolItem(tr("Volume control"), &AudioSoftvol, Add(new cMenuEditBoolItem(tr("Volume control"), &AudioSoftvol,
tr("Hardware"), tr("Software"))); tr("Hardware"), tr("Software")));
@ -1008,8 +872,6 @@ void cMenuSetupSoft::Create(void)
&AudioStereoDescent, 0, 1000)); &AudioStereoDescent, 0, 1000));
Add(new cMenuEditIntItem(tr("Audio buffer size (ms)"), Add(new cMenuEditIntItem(tr("Audio buffer size (ms)"),
&AudioBufferTime, 0, 1000)); &AudioBufferTime, 0, 1000));
Add(new cMenuEditBoolItem(tr("Enable automatic AES"), &AudioAutoAES,
trVDR("no"), trVDR("yes")));
} }
#ifdef USE_PIP #ifdef USE_PIP
// //
@ -1115,7 +977,6 @@ cMenuSetupSoft::cMenuSetupSoft(void)
General = 0; General = 0;
MakePrimary = ConfigMakePrimary; MakePrimary = ConfigMakePrimary;
HideMainMenuEntry = ConfigHideMainMenuEntry; HideMainMenuEntry = ConfigHideMainMenuEntry;
DetachFromMainMenu = ConfigDetachFromMainMenu;
// //
// osd // osd
// //
@ -1149,7 +1010,6 @@ cMenuSetupSoft::cMenuSetupSoft(void)
_60HzMode = ConfigVideo60HzMode; _60HzMode = ConfigVideo60HzMode;
SoftStartSync = ConfigVideoSoftStartSync; SoftStartSync = ConfigVideoSoftStartSync;
BlackPicture = ConfigVideoBlackPicture; BlackPicture = ConfigVideoBlackPicture;
ClearOnSwitch = ConfigVideoClearOnSwitch;
Brightness = ConfigVideoBrightness; Brightness = ConfigVideoBrightness;
Contrast = ConfigVideoContrast; Contrast = ConfigVideoContrast;
@ -1193,7 +1053,6 @@ cMenuSetupSoft::cMenuSetupSoft(void)
AudioMaxCompression = ConfigAudioMaxCompression; AudioMaxCompression = ConfigAudioMaxCompression;
AudioStereoDescent = ConfigAudioStereoDescent; AudioStereoDescent = ConfigAudioStereoDescent;
AudioBufferTime = ConfigAudioBufferTime; AudioBufferTime = ConfigAudioBufferTime;
AudioAutoAES = ConfigAudioAutoAES;
#ifdef USE_PIP #ifdef USE_PIP
// //
@ -1217,11 +1076,6 @@ cMenuSetupSoft::cMenuSetupSoft(void)
PipAltVideoWidth = ConfigPipAltVideoWidth; PipAltVideoWidth = ConfigPipAltVideoWidth;
PipAltVideoHeight = ConfigPipAltVideoHeight; PipAltVideoHeight = ConfigPipAltVideoHeight;
#endif #endif
#ifdef USE_SCREENSAVER
EnableDPMSatBlackScreen = ConfigEnableDPMSatBlackScreen;
#endif
Create(); Create();
} }
@ -1235,8 +1089,6 @@ void cMenuSetupSoft::Store(void)
SetupStore("MakePrimary", ConfigMakePrimary = MakePrimary); SetupStore("MakePrimary", ConfigMakePrimary = MakePrimary);
SetupStore("HideMainMenuEntry", ConfigHideMainMenuEntry = SetupStore("HideMainMenuEntry", ConfigHideMainMenuEntry =
HideMainMenuEntry); HideMainMenuEntry);
SetupStore("DetachFromMainMenu", ConfigDetachFromMainMenu =
DetachFromMainMenu);
switch (OsdSize) { switch (OsdSize) {
case 0: case 0:
OsdWidth = 0; OsdWidth = 0;
@ -1281,7 +1133,6 @@ void cMenuSetupSoft::Store(void)
VideoSetSoftStartSync(ConfigVideoSoftStartSync); VideoSetSoftStartSync(ConfigVideoSoftStartSync);
SetupStore("BlackPicture", ConfigVideoBlackPicture = BlackPicture); SetupStore("BlackPicture", ConfigVideoBlackPicture = BlackPicture);
VideoSetBlackPicture(ConfigVideoBlackPicture); VideoSetBlackPicture(ConfigVideoBlackPicture);
SetupStore("ClearOnSwitch", ConfigVideoClearOnSwitch = ClearOnSwitch);
SetupStore("Brightness", ConfigVideoBrightness = Brightness); SetupStore("Brightness", ConfigVideoBrightness = Brightness);
VideoSetBrightness(ConfigVideoBrightness); VideoSetBrightness(ConfigVideoBrightness);
@ -1336,12 +1187,6 @@ void cMenuSetupSoft::Store(void)
VideoSetAudioDelay(ConfigVideoAudioDelay); VideoSetAudioDelay(ConfigVideoAudioDelay);
SetupStore("AudioDrift", ConfigAudioDrift = AudioDrift); SetupStore("AudioDrift", ConfigAudioDrift = AudioDrift);
CodecSetAudioDrift(ConfigAudioDrift); CodecSetAudioDrift(ConfigAudioDrift);
// FIXME: can handle more audio state changes here
// downmix changed reset audio, to get change direct
if (ConfigAudioDownmix != AudioDownmix) {
ResetChannelId();
}
ConfigAudioPassthrough = (AudioPassthroughPCM ? CodecPCM : 0) ConfigAudioPassthrough = (AudioPassthroughPCM ? CodecPCM : 0)
| (AudioPassthroughAC3 ? CodecAC3 : 0) | (AudioPassthroughAC3 ? CodecAC3 : 0)
| (AudioPassthroughEAC3 ? CodecEAC3 : 0); | (AudioPassthroughEAC3 ? CodecEAC3 : 0);
@ -1369,8 +1214,6 @@ void cMenuSetupSoft::Store(void)
AudioStereoDescent); AudioStereoDescent);
AudioSetStereoDescent(ConfigAudioStereoDescent); AudioSetStereoDescent(ConfigAudioStereoDescent);
SetupStore("AudioBufferTime", ConfigAudioBufferTime = AudioBufferTime); SetupStore("AudioBufferTime", ConfigAudioBufferTime = AudioBufferTime);
SetupStore("AudioAutoAES", ConfigAudioAutoAES = AudioAutoAES);
AudioSetAutoAES(ConfigAudioAutoAES);
#ifdef USE_PIP #ifdef USE_PIP
SetupStore("pip.X", ConfigPipX = PipX); SetupStore("pip.X", ConfigPipX = PipX);
@ -1392,12 +1235,6 @@ void cMenuSetupSoft::Store(void)
SetupStore("pip.Alt.VideoHeight", ConfigPipAltVideoHeight = SetupStore("pip.Alt.VideoHeight", ConfigPipAltVideoHeight =
PipAltVideoHeight); PipAltVideoHeight);
#endif #endif
#ifdef USE_SCREENSAVER
SetupStore("EnableDPMSatBlackScreen", ConfigEnableDPMSatBlackScreen =
EnableDPMSatBlackScreen);
SetDPMSatBlackScreen(ConfigEnableDPMSatBlackScreen);
#endif
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -1513,11 +1350,7 @@ class cSoftReceiver:public cReceiver
{ {
protected: protected:
virtual void Activate(bool); virtual void Activate(bool);
#if APIVERSNUM >= 20301
virtual void Receive(const uchar *, int);
#else
virtual void Receive(uchar *, int); virtual void Receive(uchar *, int);
#endif
public: public:
cSoftReceiver(const cChannel *); ///< receiver constructor cSoftReceiver(const cChannel *); ///< receiver constructor
virtual ~ cSoftReceiver(); ///< receiver destructor virtual ~ cSoftReceiver(); ///< receiver destructor
@ -1610,12 +1443,12 @@ static void PipPesParse(const uint8_t * data, int size, int is_start)
if (is_start) { // start of pes packet if (is_start) { // start of pes packet
if (pes_index) { if (pes_index) {
if (0) { if (0) {
fprintf(stderr, "pip: PES packet %8d %02x%02x\n", pes_index, fprintf(stderr, "pip: pes packet %8d %02x%02x\n", pes_index,
pes_buf[2], pes_buf[3]); pes_buf[2], pes_buf[3]);
} }
if (pes_buf[0] || pes_buf[1] || pes_buf[2] != 0x01) { if (pes_buf[0] || pes_buf[1] || pes_buf[2] != 0x01) {
// FIXME: first should always fail // FIXME: first should always fail
esyslog(tr("[softhddev]pip: invalid PES packet %d\n"), esyslog(tr("[softhddev]pip: invalid pes packet %d\n"),
pes_index); pes_index);
} else { } else {
PipPlayVideo(pes_buf, pes_index); PipPlayVideo(pes_buf, pes_index);
@ -1651,11 +1484,7 @@ static void PipPesParse(const uint8_t * data, int size, int is_start)
** @param data ts packet ** @param data ts packet
** @param size size (#TS_PACKET_SIZE=188) of tes packet ** @param size size (#TS_PACKET_SIZE=188) of tes packet
*/ */
#if APIVERSNUM >= 20301
void cSoftReceiver::Receive(const uchar * data, int size)
#else
void cSoftReceiver::Receive(uchar * data, int size) void cSoftReceiver::Receive(uchar * data, int size)
#endif
{ {
const uint8_t *p; const uint8_t *p;
@ -1747,8 +1576,7 @@ static void NewPip(int channel_nr)
if (!channel_nr) { if (!channel_nr) {
channel_nr = cDevice::CurrentChannel(); channel_nr = cDevice::CurrentChannel();
} }
LOCK_CHANNELS_READ; if (channel_nr && (channel = Channels.GetByNumber(channel_nr))
if (channel_nr && (channel = Channels MURKS GetByNumber(channel_nr))
&& (device = cDevice::GetDevice(channel, 0, false, false))) { && (device = cDevice::GetDevice(channel, 0, false, false))) {
DelPip(); DelPip();
@ -1794,16 +1622,14 @@ static void PipNextAvailableChannel(int direction)
DelPip(); // disable PIP to free the device DelPip(); // disable PIP to free the device
LOCK_CHANNELS_READ;
while (channel) { while (channel) {
bool ndr; bool ndr;
cDevice *device; cDevice *device;
channel = direction > 0 ? Channels MURKS Next(channel) channel = direction > 0 ? Channels.Next(channel)
: Channels MURKS Prev(channel); : Channels.Prev(channel);
if (!channel && Setup.ChannelsWrap) { if (!channel && Setup.ChannelsWrap) {
channel = channel = direction > 0 ? Channels.First() : Channels.Last();
direction > 0 ? Channels MURKS First() : Channels MURKS Last();
} }
if (channel && !channel->GroupSep() if (channel && !channel->GroupSep()
&& (device = cDevice::GetDevice(channel, 0, false, true)) && (device = cDevice::GetDevice(channel, 0, false, true))
@ -1832,9 +1658,7 @@ static void SwapPipChannels(void)
NewPip(0); NewPip(0);
if (channel) { if (channel) {
LOCK_CHANNELS_READ; Channels.SwitchTo(channel->Number());
Channels MURKS SwitchTo(channel->Number());
} }
} }
@ -1922,12 +1746,7 @@ void cSoftHdMenu::Create(void)
Clear(); // clear the menu Clear(); // clear the menu
SetHasHotkeys(); SetHasHotkeys();
if (ConfigDetachFromMainMenu) {
Add(new cOsdItem(hk(tr("Detach SoftHdDevice")), osUser1));
} else {
Add(new cOsdItem(hk(tr("Suspend SoftHdDevice")), osUser1)); Add(new cOsdItem(hk(tr("Suspend SoftHdDevice")), osUser1));
}
#ifdef USE_PIP #ifdef USE_PIP
if (PipReceiver) { if (PipReceiver) {
Add(new cOsdItem(hk(tr("PIP toggle on/off: off")), osUser2)); Add(new cOsdItem(hk(tr("PIP toggle on/off: off")), osUser2));
@ -2023,17 +1842,6 @@ static void HandleHotkey(int code)
cString::sprintf(tr("audio delay changed to %d"), cString::sprintf(tr("audio delay changed to %d"),
ConfigVideoAudioDelay)); ConfigVideoAudioDelay));
break; break;
case 15:
ConfigAudioDownmix ^= 1;
fprintf(stderr, "toggle downmix\n");
CodecSetAudioDownmix(ConfigAudioDownmix);
if (ConfigAudioDownmix) {
Skins.QueueMessage(mtInfo, tr("surround downmix enabled"));
} else {
Skins.QueueMessage(mtInfo, tr("surround downmix disabled"));
}
ResetChannelId();
break;
case 20: // disable full screen case 20: // disable full screen
VideoSetFullscreen(0); VideoSetFullscreen(0);
@ -2108,7 +1916,6 @@ static void HandleHotkey(int code)
break; break;
case 108: case 108:
DelPip(); DelPip();
PipChannelNr = 0;
break; break;
#endif #endif
@ -2186,14 +1993,9 @@ eOSState cSoftHdMenu::ProcessKey(eKeys key)
if (SuspendMode == NOT_SUSPENDED && !cSoftHdControl::Player) { if (SuspendMode == NOT_SUSPENDED && !cSoftHdControl::Player) {
cControl::Launch(new cSoftHdControl); cControl::Launch(new cSoftHdControl);
cControl::Attach(); cControl::Attach();
if (ConfigDetachFromMainMenu) {
Suspend(1, 1, 0);
SuspendMode = SUSPEND_DETACHED;
} else {
Suspend(ConfigSuspendClose, ConfigSuspendClose, Suspend(ConfigSuspendClose, ConfigSuspendClose,
ConfigSuspendX11); ConfigSuspendX11);
SuspendMode = SUSPEND_NORMAL; SuspendMode = SUSPEND_NORMAL;
}
if (ShutdownHandler.GetUserInactiveTime()) { if (ShutdownHandler.GetUserInactiveTime()) {
dsyslog("[softhddev]%s: set user inactive\n", dsyslog("[softhddev]%s: set user inactive\n",
__FUNCTION__); __FUNCTION__);
@ -2219,7 +2021,6 @@ eOSState cSoftHdMenu::ProcessKey(eKeys key)
return osEnd; return osEnd;
case osUser8: case osUser8:
DelPip(); DelPip();
PipChannelNr = 0;
return osEnd; return osEnd;
#endif #endif
default: default:
@ -2242,11 +2043,7 @@ class cSoftHdDevice:public cDevice
virtual bool HasDecoder(void) const; virtual bool HasDecoder(void) const;
virtual bool CanReplay(void) const; virtual bool CanReplay(void) const;
virtual bool SetPlayMode(ePlayMode); virtual bool SetPlayMode(ePlayMode);
#if APIVERSNUM >= 20103
virtual void TrickSpeed(int, bool);
#else
virtual void TrickSpeed(int); virtual void TrickSpeed(int);
#endif
virtual void Clear(void); virtual void Clear(void);
virtual void Play(void); virtual void Play(void);
virtual void Freeze(void); virtual void Freeze(void);
@ -2393,7 +2190,7 @@ bool cSoftHdDevice::SetPlayMode(ePlayMode play_mode)
case pmVideoOnly: case pmVideoOnly:
break; break;
case pmNone: case pmNone:
break; return true;
case pmExtern_THIS_SHOULD_BE_AVOIDED: case pmExtern_THIS_SHOULD_BE_AVOIDED:
dsyslog("[softhddev] play mode external\n"); dsyslog("[softhddev] play mode external\n");
// FIXME: what if already suspended? // FIXME: what if already suspended?
@ -2434,23 +2231,13 @@ int64_t cSoftHdDevice::GetSTC(void)
** times. ** times.
** **
** @param speed trick speed ** @param speed trick speed
** @param forward flag forward direction
*/ */
#if APIVERSNUM >= 20103
void cSoftHdDevice::TrickSpeed(int speed, bool forward)
{
dsyslog("[softhddev]%s: %d %d\n", __FUNCTION__, speed, forward);
::TrickSpeed(speed);
}
#else
void cSoftHdDevice::TrickSpeed(int speed) void cSoftHdDevice::TrickSpeed(int speed)
{ {
dsyslog("[softhddev]%s: %d\n", __FUNCTION__, speed); dsyslog("[softhddev]%s: %d\n", __FUNCTION__, speed);
::TrickSpeed(speed); ::TrickSpeed(speed);
} }
#endif
/** /**
** Clears all video and audio data from the device. ** Clears all video and audio data from the device.
@ -2725,9 +2512,6 @@ uchar *cSoftHdDevice::GrabImage(int &size, bool jpeg, int quality, int width,
if (SuspendMode != NOT_SUSPENDED) { if (SuspendMode != NOT_SUSPENDED) {
return NULL; return NULL;
} }
if (quality < 0) { // caller should care, but fix it
quality = 95;
}
return::GrabImage(&size, jpeg, quality, width, height); return::GrabImage(&size, jpeg, quality, width, height);
} }
@ -2755,8 +2539,8 @@ cRect cSoftHdDevice::CanScaleVideo(const cRect & rect,
void cSoftHdDevice::ScaleVideo(const cRect & rect) void cSoftHdDevice::ScaleVideo(const cRect & rect)
{ {
#ifdef OSD_DEBUG #ifdef OSD_DEBUG
dsyslog("[softhddev]%s: %dx%d%+d%+d\n", __FUNCTION__, rect.Width(), dsyslog("[softhddev]%s: %dx%d%+d%+d\n", __FUNCTION__, VidWinRect.Width(),
rect.Height(), rect.X(), rect.Y()); VidWinRect.Height(), VidWinRect.X(), VidWinRect.Y());
#endif #endif
::ScaleVideo(rect.X(), rect.Y(), rect.Width(), rect.Height()); ::ScaleVideo(rect.X(), rect.Y(), rect.Width(), rect.Height());
} }
@ -3016,10 +2800,6 @@ bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
ConfigHideMainMenuEntry = atoi(value); ConfigHideMainMenuEntry = atoi(value);
return true; return true;
} }
if (!strcasecmp(name, "DetachFromMainMenu")) {
ConfigDetachFromMainMenu = atoi(value);
return true;
}
if (!strcasecmp(name, "Osd.Width")) { if (!strcasecmp(name, "Osd.Width")) {
ConfigOsdWidth = atoi(value); ConfigOsdWidth = atoi(value);
VideoSetOsdSize(ConfigOsdWidth, ConfigOsdHeight); VideoSetOsdSize(ConfigOsdWidth, ConfigOsdHeight);
@ -3069,10 +2849,6 @@ bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
VideoSetBlackPicture(ConfigVideoBlackPicture = atoi(value)); VideoSetBlackPicture(ConfigVideoBlackPicture = atoi(value));
return true; return true;
} }
if (!strcasecmp(name, "ClearOnSwitch")) {
ConfigVideoClearOnSwitch = atoi(value);
return true;
}
if (!strcasecmp(name, "Brightness")) { if (!strcasecmp(name, "Brightness")) {
VideoSetBrightness(ConfigVideoBrightness = atoi(value)); VideoSetBrightness(ConfigVideoBrightness = atoi(value));
return true; return true;
@ -3219,11 +2995,6 @@ bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
ConfigAudioBufferTime = atoi(value); ConfigAudioBufferTime = atoi(value);
return true; return true;
} }
if (!strcasecmp(name, "AudioAutoAES")) {
ConfigAudioAutoAES = atoi(value);
AudioSetAutoAES(ConfigAudioAutoAES);
return true;
}
#ifdef USE_PIP #ifdef USE_PIP
if (!strcasecmp(name, "pip.X")) { if (!strcasecmp(name, "pip.X")) {
ConfigPipX = atoi(value); ConfigPipX = atoi(value);
@ -3290,15 +3061,6 @@ bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
return true; return true;
} }
#endif #endif
#ifdef USE_SCREENSAVER
if (!strcasecmp(name, "EnableDPMSatBlackScreen")) {
ConfigEnableDPMSatBlackScreen = atoi(value);
SetDPMSatBlackScreen(ConfigEnableDPMSatBlackScreen);
return true;
}
#endif
return false; return false;
} }
@ -3418,7 +3180,7 @@ static const char *SVDRPHelpText[] = {
" 11: enable audio pass-through\n" " 11: enable audio pass-through\n"
" 12: toggle audio pass-through\n" " 12: toggle audio pass-through\n"
" 13: decrease audio delay by 10ms\n" " 13: decrease audio delay by 10ms\n"
" 14: increase audio delay by 10ms\n" " 15: toggle ac3 mixdown\n" " 14: increase audio delay by 10ms\n"
" 20: disable fullscreen\n\040 21: enable fullscreen\n" " 20: disable fullscreen\n\040 21: enable fullscreen\n"
" 22: toggle fullscreen\n" " 22: toggle fullscreen\n"
" 23: disable auto-crop\n\040 24: enable auto-crop\n" " 23: disable auto-crop\n\040 24: enable auto-crop\n"

View File

@ -1,7 +1,7 @@
/// ///
/// @file softhddevice.h @brief software HD device plugin header file. /// @file softhddevice.h @brief software HD device plugin header file.
/// ///
/// Copyright (c) 2011, 2014 by Johns. All Rights Reserved. /// Copyright (c) 2011 by Johns. All Rights Reserved.
/// ///
/// Contributor(s): /// Contributor(s):
/// ///

View File

@ -0,0 +1,74 @@
# Copyright 1999-2012 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $
EAPI="4"
inherit eutils vdr-plugin-2
if [[ ${PV} == "9999" ]] ; then
inherit git-2
EGIT_REPO_URI="git://projects.vdr-developer.org/vdr-plugin-softhddevice.git"
else
SRC_URI="http://projects.vdr-developer.org/attachments/download/838/${P}.tgz"
fi
DESCRIPTION="A software and GPU emulated HD output device plugin for VDR."
HOMEPAGE="http://projects.vdr-developer.org/projects/show/plg-softhddevice"
SRC_URI=""
LICENSE="AGPL-3"
SLOT="0"
KEYWORDS="~x86 ~amd64"
IUSE="vaapi vdpau alsa oss yaepg opengl debug"
DEPEND=">=x11-libs/libxcb-1.8
x11-libs/xcb-util
x11-libs/xcb-util-wm
x11-libs/xcb-util-keysyms
x11-libs/xcb-util-renderutil
x11-libs/libX11
opengl? ( virtual/opengl )
>=virtual/ffmpeg-0.7
sys-devel/gettext
sys-devel/make
dev-util/pkgconfig
yaepg? ( >=media-video/vdr-1.7.23[yaepg] )
!yaepg? ( >=media-video/vdr-1.7.23 )
vdpau? ( x11-libs/libvdpau virtual/ffmpeg[vdpau] )
vaapi? ( x11-libs/libva virtual/ffmpeg[vaapi] )
alsa? ( media-libs/alsa-lib )
oss? ( sys-kernel/linux-headers )
"
src_prepare() {
vdr-plugin-2_src_prepare
}
src_compile() {
local myconf
myconf="-DHAVE_PTHREAD_NAME -DAV_INFO -DAV_INFO_TIME=15000"
use vdpau && myconf="${myconf} -DUSE_VDPAU"
use vaapi && myconf="${myconf} -DUSE_VAAPI"
use alsa && myconf="${myconf} -DUSE_ALSA"
use oss && myconf="${myconf} -DUSE_OSS"
use debug && myconf="${myconf} -DDEBUG"
#vdr-plugin-2_src_compile
cd "${S}"
BUILD_TARGETS=${BUILD_TARGETS:-${VDRPLUGIN_MAKE_TARGET:-all}}
emake ${BUILD_PARAMS} CONFIG="${myconf}" \
${BUILD_TARGETS} \
LOCALEDIR="${TMP_LOCALE_DIR}" \
LIBDIR="${S}" \
TMPDIR="${T}" \
|| die "emake failed"
}
src_install() {
vdr-plugin-2_src_install
}

View File

@ -1,73 +1,65 @@
# Copyright 1999-2014 Gentoo Foundation # Copyright 1999-2012 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2 # Distributed under the terms of the GNU General Public License v2
# $Header: $ # $Header: $
EAPI="5" EAPI="5"
inherit vdr-plugin-2 git-2 inherit flag-o-matic toolchain-funcs vdr-plugin-2 eutils
RESTRICT="test" if [ "${PV}" = "9999" ]; then
inherit git-2
EGIT_REPO_URI="git://projects.vdr-developer.org/vdr-plugin-softhddevice.git"
KEYWORDS=""
else
SRC_URI="mirror://vdr-developerorg/889/${P}.tgz"
KEYWORDS="~amd64 ~x86"
fi
EGIT_REPO_URI="git://projects.vdr-developer.org/vdr-plugin-softhddevice.git" DESCRIPTION="Software and GPU emulated HD output device plugin for VDR"
KEYWORDS=""
DESCRIPTION="VDR Plugin: Software and GPU emulated HD output device"
HOMEPAGE="http://projects.vdr-developer.org/projects/show/plg-softhddevice" HOMEPAGE="http://projects.vdr-developer.org/projects/show/plg-softhddevice"
LICENSE="AGPL-3" LICENSE="AGPL-3"
SLOT="0" SLOT="0"
IUSE="alsa +debug opengl oss vaapi vdpau xscreensaver" IUSE="alsa oss vaapi vdpau yaepg xscreensaver debug"
RDEPEND=">=media-video/vdr-2 RDEPEND=">=media-video/vdr-1.7
>=virtual/ffmpeg-0.7[vdpau?,vaapi?]
x11-libs/libX11 x11-libs/libX11
>=x11-libs/libxcb-1.8 >=x11-libs/libxcb-1.8
x11-libs/xcb-util-wm x11-libs/xcb-util-wm
x11-libs/xcb-util-keysyms
x11-libs/xcb-util-renderutil
alsa? ( media-libs/alsa-lib ) alsa? ( media-libs/alsa-lib )
opengl? ( virtual/opengl ) vdpau? ( x11-libs/libvdpau )
vaapi? ( x11-libs/libva vaapi? ( x11-libs/libva )
virtual/ffmpeg[vaapi] ) alsa? ( media-libs/alsa-lib )
vdpau? ( x11-libs/libvdpau yaepg? ( >=media-video/vdr-1.7[yaepg] )"
virtual/ffmpeg[vdpau] )"
DEPEND="${RDEPEND} DEPEND="${RDEPEND}
x11-libs/xcb-util
sys-devel/gettext
virtual/pkgconfig virtual/pkgconfig
x11-libs/xcb-util" oss? ( sys-kernel/linux-headers )"
REQUIRED_USE="opengl? ( vaapi ) src_compile() {
|| ( vaapi vdpau ) local myconf
|| ( alsa oss )"
#VDR_CONFD_FILE="${FILESDIR}/confd-0.6.0" myconf+=" ALSA=$(usex alsa 1 0)"
#VDR_RCADDON_FILE="${FILESDIR}/rc-addon-0.6.0.sh" myconf+=" OSS=$(usex oss 1 0)"
myconf+=" VDPAU=$(usex vdpau 1 0)"
pkg_setup() { myconf+=" VAAPI=$(usex vaapi 1 0)"
vdr-plugin-2_pkg_setup myconf+=" SCREENSAVER=$(usex xscreensaver 1 0)"
if has_version ">=media-video/ffmpeg-0.8" ; then
append-cppflags -DHAVE_PTHREAD_NAME myconf+=" SWRESAMPLE=1"
use debug && append-cppflags -DDEBUG -DOSD_DEBUG
}
src_prepare() {
vdr-plugin-2_src_prepare
BUILD_PARAMS+=" ALSA=$(usex alsa 1 0)"
BUILD_PARAMS+=" OPENGL=$(usex opengl 1 0)"
BUILD_PARAMS+=" OSS=$(usex oss 1 0)"
BUILD_PARAMS+=" VAAPI=$(usex vaapi 1 0)"
BUILD_PARAMS+=" VDPAU=$(usex vdpau 1 0)"
BUILD_PARAMS+=" SCREENSAVER=$(usex xscreensaver 1 0)"
if has_version ">=media-video/ffmpeg-0.8"; then
BUILD_PARAMS+=" SWRESAMPLE=1"
fi
if has_version ">=media-video/libav-0.8"; then
BUILD_PARAMS+=" AVRESAMPLE=1"
fi fi
append-cflags -DHAVE_PTHREAD_NAME -D_GNU_SOURCE
append-cxxflags -DHAVE_PTHREAD_NAME -D_GNU_SOURCE
tc-export CC CXX
BUILD_PARAMS="${myconf}"
vdr-plugin-2_src_compile
} }
src_install() { src_install() {
vdr-plugin-2_src_install vdr-plugin-2_src_install
nonfatal dodoc ChangeLog Todo dodoc ChangeLog README.txt
} }

1687
video.c

File diff suppressed because it is too large Load Diff

16
video.h
View File

@ -1,7 +1,7 @@
/// ///
/// @file video.h @brief Video module header file /// @file video.h @brief Video module header file
/// ///
/// Copyright (c) 2009 - 2015 by Johns. All Rights Reserved. /// Copyright (c) 2009 - 2013 by Johns. All Rights Reserved.
/// ///
/// Contributor(s): /// Contributor(s):
/// ///
@ -37,7 +37,7 @@ typedef struct __video_stream__ VideoStream;
// Variables // Variables
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
extern signed char VideoHardwareDecoder; ///< flag use hardware decoder extern char VideoHardwareDecoder; ///< flag use hardware decoder
extern char VideoIgnoreRepeatPict; ///< disable repeat pict warning extern char VideoIgnoreRepeatPict; ///< disable repeat pict warning
extern int VideoAudioDelay; ///< audio/video delay extern int VideoAudioDelay; ///< audio/video delay
extern char ConfigStartX11Server; ///< flag start the x11 server extern char ConfigStartX11Server; ///< flag start the x11 server
@ -67,8 +67,8 @@ extern enum PixelFormat Video_get_format(VideoHwDecoder *, AVCodecContext *,
extern void VideoRenderFrame(VideoHwDecoder *, const AVCodecContext *, extern void VideoRenderFrame(VideoHwDecoder *, const AVCodecContext *,
const AVFrame *); const AVFrame *);
/// Get hwaccel context for ffmpeg. /// Get ffmpeg vaapi context.
extern void *VideoGetHwAccelContext(VideoHwDecoder *); extern struct vaapi_context *VideoGetVaapiContext(VideoHwDecoder *);
#ifdef AVCODEC_VDPAU_H #ifdef AVCODEC_VDPAU_H
/// Draw vdpau render state. /// Draw vdpau render state.
@ -168,8 +168,7 @@ extern void VideoSetAutoCrop(int, int, int);
extern void VideoOsdClear(void); extern void VideoOsdClear(void);
/// Draw an OSD ARGB image. /// Draw an OSD ARGB image.
extern void VideoOsdDrawARGB(int, int, int, int, int, const uint8_t *, int, extern void VideoOsdDrawARGB(int, int, int, int, const uint8_t *);
int);
/// Get OSD size. /// Get OSD size.
extern void VideoGetOsdSize(int *, int *); extern void VideoGetOsdSize(int *, int *);
@ -222,10 +221,7 @@ extern int VideoDecodeInput(VideoStream *);
/// Get number of input buffers. /// Get number of input buffers.
extern int VideoGetBuffers(const VideoStream *); extern int VideoGetBuffers(const VideoStream *);
/// Set DPMS at Blackscreen switch
extern void SetDPMSatBlackScreen(int);
/// Raise the frontend window /// Raise the frontend window
extern int VideoRaiseWindow(void); extern int VideoRaiseWindow();
/// @} /// @}