123 Commits

Author SHA1 Message Date
Johns
58a76439ee Softer audio/video sync. 2013-09-30 20:54:27 +02:00
Johns
a13c25d309 Add function GetStats to the video output module. 2013-08-07 10:29:44 +02:00
Johns
5265e68aa9 Add function ResetStart to the video output module. 2013-08-06 12:16:30 +02:00
Johns
11121b5bdd Add function SetClosing to the video output module. 2013-08-04 17:43:11 +02:00
Johns
d8e96c7871 Generalize GetVaapiContext to GetHwAccelContext. 2013-08-03 17:27:52 +02:00
Johns
8ff65a011a Add compile time configurable trickspeed packets dump. 2013-07-29 19:14:32 +02:00
Johns
171a3f4dc9 Fix bug #1410: wrong spelled AC-3 and E-AC-3. 2013-07-26 16:55:33 +02:00
Johns
93357fb1cd Add compile time selectable h264 trickspeed workaround. 2013-07-24 20:06:05 +02:00
Johns
c646007db1 Use ffmpeg new names AVCodecID, AV_CODEC_... . 2013-07-18 17:08:47 +02:00
Johns
7615305960 Fix bug: video lagging behind after recording stop. 2013-07-16 16:39:46 +02:00
Johns
cc1e2de58b Reduce PES error messages. 2013-07-15 17:00:22 +02:00
Johns
738e9402d2 Report synced as info and not as debug message. 2013-07-15 16:58:36 +02:00
Johns
34fd275b42 Fix bug #1392: Wrong value for mixing LFE. 2013-07-08 14:36:08 +02:00
Johns
64c11efc1b Fix bug: wrong grab size, introduced with AMD VDPAU. 2013-05-16 20:28:44 +02:00
Johns
ebb8482226 Use VDR SPU decoder as default. 2013-05-15 10:07:30 +02:00
Johns
833112eaa9 Fix bug: grab image negative quality isn't 100. 2013-05-14 12:32:09 +02:00
Johns
3022920b40 Don't forget PIP documentation. 2013-05-10 16:33:37 +02:00
Johns
c1d3b9d048 Support AMD VDPAU with surface != requested size. 2013-05-10 15:53:26 +02:00
Johns
4fe1c43c08 Removes VA-API enabled as default.
Removes studio levels environment setting.
2013-04-23 20:46:36 +02:00
Johns
7a5e696bc4 Fix opengl and opengl threads bugs. 2013-04-17 16:35:51 +02:00
Johns
8f99f80d44 Initial opengl support with va-api only. 2013-04-16 16:44:42 +02:00
Johns
c0286b3ab4 Fix "broken driver" message if empty ring buffer. 2013-04-15 16:55:15 +02:00
Johns
9dd248f9d0 Enable seamless audio track change. 2013-04-11 12:03:38 +02:00
Johns
238224efc8 Better to unlock after the free and zero. 2013-04-10 15:04:09 +02:00
Johns
5b35e70b94 Fix bug #1302: Unsupported pixel format crash. 2013-04-08 16:42:47 +02:00
Johns
857546a3a5 Fix the fix, when sillpicture is called in suspend. 2013-04-06 14:24:08 +02:00
Johns
a1b77b1502 Fixes PIP Y translation. 2013-04-03 16:53:45 +02:00
Johns
7ef5667598 Patch was not 100% correct, fixed. 2013-04-03 16:51:27 +02:00
Johns
4e3f5f5414 Fix crash, when sillpicture is called in suspend mode. 2013-04-03 16:48:00 +02:00
Johns
23b0e0d599 Add workaround for zero width+height and ffmpeg >= 1.2. 2013-04-03 16:47:21 +02:00
Johns
eab051f5e6 Release Version 0.6.0. 2013-03-17 15:53:01 +01:00
e058302a08 Update german translation. 2013-03-17 15:51:11 +01:00
Johns
efcf3a1d2d Fix Bug #1286: typo. 2013-03-12 23:27:09 +01:00
Johns
1f0d5878b1 Adds H264 only hardware decoder for still-pictures. 2013-03-11 16:32:00 +01:00
Johns
f09a37a941 Enable optional VDR-SPU deocder support. 2013-03-11 12:18:11 +01:00
Johns
a7562eb2be Removes "static" warning. 2013-03-06 17:31:01 +01:00
a747829ffb Adds raise softhddevice video window support. 2013-03-06 17:07:30 +01:00
Johns
7db63875d0 Adds optional only complete mpeg packets support. 2013-03-06 10:30:27 +01:00
Johns
637c04655a Fixes text of EAC-3 pass-through setup. 2013-03-05 14:39:13 +01:00
Johns
9954b939ef Try to connect to X11 server, when start fails. 2013-02-27 16:48:42 +01:00
Johns
e65572c2e2 Updated ebuild for new vdr-plugin-2.eclass. 2013-02-25 16:40:44 +01:00
Johns
b3ddc47cb5 Removes "unused parameter" warnings. 2013-02-25 16:39:32 +01:00
Johns
4d9e3a71f4 More informations in short description. 2013-02-25 16:34:28 +01:00
Johns
21e4f4ee04 Workaround for ffmpeg 1.1.x get_format bug. 2013-02-25 16:33:40 +01:00
Johns
746746d5b7 Workaround for ffmpeg 1.1.2 bug. 2013-02-25 16:32:52 +01:00
Johns
936566c642 Show vaapi droped/missed messages with info level. 2013-02-23 15:56:24 +01:00
Johns
d6f557c6f7 Removes warnings, when compiles without VDPAU. 2013-02-15 15:58:49 +01:00
Johns
2d2ea53d16 Quote spaces to get correct ouput. 2013-02-13 22:47:16 +01:00
Johns
bccd959833 Fix .pot file generation, support _ and _N macros. 2013-02-13 22:46:08 +01:00
Johns
240fc17471 Store pass-through on/off state in setup. 2013-02-13 17:23:18 +01:00
Johns
7b2caac901 Fix bug: still old CodecPassthroughAC3 used. 2013-02-12 22:03:52 +01:00
Johns
56aae221e7 Adds missing USE_SCREENSAVER to old Makefile. 2013-02-12 18:11:40 +01:00
Johns
54255e7b57 Try to use HBR (High Bit-Rate) for EAC3. 2013-02-11 23:40:09 +01:00
Johns
2cd667fb44 Improved pass-through (PCM+EAC3) support. 2013-02-11 16:53:51 +01:00
Johns
145d65ff01 Debug time for channel switch. 2013-02-11 15:11:52 +01:00
Johns
8faff0fd1e Try to detect wrong Makefile use. 2013-02-11 14:41:19 +01:00
Johns
d31ff55b12 Clear buffers quicker, when replay stops. 2013-02-08 21:03:06 +01:00
Johns
d4535a34c9 Fix xcb deadlock while closing PIP decoder.
Close video decoder from inside the decoder thread,
otherwise xcb hangs in a lock.
2013-02-07 16:54:16 +01:00
Johns
ebd2f85f90 Update for new Makefiles. 2013-02-07 10:17:48 +01:00
Johns
dce7ef9110 Adds PIP hot-key support. 2013-02-06 16:27:25 +01:00
Johns
780e2989ae Makes audio mixer optional. 2013-02-06 16:02:22 +01:00
Johns
2661fdf333 Plugin needs -D_GNU_SOURCE. 2013-01-30 18:04:53 +01:00
Johns
2557418e81 No longer needed. 2013-01-29 20:48:04 +01:00
Johns
b48e0d0638 Support VDR 1.7.36 new build system. 2013-01-29 17:04:50 +01:00
Johns
2c27d83b9e Makes buffers soft limit configurable. 2013-01-28 23:13:23 +01:00
Johns
8b22585748 Never trust the docs: fix ffmpeg downsample. 2013-01-26 00:18:59 +01:00
Johns
7ed6975330 Support upsampling 3,5 to 8 channels.
Improve next ring buffer handling.
Improve audio/video sync debug.
2013-01-25 17:05:53 +01:00
Johns
d5e111238d Improves VDPAU dissplay preemption handling. 2013-01-25 16:55:25 +01:00
2733e47af7 Add modifiers to X11 remote key names. 2013-01-25 16:52:23 +01:00
Johns
f9998e7664 Add audio compatibility with >=ffmpeg 1.1. 2013-01-24 21:42:39 +01:00
Johns
04286fb2ad Add video compatibility with >=ffmpeg 1.1. 2013-01-23 21:54:56 +01:00
Johns
cd82ee8e4a Fix bug: no sound with video output "none". 2013-01-22 17:18:18 +01:00
Johns
a1f17199d6 Crop setup is done by VdpauSetupOutput. 2013-01-22 17:08:44 +01:00
Johns
849ca7cfd6 Stronger H264/Mpeg detection tests. 2013-01-12 19:13:43 +01:00
Johns
308742a927 React faster only with mpeg. 2013-01-11 18:54:45 +01:00
Johns
1a730ef90b Fix build without USE_PIP. 2013-01-09 00:39:27 +01:00
Johns
d59c2ad40b Must guard CodecVideoDecode. 2013-01-08 23:52:41 +01:00
Johns
3366faece2 Fixes close PIP threading bug. 2013-01-08 21:11:46 +01:00
Johns
2bb2875cd7 Update PIP only, when visible. 2013-01-07 19:31:05 +01:00
Johns
e88403d044 Close pip before switching channel. 2013-01-07 17:47:05 +01:00
Johns
11293e8dc1 Split mpeg packets in receiver thread. 2013-01-07 16:55:42 +01:00
Johns
3bcc3d280e fprints only when building debug version. 2013-01-06 19:17:02 +01:00
Johns
55587c86f0 Switch PIP to only available channels. 2013-01-06 19:15:46 +01:00
Johns
7cc74795be Fix bug: missing external reference with -DUSE_PIP. 2013-01-06 19:14:46 +01:00
Johns
534b4094b5 Fix thread exit problem. 2013-01-06 14:47:00 +01:00
Johns
7cd025a023 Cosmetic cleanups. 2013-01-06 14:06:08 +01:00
Johns
b14a67b601 New features documented. 2013-01-05 23:16:03 +01:00
Johns
b24409323d Fix detach and attach bug. 2013-01-05 22:48:01 +01:00
Johns
9ec2716026 PIP function update. 2013-01-05 20:47:14 +01:00
Johns
fa09d940c5 Fix PIP threading problems. 2013-01-05 20:44:54 +01:00
Johns
d4702b9a9e Include softhddevice.cpp in indent target.
Fix constconst after indent.  Hello GNU who many years until it will be
fixed?
2013-01-05 19:49:59 +01:00
Johns
6a3a560857 Adds PIP channel switch functions. 2013-01-05 17:17:50 +01:00
Johns
8ee1e84b2e Restore video position, when PIP closes. 2013-01-05 16:37:25 +01:00
Johns
7e96a292eb First video surface clears complete window. 2013-01-05 15:41:57 +01:00
Johns
d89ada9aad Makes PIP+Video position configurable. 2013-01-04 21:50:55 +01:00
Johns
59d1a6b1f2 Adds function to stop PIP. 2013-01-04 18:50:14 +01:00
Johns
1a744a8eb8 Sync to audio only with the first video stream. 2013-01-04 18:04:53 +01:00
Johns
78100cba00 Use second stream for PIP. 2013-01-04 15:56:26 +01:00
Johns
b54ddd4549 Enable more than 1 vdpau video stream. 2013-01-04 15:54:32 +01:00
Johns
d42475f2dc Prepared reentrant video stream. 2013-01-03 18:52:34 +01:00
Johns
7cf6c1ab2b va-api has problems with h264 interlace. 2013-01-03 01:03:22 +01:00
Johns
06b8e3d784 Fix video size not updated for VAAPI. 2013-01-02 23:59:46 +01:00
63c22a13cf Adds VDR SeduAtmo Plugin support. 2013-01-01 17:58:54 +01:00
Johns
3d5e59a6e5 Support multiple streams with ScaleVideo. 2013-01-01 15:21:28 +01:00
Johns
acf377ec60 Makes 4:3 and 16:9 display format configurable.
Don't use DVB display format.
2013-01-01 14:48:51 +01:00
87c1c7be84 Add support for new vdr ScaleVideo API. 2013-01-01 12:51:08 +01:00
Johns
5bacd0cf7b Comments cleanup. 2013-01-01 12:40:12 +01:00
Johns
b1beb49798 Add support for old PES HDTV recording. 2013-01-01 12:09:54 +01:00
Johns
33b14be516 Change VideoSetOutputPosition to work OSD relative. 2012-12-31 17:51:43 +01:00
Johns
3907f3eb2f Change +%d to %+d, which is more general. 2012-12-31 17:11:22 +01:00
Johns
00d314dcd1 Disable trickspeed hack, to prevent ffmpeg crash. 2012-12-31 14:03:19 +01:00
Johns
9719fef55b Fix video size not updated, when window size change. 2012-12-30 17:05:42 +01:00
Johns
9b69045a20 Use 1 surface reserve. 2012-12-24 12:59:35 +01:00
Johns
966ff4229a Better video stream window position support. 2012-12-24 12:23:16 +01:00
Johns
e0c0c2021f Need LOCALEDIR to build as user. 2012-12-24 11:56:10 +01:00
Johns
a3907d11a5 Spam syslog with a/v sync infos. 2012-12-24 11:55:32 +01:00
Johns
b94d19e7b8 Make clear what downmix is enabled. 2012-12-24 11:53:16 +01:00
Johns
943ee22aa5 Makes X11 server arguments configurable. 2012-12-14 17:24:54 +01:00
Johns
b6154a988f Fix build with NO_TS_AUDIO. 2012-12-14 17:04:50 +01:00
Johns
932871dea9 Use vdr-plugin-2. 2012-11-30 20:46:13 +01:00
Johns
5ec6963398 Missing space added. 2012-11-25 00:38:32 +01:00
Johns
b04323704d Missing space added. 2012-11-25 00:35:39 +01:00
38011d51b6 Add german translation. 2012-11-18 21:17:09 +01:00
19 changed files with 6133 additions and 1659 deletions

View File

@@ -1,3 +1,94 @@
User johns
Date:
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
Date: Sun Mar 17 15:52:42 CET 2013
Release Version 0.6.0
Adds H264 only hardware decoder for still-pictures.
Enable optional VDR-SPU deocder support.
User anbr
Date: Sun Mar 17 15:49:46 CET 2013
Update german translation.
User cyril
Date: Wed Mar 6 17:05:10 CET 2013
Adds raise softhddevice video window support.
User johns
Date: Wed Mar 6 10:30:27 CET 2013
Adds optional only complete mpeg packets support.
Fixes text of EAC-3 pass-through setup.
Try to start or connect to X11 server with -xx.
Try to use HBR (High Bit-Rate) for EAC3.
Improved pass-through (PCM+EAC3) support.
Support VDR 1.7.36 new build system.
Improves VDPAU display preemption handling.
Add modifiers to X11 remote key names (from Sibbi).
Add compatibility with >=ffmpeg 1.1.
Adds PIP (Picture-in-Picture) support.
Split mpeg packets in receiver thread.
User horchi
Date: Tue Jan 1 17:58:54 CET 2013
Adds VDR SeduAtmo Plugin support.
User johns
Date: Tue Jan 1 15:21:28 CET 2013
Support multiple streams with ScaleVideo.
Makes 4:3 and 16:9 display format configurable.
Don't use DVB display format.
User Zoolook
Date: Tue Jan 1 12:49:19 CET 2013
Add support for new vdr ScaleVideo API.
User johns
Date: Tue Jan 1 12:40:12 CET 2013
Add support for old PES HDTV recording.
Disable trickspeed hack, to prevent ffmpeg crash.
Makes X11 server arguments configurable.
Add german translation.
User FireFly
Date: Sun Nov 18 21:15:50 CET 2012
Add german translation.
User johns
Date: Thu Nov 15 22:28:55 CET 2012

232
Makefile
View File

@@ -6,152 +6,197 @@
# 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
### Configuration (edit this for your needs)
# support alsa audio output module
ALSA ?= $(shell pkg-config --exists alsa && echo 1)
# support OSS audio output module
OSS ?= 1
# support VDPAU video output module
VDPAU ?= $(shell pkg-config --exists vdpau && echo 1)
# support VA-API video output module (deprecated)
#VAAPI ?= $(shell pkg-config --exists libva && echo 1)
# support glx output
#OPENGL ?= $(shell pkg-config --exists gl glu && echo 1)
# screensaver disable/enable
SCREENSAVER ?= 1
# use ffmpeg libswresample
SWRESAMPLE ?= $(shell pkg-config --exists libswresample && echo 1)
CONFIG := # -DDEBUG #-DOSD_DEBUG # enable debug output+functions
#CONFIG += -DSTILL_DEBUG=2 # still picture debug verbose level
CONFIG += -DAV_INFO -DAV_INFO_TIME=3000 # info/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
#CONFIG += -DUSE_MPEG_COMPLETE # support only complete mpeg packets
#CONFIG += -DH264_EOS_TRICKSPEED # insert seq end packets for trickspeed
#CONDIF += -DDUMP_TRICKSPEED # dump trickspeed packets
CONFIG += -DUSE_VDR_SPU # use VDR SPU decoder.
#CONFIG += -DUSE_SOFTLIMIT # (tobe removed) limit the buffer fill
ifeq ($(ALSA),1)
CONFIG += -DUSE_ALSA
_CFLAGS += $(shell pkg-config --cflags alsa)
LIBS += $(shell pkg-config --libs alsa)
endif
ifeq ($(OSS),1)
CONFIG += -DUSE_OSS
endif
ifeq ($(VDPAU),1)
CONFIG += -DUSE_VDPAU
_CFLAGS += $(shell pkg-config --cflags vdpau)
LIBS += $(shell pkg-config --libs vdpau)
endif
ifeq ($(VAAPI),1)
CONFIG += -DUSE_VAAPI
_CFLAGS += $(shell pkg-config --cflags 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
ifeq ($(SCREENSAVER),1)
CONFIG += -DUSE_SCREENSAVER
_CFLAGS += $(shell pkg-config --cflags xcb-screensaver xcb-dpms)
LIBS += $(shell pkg-config --libs xcb-screensaver xcb-dpms)
endif
ifeq ($(SWRESAMPLE),1)
CONFIG += -DUSE_SWRESAMPLE
_CFLAGS += $(shell pkg-config --cflags libswresample)
LIBS += $(shell pkg-config --libs libswresample)
endif
_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)
### 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 += -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
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
CXXFLAGS ?= -g -O2 -W -Wall -Wextra -Werror=overloaded-virtual
### The directory environment:
VDRDIR ?= ../../..
LIBDIR ?= ../../lib
# 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
### Make sure that necessary options are included:
### The compiler options:
-include $(VDRDIR)/Make.global
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 $(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)
-include $(PLGCFG)
### The name of the distribution archive:
ARCHIVE = $(PLUGIN)-$(VERSION)
PACKAGE = vdr-$(ARCHIVE)
### Includes, Defines and dependencies (add further entries here):
### The name of the shared object file:
INCLUDES += -I$(VDRDIR)/include
SOFILE = libvdr-$(PLUGIN).so
DEFINES += $(CONFIG) -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"' \
### Includes and Defines (add further entries here):
INCLUDES +=
DEFINES += -DPLUGIN_NAME_I18N='"$(PLUGIN)"' -D_GNU_SOURCE $(CONFIG) \
$(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_VDPAU,$(CONFIG)), \
`pkg-config --cflags vdpau`) \
$(if $(findstring USE_VAAPI,$(CONFIG)), \
`pkg-config --cflags libva-x11 libva-glx libva`) \
$(if $(findstring USE_ALSA,$(CONFIG)), \
`pkg-config --cflags alsa`)
### Make it standard
#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_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`)
override CXXFLAGS += $(_CFLAGS) $(DEFINES) $(INCLUDES) \
-g -W -Wall -Wextra -Winit-self -Werror=overloaded-virtual
override CFLAGS += $(_CFLAGS) $(DEFINES) $(INCLUDES) \
-g -W -Wall -Wextra -Winit-self -Wdeclaration-after-statement
### 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) $<
all: $(SOFILE) i18n
### Dependencies:
MAKEDEP = $(CC) -MM -MG
MAKEDEP = $(CXX) -MM -MG
DEPFILE = .dependencies
$(DEPFILE): Makefile
@$(MAKEDEP) $(DEFINES) $(INCLUDES) $(SRCS) >$@
$(OBJS): Makefile
@$(MAKEDEP) $(CXXFLAGS) $(SRCS) > $@
-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))))))
I18Nmo = $(addsuffix .mo, $(foreach file, $(I18Npo), $(basename $(file))))
I18Nmsgs = $(addprefix $(DESTDIR)$(LOCDIR)/, $(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)
$(I18Npot): $(SRCS)
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 $@ $^
-k_ -k_N --package-name=vdr-$(PLUGIN) --package-version=$(VERSION) \
--msgid-bugs-address='<see README>' -o $@ `ls $^`
%.po: $(I18Npot)
msgmerge -U --no-wrap --no-location --backup=none -q $@ $<
msgmerge -U --no-wrap --no-location --backup=none -q -N $@ $<
@touch $@
$(I18Nmsgs): $(LOCALEDIR)/%/LC_MESSAGES/vdr-$(PLUGIN).mo: $(PODIR)/%.mo
@mkdir -p $(dir $@)
cp $< $@
$(I18Nmsgs): $(DESTDIR)$(LOCDIR)/%/LC_MESSAGES/vdr-$(PLUGIN).mo: $(PODIR)/%.mo
install -D -m644 $< $@
.PHONY: i18n
i18n: $(I18Nmsgs) $(I18Npot)
i18n: $(I18Nmo) $(I18Npot)
install-i18n: $(I18Nmsgs)
### Targets:
libvdr-$(PLUGIN).so: $(OBJS) Makefile
$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared -fPIC $(OBJS) -o $@ $(LIBS)
@cp --remove-destination $@ $(LIBDIR)/$@.$(APIVERSION)
$(OBJS): Makefile
$(SOFILE): $(OBJS)
$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) $(LIBS) -o $@
install-lib: $(SOFILE)
install -D $^ $(DESTDIR)$(LIBDIR)/$^.$(APIVERSION)
install: install-lib install-i18n
dist: $(I18Npo) clean
@-rm -rf $(TMPDIR)/$(ARCHIVE)
@@ -162,19 +207,20 @@ dist: $(I18Npo) clean
@echo Distribution package created as $(PACKAGE).tgz
clean:
@-rm -f $(OBJS) $(DEPFILE) *.so *.tgz core* *~ $(PODIR)/*.mo $(PODIR)/*.pot
@-rm -f $(PODIR)/*.mo $(PODIR)/*.pot
@-rm -f $(OBJS) $(DEPFILE) *.so *.tgz core* *~
install: libvdr-$(PLUGIN).so
cp --remove-destination libvdr-$(PLUGIN).so \
/usr/lib/vdr/plugins/libvdr-$(PLUGIN).so.$(APIVERSION)
## Private Targets:
HDRS= $(wildcard *.h)
indent:
for i in $(wildcard $(OBJS:.o=.c)) $(HDRS); do \
indent $$i; unexpand -a $$i > $$i.up; mv $$i.up $$i; \
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 $@
$(CC) -DVIDEO_TEST -DVERSION='"$(VERSION)"' $(CFLAGS) $(LDFLAGS) $< \
$(LIBS) -o $@

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

@@ -1,6 +1,6 @@
@file README.txt @brief A software HD output device for VDR
Copyright (c) 2011, 2012 by Johns. All Rights Reserved.
Copyright (c) 2011 - 2013 by Johns. All Rights Reserved.
Contributor(s):
@@ -20,25 +20,27 @@ $Id$
A software and GPU emulated HD output device plugin for VDR.
o Video decoder CPU / VA-API / VDPAU
o Video output VA-API / VDPAU
o Video decoder CPU / VDPAU
o Video output VDPAU
o Audio FFMpeg / Alsa / Analog
o Audio FFMpeg / Alsa / Digital
o Audio FFMpeg / OSS / Analog
o HDMI/SPDIF pass-through
o Software volume, compression, normalize and channel resample
o YaepgHD support
o VDR ScaleVideo API
o Software deinterlacer Bob (VA-API only)
o Autocrop
o Grab image (VDPAU only)
o Suspend
o Suspend / Dettach
o Letterbox, Stretch and Center cut-out video display modes
o atmo light support with plugin http://github.com/durchflieger/DFAtmo
o PIP (Picture-in-Picture) (VDPAU only)
o planned: Video decoder VA-API Branch: vaapi-ext/staging
o planned: Video output XvBA / Opengl / Xv
o planned: VA-API grab image
o planned: Improved Software Deinterlacer (yadif or/and ffmpeg filters)
o planned: Remove VA-API decoder and output support
o planned: Video decoder OpenMax
o planned: Video output Opengl / Xv
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.
@@ -56,8 +58,8 @@ Install:
git clone git://projects.vdr-developer.org/vdr-plugin-softhddevice.git
cd vdr-plugin-softhddevice
make VDRDIR=<path-to-your-vdr-files> LIBDIR=.
gentoo: make VDRDIR=/usr/include/vdr LIBDIR=.
make
make install
2a) tarball
@@ -66,10 +68,11 @@ Install:
tar vxf vdr-softhddevice-*.tar.bz2
cd softhddevice-*
make VDRDIR=<path-to-your-vdr-files> LIBDIR=.
make
make install
You can edit Makefile to enable/disable VDPAU / VA-API / Alsa / OSS
support.
support. The default is to autodetect as much as possible.
Setup: environment
------
@@ -81,14 +84,12 @@ Setup: environment
if set don't use the hardware decoders
NO_MPEG_HW=1
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
ALSA_DEVICE=default
alsa PCM device name
ALSA_AC3_DEVICE=
alsa AC3/pass-though device name
ALSA_PASSTHROUGH_DEVICE=
alsa pass-though (AC-3,E-AC-3,DTS,...) device name
ALSA_MIXER=default
alsa control device name
ALSA_MIXER_CHANNEL=PCM
@@ -97,8 +98,8 @@ Setup: environment
only if oss is configured
OSS_AUDIODEV=/dev/dsp
oss dsp device name
OSS_AC3_AUDIODEV=
oss AC3/pass-though device name
OSS_PASSTHROUGHDEV=
oss pass-though (AC-3,E-AC-3,DTS,...) device name
OSS_MIXERDEV=/dev/mixer
oss mixer device name
OSS_MIXER_CHANNEL=pcm
@@ -128,7 +129,7 @@ Setup: /etc/vdr/setup.conf
softhddevice.<res>.Deinterlace = 0
0 = bob, 1 = weave, 2 = temporal, 3 = temporal_spatial, 4 = software
(only 0, 1 supported with vaapi)
(only 0, 1, 4 supported with VA-API)
softhddevice.<res>.SkipChromaDeinterlace = 0
0 = disabled, 1 = enabled (for slower cards, poor qualit<69>t)
@@ -154,13 +155,17 @@ Setup: /etc/vdr/setup.conf
delay audio or delay video
softhddevice.AudioPassthrough = 0
0 = none, 1 = AC-3
0 = none, 1 = PCM, 2 = MPA, 4 = AC-3, 8 = EAC-3, -X disable
for AC-3 the pass-through device is used.
for PCM/AC-3/EAC-3 the pass-through device is used and the audio
stream is passed undecoded to the output device.
z.b. 12 = AC-3+EAC-3, 13 = PCM+AC-3+EAC-3
note: MPA/DTS/TrueHD/... aren't supported yet
negative values disable passthrough
softhddevice.AudioDownmix = 0
0 = none, 1 = downmix
downmix AC-3 to stero.
Use ffmpeg/libav downmix of AC-3/EAC-3 audio to stereo.
softhddevice.AudioSoftvol = 0
0 = off, use hardware volume control
@@ -228,11 +233,41 @@ Setup: /etc/vdr/setup.conf
0 disable black picture during channel switch
1 enable black picture during channel switch
VideoDisplayFormat = ?
softhddevice.Video4to3DisplayFormat = 1
0 pan and scan
1 letter box
2 center cut-out
softhddevice.VideoOtherDisplayFormat = 1
0 pan and scan
1 pillar box
2 center cut-out
softhddevice.pip.X = 79
softhddevice.pip.Y = 78
softhddevice.pip.Width = 18
softhddevice.pip.Height = 18
PIP pip window position and size in percent.
softhddevice.pip.VideoX = 0
softhddevice.pip.VideoY = 0
softhddevice.pip.VideoWidth = 0
softhddevice.pip.VideoHeight = 0
PIP video window position and size in percent.
softhddevice.pip.Alt.X = 0
softhddevice.pip.Alt.Y = 50
softhddevice.pip.Alt.Width = 0
softhddevice.pip.Alt.Height = 50
PIP alternative pip window position and size in percent.
softhddevice.pip.Alt.VideoX = 0
softhddevice.pip.Alt.VideoY = 0
softhddevice.pip.Alt.VideoWidth = 0
softhddevice.pip.Alt.VideoHeight = 50
PIP alternative video window position and size in percent.
Setup: /etc/vdr/remote.conf
------
@@ -305,11 +340,16 @@ Warning:
Known Bugs:
-----------
VA-API doesn't v-sync 1080i streams
VA-API doesn't v-sync h264 interlaced streams
vdr-image not working
Requires:
---------
media-video/vdr (version >=1.7.xx)
Video Disk Recorder - turns a pc into a powerful set top box
for DVB.
http://www.tvdr.de/
media-video/ffmpeg (version >=0.7)
Complete solution to record, convert and stream audio and
video. Includes libavcodec.
@@ -320,7 +360,7 @@ Requires:
or
kernel support for oss/oss4 or alsa oss emulation
x11-libs/libva
x11-libs/libva (deprecated)
Video Acceleration (VA) API for Linux
http://www.freedesktop.org/wiki/Software/vaapi
x11-libs/libva-intel-driver

18
Todo
View File

@@ -1,6 +1,6 @@
@file Todo @brief A software HD output device for VDR
Copyright (c) 2011, 2012 by Johns. All Rights Reserved.
Copyright (c) 2011 - 2013 by Johns. All Rights Reserved.
Contributor(s):
@@ -19,6 +19,9 @@ GNU Affero General Public License for more details.
$Id: $
missing:
documentation of the PIP hotkeys.
svdrp help page missing PIP hotkeys.
svdrp stat: add X11 crashed status.
more software deinterlace (yadif, ...)
more software decoder with software deinterlace
suspend output / energie saver: stop and restart X11
@@ -39,11 +42,15 @@ video:
some low-bandwidth tv channels have hiccups.
check start with 24Hz display rate
crash with ffmpeg without vaapi and vdpau.
still-picture of PES recordings should use VideoMpegEnqueue.
convert PIX_FMT_... PixelFormat to new names AV_PIX_FMT_..., AVPixelFormat.
atmo service support 3D grab
vdpau:
software deinterlace path not working.
OSD looses transparency, during channel switch.
OSD looses transparency, while moving cut marks.
ffmpeg >=1.2 supports same API like VA-API.
libva:
yaepghd (VaapiSetOutputPosition) support
@@ -54,6 +61,8 @@ libva:
[drm:i915_hangcheck_elapsed] *ERROR* Hangcheck timer elapsed... GPU hung
[drm:i915_wait_request] *ERROR* i915_wait_request returns -11 ...
missing OSD support for 3d SBS / Top-Bottom streams, like VPDAU.
PIP support / multistream handling
VA-AP VaapiCleanup crash after channel without video.
libva: branch vaapi-ext / staging
add support for vaapi-ext / staging
@@ -110,23 +119,20 @@ plugins:
setup:
Setup of decoder type.
Setup of output type.
Setup of display type.
Setup 4:3 zoom type
Some setup parameters are not used until restart.
Can a notice be added to the setup menu?
unsorted:
stoping vdr while plugin is suspended opens and closes a window.
svdrp prim: support plugin names for device numbers.
Workaround exists: hangup PipVideoStream -> Vdpau_get_format -> xcb -> poll
+ lock DecoderLockMutex
future features (not planed for 1.0 - 1.5)
video out with xv
video out with opengl
video out with xvba
software decoder for xv / opengl
multistream handling
pip support
save and use auto-crop with channel zapping
upmix stereo to AC-3 (supported by alsa plugin)

262
audio.c
View File

@@ -1,7 +1,7 @@
///
/// @file audio.c @brief Audio module
///
/// Copyright (c) 2009 - 2012 by Johns. All Rights Reserved.
/// Copyright (c) 2009 - 2013 by Johns. All Rights Reserved.
///
/// Contributor(s):
///
@@ -40,6 +40,7 @@
//#define USE_ALSA ///< enable alsa support
//#define USE_OSS ///< enable OSS support
#define USE_AUDIO_THREAD ///< use thread for audio playback
#define USE_AUDIO_MIXER ///< use audio module mixer
#include <stdio.h>
#include <stdint.h>
@@ -128,7 +129,7 @@ static const char *AudioModuleName; ///< which audio module to use
/// Selected audio module.
static const AudioModule *AudioUsedModule = &NoopModule;
static const char *AudioPCMDevice; ///< PCM device name
static const char *AudioAC3Device; ///< AC3 device name
static const char *AudioPassthroughDevice; ///< Passthrough device name
static const char *AudioMixerDevice; ///< mixer device name
static const char *AudioMixerChannel; ///< mixer channel name
static char AudioDoingInit; ///> flag in init, reduce error
@@ -163,7 +164,6 @@ static int AudioStereoDescent; ///< volume descent for stereo
static int AudioVolume; ///< current volume (0 .. 1000)
extern int VideoAudioDelay; ///< import audio/video delay
extern int VideoGetBuffers(void); ///< Get number of input buffers.
/// default ring buffer size ~2s 8ch 16bit (3 * 5 * 7 * 8)
static const unsigned AudioRingBufferSize = 3 * 5 * 7 * 8 * 2 * 1000;
@@ -178,7 +178,7 @@ enum _audio_rates
//Audio88200, ///< 88.2Khz
//Audio96000, ///< 96.0Khz
//Audio176400, ///< 176.4Khz
//Audio192000, ///< 192.0Khz
Audio192000, ///< 192.0Khz
AudioRatesMax ///< max index
};
@@ -188,9 +188,9 @@ static int AudioRatesInHw[AudioRatesMax];
/// input to hardware channel matrix
static int AudioChannelMatrix[AudioRatesMax][9];
/// rates tables
/// rates tables (must be sorted by frequency)
static const unsigned AudioRatesTable[AudioRatesMax] = {
44100, 48000,
44100, 48000, 192000
};
//----------------------------------------------------------------------------
@@ -401,6 +401,8 @@ static void AudioSoftAmplifier(int16_t * samples, int count)
}
}
#ifdef USE_AUDIO_MIXER
/**
** Upmix mono to stereo.
**
@@ -484,7 +486,7 @@ static void AudioSurround2Stereo(const int16_t * in, int in_chan, int frames,
r += in[3] * 200; // Rs
l += in[4] * 300; // C
r += in[4] * 300;
l += in[5] * 300; // LFE
l += in[5] * 100; // LFE
r += in[5] * 100;
break;
case 7: // 7.0
@@ -547,6 +549,13 @@ static void AudioUpmix(const int16_t * in, int in_chan, int frames,
/**
** Resample ffmpeg sample format to hardware format.
**
** FIXME: use libswresample for this and move it to codec.
** FIXME: ffmpeg to alsa conversion is already done in codec.c.
**
** ffmpeg L R C Ls Rs -> alsa L R Ls Rs C
** ffmpeg L R C LFE Ls Rs -> alsa L R Ls Rs C LFE
** ffmpeg L R C LFE Ls Rs Rl Rr -> alsa L R Ls Rs C LFE Rl Rr
**
** @param in input sample buffer
** @param in_chan nr. of input channels
** @param frames number of frames in sample buffer
@@ -582,6 +591,9 @@ static void AudioResample(const int16_t * in, int in_chan, int frames,
AudioSurround2Stereo(in, in_chan, frames, out);
break;
case 5 * 8 + 6:
case 3 * 8 + 8:
case 5 * 8 + 8:
case 6 * 8 + 8:
AudioUpmix(in, in_chan, frames, out, out_chan);
break;
@@ -594,6 +606,8 @@ static void AudioResample(const int16_t * in, int in_chan, int frames,
}
}
#endif
//----------------------------------------------------------------------------
// ring buffer
//----------------------------------------------------------------------------
@@ -606,7 +620,7 @@ static void AudioResample(const int16_t * in, int in_chan, int frames,
typedef struct _audio_ring_ring_
{
char FlushBuffers; ///< flag: flush buffers
char UseAc3; ///< flag: use ac3 pass-through
char Passthrough; ///< flag: use pass-through (AC-3, ...)
int16_t PacketSize; ///< packet size
unsigned HwSampleRate; ///< hardware sample rate in Hz
unsigned HwChannels; ///< hardware number of channels
@@ -624,29 +638,34 @@ static atomic_t AudioRingFilled; ///< how many of the ring is used
static unsigned AudioStartThreshold; ///< start play, if filled
/**
** Add sample-rate, number of channel change to ring.
** Add sample-rate, number of channels change to ring.
**
** @param sample_rate sample-rate frequency
** @param channels number of channels
** @param use_ac3 use ac3/pass-through device
** @param passthrough use /pass-through (AC-3, ...) device
**
** @retval -1 error
** @retval 0 okay
**
** @note this function shouldn't fail. Checks are done during AudoInit.
*/
static int AudioRingAdd(unsigned sample_rate, int channels, int use_ac3)
static int AudioRingAdd(unsigned sample_rate, int channels, int passthrough)
{
unsigned u;
// search supported sample-rates
for (u = 0; u < AudioRatesMax; ++u) {
if (AudioRatesTable[u] == sample_rate) {
goto found;
}
if (AudioRatesTable[u] > sample_rate) {
break;
}
}
if (u == AudioRatesMax) { // unsupported sample-rate
Error(_("audio: %dHz sample-rate unsupported\n"), sample_rate);
return -1;
}
return -1; // unsupported sample-rate
found:
if (!AudioChannelMatrix[u][channels]) {
Error(_("audio: %d channels unsupported\n"), channels);
return -1; // unsupported nr. of channels
@@ -659,9 +678,8 @@ static int AudioRingAdd(unsigned sample_rate, int channels, int use_ac3)
}
AudioRingWrite = (AudioRingWrite + 1) % AUDIO_RING_MAX;
// FIXME: don't flush buffers here
AudioRing[AudioRingWrite].FlushBuffers = 1;
AudioRing[AudioRingWrite].UseAc3 = use_ac3;
AudioRing[AudioRingWrite].FlushBuffers = 0;
AudioRing[AudioRingWrite].Passthrough = passthrough;
AudioRing[AudioRingWrite].PacketSize = 0;
AudioRing[AudioRingWrite].InSampleRate = sample_rate;
AudioRing[AudioRingWrite].InChannels = channels;
@@ -670,6 +688,9 @@ static int AudioRingAdd(unsigned sample_rate, int channels, int use_ac3)
AudioRing[AudioRingWrite].PTS = INT64_C(0x8000000000000000);
RingBufferReset(AudioRing[AudioRingWrite].RingBuffer);
Debug(3, "audio: %d ring buffer prepared\n",
atomic_read(&AudioRingFilled) + 1);
atomic_inc(&AudioRingFilled);
#ifdef USE_AUDIO_THREAD
@@ -817,8 +838,9 @@ static int AlsaPlayRingbuffer(void)
if (!avail) { // full or buffer empty
break;
}
// muting ac3, can produce disturbance
if (AudioMute || (AudioSoftVolume && !AudioRing[AudioRingRead].UseAc3)) {
// muting pass-through AC-3, can produce disturbance
if (AudioMute || (AudioSoftVolume
&& !AudioRing[AudioRingRead].Passthrough)) {
// FIXME: quick&dirty cast
AudioSoftAmplifier((int16_t *) p, avail);
// FIXME: if not all are written, we double amplify them
@@ -965,23 +987,23 @@ static int AlsaThread(void)
/**
** Open alsa pcm device.
**
** @param use_ac3 use ac3/pass-through device
** @param passthrough use pass-through (AC-3, ...) device
*/
static snd_pcm_t *AlsaOpenPCM(int use_ac3)
static snd_pcm_t *AlsaOpenPCM(int passthrough)
{
const char *device;
snd_pcm_t *handle;
int err;
// &&|| hell
if (!(use_ac3 && ((device = AudioAC3Device)
|| (device = getenv("ALSA_AC3_DEVICE"))))
if (!(passthrough && ((device = AudioPassthroughDevice)
|| (device = getenv("ALSA_PASSTHROUGH_DEVICE"))))
&& !(device = AudioPCMDevice) && !(device = getenv("ALSA_DEVICE"))) {
device = "default";
}
if (!AudioDoingInit) { // reduce blabla during init
Info(_("audio/alsa: using %sdevice '%s'\n"), use_ac3 ? "ac3 " : "",
device);
Info(_("audio/alsa: using %sdevice '%s'\n"),
passthrough ? "pass-through " : "", device);
}
// open none blocking; if device is already used, we don't want wait
if ((err =
@@ -1148,7 +1170,7 @@ static int64_t AlsaGetDelay(void)
**
** @param freq sample frequency
** @param channels number of channels
** @param use_ac3 use ac3/pass-through device
** @param passthrough use pass-through (AC-3, ...) device
**
** @retval 0 everything ok
** @retval 1 didn't support frequency/channels combination
@@ -1156,7 +1178,7 @@ static int64_t AlsaGetDelay(void)
**
** @todo FIXME: remove pointer for freq + channels
*/
static int AlsaSetup(int *freq, int *channels, int use_ac3)
static int AlsaSetup(int *freq, int *channels, int passthrough)
{
snd_pcm_uframes_t buffer_size;
snd_pcm_uframes_t period_size;
@@ -1164,7 +1186,7 @@ static int AlsaSetup(int *freq, int *channels, int use_ac3)
int delay;
if (!AlsaPCMHandle) { // alsa not running yet
// FIXME: if open fails for ac3, we never recover
// FIXME: if open fails for fe. pass-through, we never recover
return -1;
}
if (1) { // close+open to fix HDMI no sound bug
@@ -1174,7 +1196,7 @@ static int AlsaSetup(int *freq, int *channels, int use_ac3)
// FIXME: need lock
AlsaPCMHandle = NULL; // other threads should check handle
snd_pcm_close(handle);
if (!(handle = AlsaOpenPCM(use_ac3))) {
if (!(handle = AlsaOpenPCM(passthrough))) {
return -1;
}
AlsaPCMHandle = handle;
@@ -1434,7 +1456,7 @@ static int OssPlayRingbuffer(void)
break; // bi.bytes could become negative!
}
if (AudioSoftVolume && !AudioRing[AudioRingRead].UseAc3) {
if (AudioSoftVolume && !AudioRing[AudioRingRead].Passthrough) {
// FIXME: quick&dirty cast
AudioSoftAmplifier((int16_t *) p, bi.bytes);
// FIXME: if not all are written, we double amplify them
@@ -1541,22 +1563,22 @@ static int OssThread(void)
/**
** Open OSS pcm device.
**
** @param use_ac3 use ac3/pass-through device
** @param passthrough use pass-through (AC-3, ...) device
*/
static int OssOpenPCM(int use_ac3)
static int OssOpenPCM(int passthrough)
{
const char *device;
int fildes;
// &&|| hell
if (!(use_ac3 && ((device = AudioAC3Device)
|| (device = getenv("OSS_AC3_AUDIODEV"))))
if (!(passthrough && ((device = AudioPassthroughDevice)
|| (device = getenv("OSS_PASSTHROUGHDEV"))))
&& !(device = AudioPCMDevice) && !(device = getenv("OSS_AUDIODEV"))) {
device = "/dev/dsp";
}
if (!AudioDoingInit) {
Info(_("audio/oss: using %sdevice '%s'\n"), use_ac3 ? "ac3 " : "",
device);
Info(_("audio/oss: using %sdevice '%s'\n"),
passthrough ? "pass-through " : "", device);
}
if ((fildes = open(device, O_WRONLY)) < 0) {
@@ -1705,13 +1727,13 @@ static int64_t OssGetDelay(void)
**
** @param sample_rate sample rate/frequency
** @param channels number of channels
** @param use_ac3 use ac3/pass-through device
** @param passthrough use pass-through (AC-3, ...) device
**
** @retval 0 everything ok
** @retval 1 didn't support frequency/channels combination
** @retval -1 something gone wrong
*/
static int OssSetup(int *sample_rate, int *channels, int use_ac3)
static int OssSetup(int *sample_rate, int *channels, int passthrough)
{
int ret;
int tmp;
@@ -1719,17 +1741,17 @@ static int OssSetup(int *sample_rate, int *channels, int use_ac3)
audio_buf_info bi;
if (OssPcmFildes == -1) { // OSS not ready
// FIXME: if open fails for ac3, we never recover
// FIXME: if open fails for fe. pass-through, we never recover
return -1;
}
if (1) { // close+open for pcm / ac3
if (1) { // close+open for pcm / AC-3
int fildes;
fildes = OssPcmFildes;
OssPcmFildes = -1;
close(fildes);
if (!(fildes = OssOpenPCM(use_ac3))) {
if (!(fildes = OssOpenPCM(passthrough))) {
return -1;
}
OssPcmFildes = fildes;
@@ -1912,11 +1934,12 @@ static void NoopSetVolume( __attribute__ ((unused))
**
** @param freq sample frequency
** @param channels number of channels
** @param passthrough use pass-through (AC-3, ...) device
*/
static int NoopSetup( __attribute__ ((unused))
int *channels, __attribute__ ((unused))
int *freq, __attribute__ ((unused))
int use_ac3)
int passthrough)
{
return -1;
}
@@ -1954,16 +1977,17 @@ static const AudioModule NoopModule = {
*/
static int AudioNextRing(void)
{
int use_ac3;
int passthrough;
int sample_rate;
int channels;
size_t used;
// update audio format
// not always needed, but check if needed is too complex
use_ac3 = AudioRing[AudioRingRead].UseAc3;
passthrough = AudioRing[AudioRingRead].Passthrough;
sample_rate = AudioRing[AudioRingRead].HwSampleRate;
channels = AudioRing[AudioRingRead].HwChannels;
if (AudioUsedModule->Setup(&sample_rate, &channels, use_ac3)) {
if (AudioUsedModule->Setup(&sample_rate, &channels, passthrough)) {
Error(_("audio: can't set channels %d sample-rate %dHz\n"), channels,
sample_rate);
// FIXME: handle error
@@ -1976,13 +2000,19 @@ static int AudioNextRing(void)
AudioResetCompressor();
AudioResetNormalizer();
Debug(3, "audio: a/v next buf(%d,%4zdms)\n", atomic_read(&AudioRingFilled),
(RingBufferUsedBytes(AudioRing[AudioRingRead].RingBuffer) * 1000)
/ (AudioRing[AudioRingWrite].HwSampleRate *
AudioRing[AudioRingWrite].HwChannels * AudioBytesProSample));
// stop, if not enough in next buffer
if (AudioStartThreshold >=
RingBufferUsedBytes(AudioRing[AudioRingRead].RingBuffer)) {
return 1;
}
used = RingBufferUsedBytes(AudioRing[AudioRingRead].RingBuffer);
if (AudioStartThreshold * 4 < used || (AudioVideoIsReady
&& AudioStartThreshold < used)) {
return 0;
}
return 1;
}
/**
** Audio play thread.
@@ -2003,10 +2033,10 @@ static void *AudioPlayHandlerThread(void *dummy)
pthread_mutex_unlock(&AudioMutex);
Debug(3, "audio: ----> %dms start\n", (AudioUsedBytes() * 1000)
/ (!AudioRing[AudioRingRead].HwSampleRate +
!AudioRing[AudioRingRead].HwChannels +
AudioRing[AudioRingRead].HwSampleRate *
AudioRing[AudioRingRead].HwChannels * AudioBytesProSample));
/ (!AudioRing[AudioRingWrite].HwSampleRate +
!AudioRing[AudioRingWrite].HwChannels +
AudioRing[AudioRingWrite].HwSampleRate *
AudioRing[AudioRingWrite].HwChannels * AudioBytesProSample));
do {
int filled;
@@ -2030,19 +2060,25 @@ static void *AudioPlayHandlerThread(void *dummy)
}
if (flush) {
Debug(3, "audio: flush\n");
AudioUsedModule->FlushBuffers();
if (AudioNextRing()) {
Debug(3, "audio: break after flush\n");
break;
}
Debug(3, "audio: continue after flush\n");
}
// try to play some samples
err = 0;
if (RingBufferUsedBytes(AudioRing[AudioRingRead].RingBuffer)) {
err = AudioUsedModule->Thread();
}
// underrun, check if new ring buffer is available
if (!err) {
int use_ac3;
int passthrough;
int sample_rate;
int channels;
int old_use_ac3;
int old_passthrough;
int old_sample_rate;
int old_channels;
@@ -2052,20 +2088,21 @@ static void *AudioPlayHandlerThread(void *dummy)
}
Debug(3, "audio: next ring buffer\n");
old_use_ac3 = AudioRing[AudioRingRead].UseAc3;
old_passthrough = AudioRing[AudioRingRead].Passthrough;
old_sample_rate = AudioRing[AudioRingRead].HwSampleRate;
old_channels = AudioRing[AudioRingRead].HwChannels;
atomic_dec(&AudioRingFilled);
AudioRingRead = (AudioRingRead + 1) % AUDIO_RING_MAX;
use_ac3 = AudioRing[AudioRingRead].UseAc3;
passthrough = AudioRing[AudioRingRead].Passthrough;
sample_rate = AudioRing[AudioRingRead].HwSampleRate;
channels = AudioRing[AudioRingRead].HwChannels;
Debug(3, "audio: thread channels %d frequency %dHz %s\n",
channels, sample_rate, use_ac3 ? "ac3" : "pcm");
channels, sample_rate, passthrough ? "pass-through" : "");
// audio config changed?
if (old_use_ac3 != use_ac3 || old_sample_rate != sample_rate
if (old_passthrough != passthrough
|| old_sample_rate != sample_rate
|| old_channels != channels) {
// FIXME: wait for buffer drain
if (AudioNextRing()) {
@@ -2144,7 +2181,6 @@ void AudioEnqueue(const void *samples, int count)
{
size_t n;
int16_t *buffer;
int frames;
#ifdef noDEBUG
static uint32_t last_tick;
@@ -2166,28 +2202,40 @@ void AudioEnqueue(const void *samples, int count)
AudioRing[AudioRingWrite].PacketSize = count;
Debug(3, "audio: a/v packet size %d bytes\n", count);
}
if (AudioRing[AudioRingWrite].UseAc3) {
// audio sample modification allowed and needed?
buffer = (void *)samples;
} else {
//
// Convert / resample input to hardware format
//
if (!AudioRing[AudioRingWrite].Passthrough && (AudioCompression
|| AudioNormalize
|| AudioRing[AudioRingWrite].InChannels !=
AudioRing[AudioRingWrite].HwChannels)) {
int frames;
// resample into ring-buffer is too complex in the case of a roundabout
// just use a temporary buffer
frames =
count / (AudioRing[AudioRingWrite].InChannels *
AudioBytesProSample);
buffer =
alloca(frames * AudioRing[AudioRingWrite].HwChannels *
AudioBytesProSample);
#ifdef USE_AUDIO_MIXER
// Convert / resample input to hardware format
AudioResample(samples, AudioRing[AudioRingWrite].InChannels, frames,
buffer, AudioRing[AudioRingWrite].HwChannels);
#else
#ifdef DEBUG
if (AudioRing[AudioRingWrite].InChannels !=
AudioRing[AudioRingWrite].HwChannels) {
Debug(3, "audio: internal failure channels mismatch\n");
return;
}
#endif
memcpy(buffer, samples, count);
#endif
count =
frames * AudioRing[AudioRingWrite].HwChannels *
AudioBytesProSample;
// resample into ring-buffer is too complex in the case of a roundabout
// just use a temporary buffer
if (AudioCompression) { // in place operation
AudioCompressor(buffer, count);
}
@@ -2276,11 +2324,12 @@ void AudioVideoReady(int64_t pts)
(used * 90 * 1000) / (AudioRing[AudioRingWrite].HwSampleRate *
AudioRing[AudioRingWrite].HwChannels * AudioBytesProSample);
Debug(3, "audio: a/v buf:%4zdms %s|%s = %dms video ready\n",
Debug(3, "audio: a/v sync buf(%d,%4zdms) %s|%s = %dms %s\n",
atomic_read(&AudioRingFilled),
(used * 1000) / (AudioRing[AudioRingWrite].HwSampleRate *
AudioRing[AudioRingWrite].HwChannels * AudioBytesProSample),
Timestamp2String(audio_pts), Timestamp2String(pts),
(int)(pts - audio_pts) / 90);
Timestamp2String(pts), Timestamp2String(audio_pts),
(int)(pts - audio_pts) / 90, AudioRunning ? "running" : "ready");
if (!AudioRunning) {
int skip;
@@ -2291,7 +2340,7 @@ void AudioVideoReady(int64_t pts)
pts - 15 * 20 * 90 - AudioBufferTime * 90 - audio_pts +
VideoAudioDelay;
#ifdef DEBUG
printf("%dms %dms %dms\n", (int)(pts - audio_pts) / 90,
fprintf(stderr, "%dms %dms %dms\n", (int)(pts - audio_pts) / 90,
VideoAudioDelay / 90, skip / 90);
#endif
// guard against old PTS
@@ -2304,7 +2353,7 @@ void AudioVideoReady(int64_t pts)
AudioSkip = skip - used;
skip = used;
}
Debug(3, "audio: advance %dms %d/%zd\n",
Debug(3, "audio: sync advance %dms %d/%zd\n",
(skip * 1000) / (AudioRing[AudioRingWrite].HwSampleRate *
AudioRing[AudioRingWrite].HwChannels *
AudioBytesProSample), skip, used);
@@ -2373,9 +2422,10 @@ void AudioFlushBuffers(void)
int i;
old = AudioRingWrite;
// FIXME: check ring buffer overflow
AudioRingWrite = (AudioRingWrite + 1) % AUDIO_RING_MAX;
AudioRing[AudioRingWrite].FlushBuffers = 1;
AudioRing[AudioRingWrite].UseAc3 = AudioRing[old].UseAc3;
AudioRing[AudioRingWrite].Passthrough = AudioRing[old].Passthrough;
AudioRing[AudioRingWrite].HwSampleRate = AudioRing[old].HwSampleRate;
AudioRing[AudioRingWrite].HwChannels = AudioRing[old].HwChannels;
AudioRing[AudioRingWrite].InSampleRate = AudioRing[old].InSampleRate;
@@ -2487,7 +2537,7 @@ int64_t AudioGetClock(void)
// delay zero, if no valid time stamp
if ((delay = AudioGetDelay())) {
if (AudioRing[AudioRingRead].UseAc3) {
if (AudioRing[AudioRingRead].Passthrough) {
return AudioRing[AudioRingRead].PTS + 0 * 90 - delay;
}
return AudioRing[AudioRingRead].PTS + 0 * 90 - delay;
@@ -2507,7 +2557,7 @@ void AudioSetVolume(int volume)
AudioMute = !volume;
// reduce loudness for stereo output
if (AudioStereoDescent && AudioRing[AudioRingRead].InChannels == 2
&& !AudioRing[AudioRingRead].UseAc3) {
&& !AudioRing[AudioRingRead].Passthrough) {
volume -= AudioStereoDescent;
if (volume < 0) {
volume = 0;
@@ -2526,16 +2576,18 @@ void AudioSetVolume(int volume)
**
** @param freq sample frequency
** @param channels number of channels
** @param use_ac3 use ac3/pass-through device
** @param passthrough use pass-through (AC-3, ...) device
**
** @retval 0 everything ok
** @retval 1 didn't support frequency/channels combination
** @retval -1 something gone wrong
**
** @todo add support to report best fitting format.
*/
int AudioSetup(int *freq, int *channels, int use_ac3)
int AudioSetup(int *freq, int *channels, int passthrough)
{
Debug(3, "audio: setup channels %d frequency %dHz %s\n", *channels, *freq,
use_ac3 ? "ac3" : "pcm");
passthrough ? "pass-through" : "");
// invalid parameter
if (!freq || !channels || !*freq || !*channels) {
@@ -2543,7 +2595,7 @@ int AudioSetup(int *freq, int *channels, int use_ac3)
// FIXME: set flag invalid setup
return -1;
}
return AudioRingAdd(*freq, *channels, use_ac3);
return AudioRingAdd(*freq, *channels, passthrough);
}
/**
@@ -2679,7 +2731,7 @@ void AudioSetDevice(const char *device)
**
** @note this is currently usable with alsa only.
*/
void AudioSetDeviceAC3(const char *device)
void AudioSetPassthroughDevice(const char *device)
{
if (!AudioModuleName) {
AudioModuleName = "alsa"; // detect alsa/OSS
@@ -2689,7 +2741,7 @@ void AudioSetDeviceAC3(const char *device)
AudioModuleName = "oss";
}
}
AudioAC3Device = device;
AudioPassthroughDevice = device;
}
/**
@@ -2748,10 +2800,16 @@ void AudioInit(void)
// Check which channels/rates/formats are supported
// FIXME: we force 44.1Khz and 48Khz must be supported equal
// FIXME: should use bitmap of channels supported in RatesInHw
// FIXME: use loop over sample-rates
freq = 44100;
AudioRatesInHw[Audio44100] = 0;
for (chan = 1; chan < 9; ++chan) {
if (AudioUsedModule->Setup(&freq, &chan, 0)) {
int tchan;
int tfreq;
tchan = chan;
tfreq = freq;
if (AudioUsedModule->Setup(&tfreq, &tchan, 0)) {
AudioChannelsInHw[chan] = 0;
} else {
AudioChannelsInHw[chan] = chan;
@@ -2761,16 +2819,39 @@ void AudioInit(void)
freq = 48000;
AudioRatesInHw[Audio48000] = 0;
for (chan = 1; chan < 9; ++chan) {
int tchan;
int tfreq;
if (!AudioChannelsInHw[chan]) {
continue;
}
if (AudioUsedModule->Setup(&freq, &chan, 0)) {
AudioChannelsInHw[chan] = 0;
tchan = chan;
tfreq = freq;
if (AudioUsedModule->Setup(&tfreq, &tchan, 0)) {
//AudioChannelsInHw[chan] = 0;
} else {
AudioChannelsInHw[chan] = chan;
AudioRatesInHw[Audio48000] |= (1 << chan);
}
}
freq = 192000;
AudioRatesInHw[Audio192000] = 0;
for (chan = 1; chan < 9; ++chan) {
int tchan;
int tfreq;
if (!AudioChannelsInHw[chan]) {
continue;
}
tchan = chan;
tfreq = freq;
if (AudioUsedModule->Setup(&tfreq, &tchan, 0)) {
//AudioChannelsInHw[chan] = 0;
} else {
AudioChannelsInHw[chan] = chan;
AudioRatesInHw[Audio192000] |= (1 << chan);
}
}
// build channel support and conversion table
for (u = 0; u < AudioRatesMax; ++u) {
for (chan = 1; chan < 9; ++chan) {
@@ -2852,13 +2933,16 @@ void AudioInit(void)
*/
void AudioExit(void)
{
const AudioModule *module;
#ifdef USE_AUDIO_THREAD
if (AudioUsedModule->Thread) { // supports threads
AudioExitThread();
}
#endif
AudioUsedModule->Exit();
module = AudioUsedModule;
AudioUsedModule = &NoopModule;
module->Exit();
AudioRingExit();
AudioRunning = 0;
AudioPaused = 0;
@@ -2905,7 +2989,7 @@ static void PrintVersion(void)
#ifdef GIT_REV
"(GIT-" GIT_REV ")"
#endif
",\n\t(c) 2009 - 2012 by Johns\n"
",\n\t(c) 2009 - 2013 by Johns\n"
"\tLicense AGPLv3: GNU Affero General Public License version 3\n");
}
@@ -2962,7 +3046,7 @@ int main(int argc, char *const argv[])
return -1;
default:
PrintVersion();
fprintf(stderr, "Unkown option '%c'\n", optopt);
fprintf(stderr, "Unknown option '%c'\n", optopt);
return -1;
}
break;

View File

@@ -1,7 +1,7 @@
///
/// @file audio.h @brief Audio module headerfile
///
/// Copyright (c) 2009 - 2012 by Johns. All Rights Reserved.
/// Copyright (c) 2009 - 2013 by Johns. All Rights Reserved.
///
/// Contributor(s):
///
@@ -48,7 +48,9 @@ extern void AudioSetCompression(int, int); ///< set compression parameters
extern void AudioSetStereoDescent(int); ///< set stereo loudness descent
extern void AudioSetDevice(const char *); ///< set PCM audio device
extern void AudioSetDeviceAC3(const char *); ///< set pass-through device
/// set pass-through device
extern void AudioSetPassthroughDevice(const char *);
extern void AudioSetChannel(const char *); ///< set mixer channel
extern void AudioInit(void); ///< setup audio module
extern void AudioExit(void); ///< cleanup and exit audio module

685
codec.c
View File

@@ -1,7 +1,7 @@
///
/// @file codec.c @brief Codec functions
///
/// Copyright (c) 2009 - 2012 by Johns. All Rights Reserved.
/// Copyright (c) 2009 - 2013 by Johns. All Rights Reserved.
///
/// Contributor(s):
///
@@ -30,12 +30,14 @@
/// many bugs and incompatiblity in it. Don't use this shit.
///
/// compile with passthrough support (stable, ac3 only)
/// compile with pass-through support (stable, AC-3, E-AC-3 only)
#define USE_PASSTHROUGH
/// compile audio drift correction support (experimental)
/// compile audio drift correction support (very experimental)
#define USE_AUDIO_DRIFT_CORRECTION
/// compile AC3 audio drift correction support (experimental)
/// compile AC-3 audio drift correction support (very experimental)
#define USE_AC3_DRIFT_CORRECTION
/// use ffmpeg libswresample API (autodected, Makefile)
#define noUSE_SWRESAMPLE
#include <stdio.h>
#include <unistd.h>
@@ -54,10 +56,20 @@
#include <alsa/iatomic.h>
#include <libavcodec/avcodec.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_H264 CODEC_ID_H264
#endif
#include <libavcodec/vaapi.h>
#ifdef USE_VDPAU
#include <libavcodec/vdpau.h>
#endif
#ifdef USE_SWRESAMPLE
#include <libswresample/swresample.h>
#endif
#ifndef __USE_GNU
#define __USE_GNU
@@ -115,9 +127,11 @@ struct _video_decoder_
/**
** Callback to negotiate the PixelFormat.
**
** @param fmt is the list of formats which are supported by the codec,
** it is terminated by -1 as 0 is a valid format, the
** formats are ordered by quality.
** @param video_ctx codec context
** @param fmt is the list of formats which are supported by
** the codec, it is terminated by -1 as 0 is a
** valid format, the formats are ordered by
** quality.
*/
static enum PixelFormat Codec_get_format(AVCodecContext * video_ctx,
const enum PixelFormat *fmt)
@@ -125,7 +139,24 @@ static enum PixelFormat Codec_get_format(AVCodecContext * video_ctx,
VideoDecoder *decoder;
decoder = video_ctx->opaque;
//Debug(3, "codec: %s: %18p\n", __FUNCTION__, decoder);
#if LIBAVCODEC_VERSION_INT == AV_VERSION_INT(54,86,100)
// this begins to stink, 1.1.2 calls get_format for each frame
// 1.1.3 has the same version, but works again
if (decoder->GetFormatDone) {
if (decoder->GetFormatDone < 10) {
++decoder->GetFormatDone;
Error
("codec/video: ffmpeg/libav buggy: get_format called again\n");
}
return *fmt; // FIXME: this is hack
}
#endif
// bug in ffmpeg 1.1.1, called with zero width or height
if (!video_ctx->width || !video_ctx->height) {
Error("codec/video: ffmpeg/libav buggy: width or height zero\n");
}
decoder->GetFormatDone = 1;
return Video_get_format(decoder->HwDecoder, video_ctx, fmt);
}
@@ -143,11 +174,15 @@ static int Codec_get_buffer(AVCodecContext * video_ctx, AVFrame * frame)
VideoDecoder *decoder;
decoder = video_ctx->opaque;
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54,86,100)
// ffmpeg has this already fixed
// libav 0.8.5 53.35.0 still needs this
#endif
if (!decoder->GetFormatDone) { // get_format missing
enum PixelFormat fmts[2];
fprintf(stderr, "codec: buggy ffmpeg/libav\n");
Warning(_("codec: buggy ffmpeg/libav\n"));
fprintf(stderr, "codec: buggy libav, use ffmpeg\n");
Warning(_("codec: buggy libav, use ffmpeg\n"));
fmts[0] = video_ctx->pix_fmt;
fmts[1] = PIX_FMT_NONE;
Codec_get_format(video_ctx, fmts);
@@ -160,7 +195,7 @@ static int Codec_get_buffer(AVCodecContext * video_ctx, AVFrame * frame)
unsigned surface;
struct vdpau_render_state *vrs;
surface = VideoGetSurface(decoder->HwDecoder);
surface = VideoGetSurface(decoder->HwDecoder, video_ctx);
vrs = av_mallocz(sizeof(struct vdpau_render_state));
vrs->surface = surface;
@@ -189,7 +224,7 @@ static int Codec_get_buffer(AVCodecContext * video_ctx, AVFrame * frame)
if (video_ctx->hwaccel_context) {
unsigned surface;
surface = VideoGetSurface(decoder->HwDecoder);
surface = VideoGetSurface(decoder->HwDecoder, video_ctx);
//Debug(3, "codec: use surface %#010x\n", surface);
@@ -406,15 +441,18 @@ void CodecVideoOpen(VideoDecoder * decoder, const char *name, int codec_id)
decoder->VideoCtx->opaque = decoder; // our structure
Debug(3, "codec: video '%s'\n", decoder->VideoCtx->codec_name);
if (codec_id == CODEC_ID_H264) {
if (codec_id == AV_CODEC_ID_H264) {
// 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_BIDIR;
}
if (video_codec->capabilities & CODEC_CAP_TRUNCATED) {
Debug(3, "codec: video can use truncated packets\n");
#ifndef USE_MPEG_COMPLETE
// we send incomplete frames, for old PES recordings
// this breaks the decoder for some stations
decoder->VideoCtx->flags |= CODEC_FLAG_TRUNCATED;
#endif
}
// FIXME: own memory management for video frames.
if (video_codec->capabilities & CODEC_CAP_DR1) {
@@ -445,7 +483,7 @@ void CodecVideoOpen(VideoDecoder * decoder, const char *name, int codec_id)
} else {
decoder->VideoCtx->get_format = Codec_get_format;
decoder->VideoCtx->hwaccel_context =
VideoGetVaapiContext(decoder->HwDecoder);
VideoGetHwAccelContext(decoder->HwDecoder);
}
// our pixel format video hardware decoder hook
@@ -484,8 +522,8 @@ void CodecVideoClose(VideoDecoder * video_decoder)
if (video_decoder->VideoCtx) {
pthread_mutex_lock(&CodecLockMutex);
avcodec_close(video_decoder->VideoCtx);
pthread_mutex_unlock(&CodecLockMutex);
av_freep(&video_decoder->VideoCtx);
pthread_mutex_unlock(&CodecLockMutex);
}
}
@@ -619,14 +657,27 @@ struct _audio_decoder_
AVCodec *AudioCodec; ///< audio codec
AVCodecContext *AudioCtx; ///< audio codec context
int PassthroughAC3; ///< current ac-3 pass-through
char Passthrough; ///< current pass-through flags
int SampleRate; ///< current stream sample rate
int Channels; ///< current stream channels
int HwSampleRate; ///< hw sample rate
int HwChannels; ///< hw channels
#ifndef USE_SWRESAMPLE
ReSampleContext *ReSample; ///< audio resampling context
#endif
#ifdef USE_SWRESAMPLE
#if LIBSWRESAMPLE_VERSION_INT < AV_VERSION_INT(0, 15, 100)
struct SwrContext *Resample; ///< audio software resample context
#else
SwrContext *Resample; ///< audio software resample context
#endif
#endif
uint16_t Spdif[24576 / 2]; ///< SPDIF output buffer
int SpdifIndex; ///< index into SPDIF output buffer
int SpdifCount; ///< SPDIF repeat counter
int64_t LastDelay; ///< last delay
struct timespec LastTime; ///< last time
@@ -636,6 +687,7 @@ struct _audio_decoder_
int DriftCorr; ///< audio drift correction value
int DriftFrac; ///< audio drift fraction for ac3
#ifndef USE_SWRESAMPLE
struct AVResampleContext *AvResample; ///< second audio resample context
#define MAX_CHANNELS 8 ///< max number of channels supported
int16_t *Buffer[MAX_CHANNELS]; ///< deinterleave sample buffers
@@ -643,24 +695,35 @@ struct _audio_decoder_
int16_t *Remain[MAX_CHANNELS]; ///< filter remaining samples
int RemainSize; ///< size of remain buffer
int RemainCount; ///< number of remaining samples
#endif
};
///
/// IEC Data type enumeration.
///
enum IEC61937
{
IEC61937_AC3 = 0x01, ///< AC-3 data
// FIXME: more data types
IEC61937_EAC3 = 0x15, ///< E-AC-3 data
};
#ifdef USE_AUDIO_DRIFT_CORRECTION
#define CORRECT_PCM 1 ///< do PCM audio-drift correction
#define CORRECT_AC3 2 ///< do AC-3 audio-drift correction
static char CodecAudioDrift; ///< flag: enable audio-drift correction
#else
static const int CodecAudioDrift = 0;
#endif
#ifdef USE_PASSTHROUGH
//static char CodecPassthroughPCM; ///< pass pcm through (unsupported)
static char CodecPassthroughAC3; ///< pass ac3 through
//static char CodecPassthroughDTS; ///< pass dts through (unsupported)
//static char CodecPassthroughMPA; ///< pass mpa through (unsupported)
///
/// Pass-through flags: CodecPCM, CodecAC3, CodecEAC3, ...
///
static char CodecPassthrough;
#else
static const int CodecPassthroughAC3 = 0;
static const int CodecPassthrough = 0;
#endif
static char CodecDownmix; ///< enable ac-3 downmix
static char CodecDownmix; ///< enable AC-3 decoder downmix
/**
** Allocate a new audio decoder context.
@@ -715,10 +778,16 @@ void CodecAudioOpen(AudioDecoder * audio_decoder, const char *name,
}
if (CodecDownmix) {
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(53,61,100) || FF_API_REQUEST_CHANNELS
audio_decoder->AudioCtx->request_channels = 2;
#endif
audio_decoder->AudioCtx->request_channel_layout =
AV_CH_LAYOUT_STEREO_DOWNMIX;
}
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53,61,100)
// this has no effect
// audio_decoder->AudioCtx->request_sample_fmt = AV_SAMPLE_FMT_S16;
#endif
pthread_mutex_lock(&CodecLockMutex);
// open codec
#if LIBAVCODEC_VERSION_INT <= AV_VERSION_INT(53,5,0)
@@ -765,6 +834,7 @@ void CodecAudioOpen(AudioDecoder * audio_decoder, const char *name,
void CodecAudioClose(AudioDecoder * audio_decoder)
{
// FIXME: output any buffered data
#ifndef USE_SWRESAMPLE
if (audio_decoder->AvResample) {
int ch;
@@ -784,23 +854,29 @@ void CodecAudioClose(AudioDecoder * audio_decoder)
audio_resample_close(audio_decoder->ReSample);
audio_decoder->ReSample = NULL;
}
#endif
#ifdef USE_SWRESAMPLE
if (audio_decoder->Resample) {
swr_free(&audio_decoder->Resample);
}
#endif
if (audio_decoder->AudioCtx) {
pthread_mutex_lock(&CodecLockMutex);
avcodec_close(audio_decoder->AudioCtx);
pthread_mutex_unlock(&CodecLockMutex);
av_freep(&audio_decoder->AudioCtx);
pthread_mutex_unlock(&CodecLockMutex);
}
}
/**
** Set audio drift correction.
**
** @param mask enable mask (PCM, AC3)
** @param mask enable mask (PCM, AC-3)
*/
void CodecSetAudioDrift(int mask)
{
#ifdef USE_AUDIO_DRIFT_CORRECTION
CodecAudioDrift = mask & 3;
CodecAudioDrift = mask & (CORRECT_PCM | CORRECT_AC3);
#endif
(void)mask;
}
@@ -808,12 +884,12 @@ void CodecSetAudioDrift(int mask)
/**
** Set audio pass-through.
**
** @param mask enable mask (PCM, AC3)
** @param mask enable mask (PCM, AC-3, E-AC-3)
*/
void CodecSetAudioPassthrough(int mask)
{
#ifdef USE_PASSTHROUGH
CodecPassthroughAC3 = mask & 1 ? 1 : 0;
CodecPassthrough = mask & (CodecPCM | CodecAC3 | CodecEAC3);
#endif
(void)mask;
}
@@ -892,6 +968,195 @@ static void CodecReorderAudioFrame(int16_t * buf, int size, int channels)
}
}
/**
** Handle audio format changes helper.
**
** @param audio_decoder audio decoder data
** @param[out] passthrough pass-through output
*/
static int CodecAudioUpdateHelper(AudioDecoder * audio_decoder,
int *passthrough)
{
const AVCodecContext *audio_ctx;
int err;
audio_ctx = audio_decoder->AudioCtx;
Debug(3, "codec/audio: format change %s %dHz *%d channels%s%s%s%s%s\n",
av_get_sample_fmt_name(audio_ctx->sample_fmt), audio_ctx->sample_rate,
audio_ctx->channels, CodecPassthrough & CodecPCM ? " PCM" : "",
CodecPassthrough & CodecMPA ? " MPA" : "",
CodecPassthrough & CodecAC3 ? " AC-3" : "",
CodecPassthrough & CodecEAC3 ? " E-AC-3" : "",
CodecPassthrough ? " pass-through" : "");
*passthrough = 0;
audio_decoder->SampleRate = audio_ctx->sample_rate;
audio_decoder->HwSampleRate = audio_ctx->sample_rate;
audio_decoder->Channels = audio_ctx->channels;
audio_decoder->HwChannels = audio_ctx->channels;
audio_decoder->Passthrough = CodecPassthrough;
// SPDIF/HDMI pass-through
if ((CodecPassthrough & CodecAC3 && audio_ctx->codec_id == AV_CODEC_ID_AC3)
|| (CodecPassthrough & CodecEAC3
&& audio_ctx->codec_id == AV_CODEC_ID_EAC3)) {
if (audio_ctx->codec_id == AV_CODEC_ID_EAC3) {
// E-AC-3 over HDMI some receivers need HBR
audio_decoder->HwSampleRate *= 4;
}
audio_decoder->HwChannels = 2;
audio_decoder->SpdifIndex = 0; // reset buffer
audio_decoder->SpdifCount = 0;
*passthrough = 1;
}
// channels/sample-rate not support?
if ((err =
AudioSetup(&audio_decoder->HwSampleRate,
&audio_decoder->HwChannels, *passthrough))) {
// try E-AC-3 none HBR
audio_decoder->HwSampleRate /= 4;
if (audio_ctx->codec_id != AV_CODEC_ID_EAC3
|| (err =
AudioSetup(&audio_decoder->HwSampleRate,
&audio_decoder->HwChannels, *passthrough))) {
Debug(3, "codec/audio: audio setup error\n");
// FIXME: handle errors
audio_decoder->HwChannels = 0;
audio_decoder->HwSampleRate = 0;
return err;
}
}
Debug(3, "codec/audio: resample %s %dHz *%d -> %s %dHz *%d\n",
av_get_sample_fmt_name(audio_ctx->sample_fmt), audio_ctx->sample_rate,
audio_ctx->channels, av_get_sample_fmt_name(AV_SAMPLE_FMT_S16),
audio_decoder->HwSampleRate, audio_decoder->HwChannels);
return 0;
}
/**
** Audio pass-through decoder helper.
**
** @param audio_decoder audio decoder data
** @param avpkt undecoded audio packet
*/
static int CodecAudioPassthroughHelper(AudioDecoder * audio_decoder,
const AVPacket * avpkt)
{
#ifdef USE_PASSTHROUGH
const AVCodecContext *audio_ctx;
audio_ctx = audio_decoder->AudioCtx;
// SPDIF/HDMI passthrough
if (CodecPassthrough & CodecAC3 && audio_ctx->codec_id == AV_CODEC_ID_AC3) {
uint16_t *spdif;
int spdif_sz;
spdif = audio_decoder->Spdif;
spdif_sz = 6144;
#ifdef USE_AC3_DRIFT_CORRECTION
// FIXME: this works with some TVs/AVReceivers
// FIXME: write burst size drift correction, which should work with all
if (CodecAudioDrift & CORRECT_AC3) {
int x;
x = (audio_decoder->DriftFrac +
(audio_decoder->DriftCorr * spdif_sz)) / (10 *
audio_decoder->HwSampleRate * 100);
audio_decoder->DriftFrac =
(audio_decoder->DriftFrac +
(audio_decoder->DriftCorr * spdif_sz)) % (10 *
audio_decoder->HwSampleRate * 100);
// round to word border
x *= audio_decoder->HwChannels * 4;
if (x < -64) { // limit correction
x = -64;
} else if (x > 64) {
x = 64;
}
spdif_sz += x;
}
#endif
// build SPDIF header and append A52 audio to it
// avpkt is the original data
if (spdif_sz < avpkt->size + 8) {
Error(_("codec/audio: decoded data smaller than encoded\n"));
return -1;
}
spdif[0] = htole16(0xF872); // iec 61937 sync word
spdif[1] = htole16(0x4E1F);
spdif[2] = htole16(IEC61937_AC3 | (avpkt->data[5] & 0x07) << 8);
spdif[3] = htole16(avpkt->size * 8);
// copy original data for output
// FIXME: not 100% sure, if endian is correct on not intel hardware
swab(avpkt->data, spdif + 4, avpkt->size);
// FIXME: don't need to clear always
memset(spdif + 4 + avpkt->size / 2, 0, spdif_sz - 8 - avpkt->size);
// don't play with the ac-3 samples
AudioEnqueue(spdif, spdif_sz);
return 1;
}
if (CodecPassthrough & CodecEAC3
&& audio_ctx->codec_id == AV_CODEC_ID_EAC3) {
uint16_t *spdif;
int spdif_sz;
int repeat;
// build SPDIF header and append A52 audio to it
// avpkt is the original data
spdif = audio_decoder->Spdif;
spdif_sz = 24576; // 4 * 6144
if (audio_decoder->HwSampleRate == 48000) {
spdif_sz = 6144;
}
if (spdif_sz < audio_decoder->SpdifIndex + avpkt->size + 8) {
Error(_("codec/audio: decoded data smaller than encoded\n"));
return -1;
}
// check if we must pack multiple packets
repeat = 1;
if ((avpkt->data[4] & 0xc0) != 0xc0) { // fscod
static const uint8_t eac3_repeat[4] = { 6, 3, 2, 1 };
// fscod2
repeat = eac3_repeat[(avpkt->data[4] & 0x30) >> 4];
}
// fprintf(stderr, "repeat %d %d\n", repeat, avpkt->size);
// copy original data for output
// pack upto repeat EAC-3 pakets into one IEC 61937 burst
// FIXME: not 100% sure, if endian is correct on not intel hardware
swab(avpkt->data, spdif + 4 + audio_decoder->SpdifIndex, avpkt->size);
audio_decoder->SpdifIndex += avpkt->size;
if (++audio_decoder->SpdifCount < repeat) {
return 1;
}
spdif[0] = htole16(0xF872); // iec 61937 sync word
spdif[1] = htole16(0x4E1F);
spdif[2] = htole16(IEC61937_EAC3);
spdif[3] = htole16(audio_decoder->SpdifIndex * 8);
memset(spdif + 4 + audio_decoder->SpdifIndex / 2, 0,
spdif_sz - 8 - audio_decoder->SpdifIndex);
// don't play with the eac-3 samples
AudioEnqueue(spdif, spdif_sz);
audio_decoder->SpdifIndex = 0;
audio_decoder->SpdifCount = 0;
return 1;
}
#endif
return 0;
}
#ifndef USE_SWRESAMPLE
/**
** Set/update audio pts clock.
**
@@ -913,14 +1178,15 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
if (!delay) {
return;
}
clock_gettime(CLOCK_REALTIME, &nowtime);
clock_gettime(CLOCK_MONOTONIC, &nowtime);
if (!audio_decoder->LastDelay) {
audio_decoder->LastTime = nowtime;
audio_decoder->LastPTS = pts;
audio_decoder->LastDelay = delay;
audio_decoder->Drift = 0;
audio_decoder->DriftFrac = 0;
Debug(3, "codec/audio: inital delay %" PRId64 "ms\n", delay / 90);
Debug(3, "codec/audio: inital drift delay %" PRId64 "ms\n",
delay / 90);
return;
}
// collect over some time
@@ -964,8 +1230,10 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
audio_decoder->Drift = drift;
corr = (10 * audio_decoder->HwSampleRate * drift) / (90 * 1000);
// SPDIF/HDMI passthrough
if ((CodecAudioDrift & 2) && (!CodecPassthroughAC3
|| audio_decoder->AudioCtx->codec_id != CODEC_ID_AC3)) {
if ((CodecAudioDrift & CORRECT_AC3) && (!(CodecPassthrough & CodecAC3)
|| audio_decoder->AudioCtx->codec_id != AV_CODEC_ID_AC3)
&& (!(CodecPassthrough & CodecEAC3)
|| audio_decoder->AudioCtx->codec_id != AV_CODEC_ID_EAC3)) {
audio_decoder->DriftCorr = -corr;
}
@@ -1002,14 +1270,15 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
** Handle audio format changes.
**
** @param audio_decoder audio decoder data
**
** @note this is the old not good supported version
*/
static void CodecAudioUpdateFormat(AudioDecoder * audio_decoder)
{
int passthrough;
const AVCodecContext *audio_ctx;
int err;
int isAC3;
// FIXME: use swr_convert from swresample (only in ffmpeg!)
if (audio_decoder->ReSample) {
audio_resample_close(audio_decoder->ReSample);
audio_decoder->ReSample = NULL;
@@ -1021,28 +1290,8 @@ static void CodecAudioUpdateFormat(AudioDecoder * audio_decoder)
}
audio_ctx = audio_decoder->AudioCtx;
Debug(3, "codec/audio: format change %dHz %d channels %s\n",
audio_ctx->sample_rate, audio_ctx->channels,
CodecPassthroughAC3 ? "pass-through" : "");
if ((err = CodecAudioUpdateHelper(audio_decoder, &passthrough))) {
audio_decoder->SampleRate = audio_ctx->sample_rate;
audio_decoder->HwSampleRate = audio_ctx->sample_rate;
audio_decoder->Channels = audio_ctx->channels;
audio_decoder->PassthroughAC3 = CodecPassthroughAC3;
// SPDIF/HDMI passthrough
if (CodecPassthroughAC3 && audio_ctx->codec_id == CODEC_ID_AC3) {
audio_decoder->HwChannels = 2;
isAC3 = 1;
} else {
audio_decoder->HwChannels = audio_ctx->channels;
isAC3 = 0;
}
// channels not support?
if ((err =
AudioSetup(&audio_decoder->HwSampleRate,
&audio_decoder->HwChannels, isAC3))) {
Debug(3, "codec/audio: resample %dHz *%d -> %dHz *%d\n",
audio_ctx->sample_rate, audio_ctx->channels,
audio_decoder->HwSampleRate, audio_decoder->HwChannels);
@@ -1058,19 +1307,21 @@ static void CodecAudioUpdateFormat(AudioDecoder * audio_decoder)
Error(_("codec/audio: resample setup error\n"));
audio_decoder->HwChannels = 0;
audio_decoder->HwSampleRate = 0;
}
return;
}
} else {
Debug(3, "codec/audio: audio setup error\n");
// FIXME: handle errors
audio_decoder->HwChannels = 0;
audio_decoder->HwSampleRate = 0;
return;
}
if (passthrough) { // pass-through no conversion allowed
return;
}
// prepare audio drift resample
#ifdef USE_AUDIO_DRIFT_CORRECTION
if ((CodecAudioDrift & 1) && !isAC3) {
if (CodecAudioDrift & CORRECT_PCM) {
if (audio_decoder->AvResample) {
Error(_("codec/audio: overwrite resample\n"));
}
@@ -1101,7 +1352,7 @@ static void CodecAudioUpdateFormat(AudioDecoder * audio_decoder)
void CodecAudioEnqueue(AudioDecoder * audio_decoder, int16_t * data, int count)
{
#ifdef USE_AUDIO_DRIFT_CORRECTION
if ((CodecAudioDrift & 1) && audio_decoder->AvResample) {
if ((CodecAudioDrift & CORRECT_PCM) && audio_decoder->AvResample) {
int16_t buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 4 +
FF_INPUT_BUFFER_PADDING_SIZE] __attribute__ ((aligned(16)));
int16_t buftmp[MAX_CHANNELS][(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 4];
@@ -1162,12 +1413,16 @@ void CodecAudioEnqueue(AudioDecoder * audio_decoder, int16_t * data, int count)
n *= 2;
n *= audio_decoder->HwChannels;
if (!(audio_decoder->Passthrough & CodecPCM)) {
CodecReorderAudioFrame(buf, n, audio_decoder->HwChannels);
}
AudioEnqueue(buf, n);
return;
}
#endif
if (!(audio_decoder->Passthrough & CodecPCM)) {
CodecReorderAudioFrame(data, count, audio_decoder->HwChannels);
}
AudioEnqueue(data, count);
}
@@ -1189,6 +1444,7 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
audio_ctx = audio_decoder->AudioCtx;
// FIXME: don't need to decode pass-through codecs
buf_sz = sizeof(buf);
l = avcodec_decode_audio3(audio_ctx, buf, &buf_sz, (AVPacket *) avpkt);
if (avpkt->size != l) {
@@ -1202,20 +1458,12 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
}
Error(_("codec: error more than one frame data\n"));
}
#ifdef notyetFF_API_OLD_DECODE_AUDIO
// FIXME: ffmpeg git comeing
int got_frame;
avcodec_decode_audio4(audio_ctx, frame, &got_frame, avpkt);
#else
#endif
// update audio clock
if (avpkt->pts != (int64_t) AV_NOPTS_VALUE) {
CodecAudioSetClock(audio_decoder, avpkt->pts);
}
// FIXME: must first play remainings bytes, than change and play new.
if (audio_decoder->PassthroughAC3 != CodecPassthroughAC3
if (audio_decoder->Passthrough != CodecPassthrough
|| audio_decoder->SampleRate != audio_ctx->sample_rate
|| audio_decoder->Channels != audio_ctx->channels) {
CodecAudioUpdateFormat(audio_decoder);
@@ -1248,48 +1496,7 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
CodecAudioEnqueue(audio_decoder, outbuf, outlen);
}
} else {
#ifdef USE_PASSTHROUGH
// SPDIF/HDMI passthrough
if (CodecPassthroughAC3 && audio_ctx->codec_id == CODEC_ID_AC3) {
// build SPDIF header and append A52 audio to it
// avpkt is the original data
buf_sz = 6144;
#ifdef USE_AC3_DRIFT_CORRECTION
if (CodecAudioDrift & 2) {
int x;
x = (audio_decoder->DriftFrac +
(audio_decoder->DriftCorr * buf_sz)) / (10 *
audio_decoder->HwSampleRate * 100);
audio_decoder->DriftFrac =
(audio_decoder->DriftFrac +
(audio_decoder->DriftCorr * buf_sz)) % (10 *
audio_decoder->HwSampleRate * 100);
x *= audio_decoder->HwChannels * 4;
if (x < -64) { // limit correction
x = -64;
} else if (x > 64) {
x = 64;
}
buf_sz += x;
}
#endif
if (buf_sz < avpkt->size + 8) {
Error(_
("codec/audio: decoded data smaller than encoded\n"));
return;
}
// copy original data for output
// FIXME: not 100% sure, if endian is correct
buf[0] = htole16(0xF872); // iec 61937 sync word
buf[1] = htole16(0x4E1F);
buf[2] = htole16(0x01 | (avpkt->data[5] & 0x07) << 8);
buf[3] = htole16(avpkt->size * 8);
swab(avpkt->data, buf + 4, avpkt->size);
memset(buf + 4 + avpkt->size / 2, 0, buf_sz - 8 - avpkt->size);
// don't play with the ac-3 samples
AudioEnqueue(buf, buf_sz);
if (CodecAudioPassthroughHelper(audio_decoder, avpkt)) {
return;
}
#if 0
@@ -1342,13 +1549,269 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
}
// DTS HD?
// True HD?
#endif
#endif
CodecAudioEnqueue(audio_decoder, buf, buf_sz);
}
}
}
#endif
#ifdef USE_SWRESAMPLE
/**
** Set/update audio pts clock.
**
** @param audio_decoder audio decoder data
** @param pts presentation timestamp
*/
static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
{
struct timespec nowtime;
int64_t delay;
int64_t tim_diff;
int64_t pts_diff;
int drift;
int corr;
AudioSetClock(pts);
delay = AudioGetDelay();
if (!delay) {
return;
}
clock_gettime(CLOCK_MONOTONIC, &nowtime);
if (!audio_decoder->LastDelay) {
audio_decoder->LastTime = nowtime;
audio_decoder->LastPTS = pts;
audio_decoder->LastDelay = delay;
audio_decoder->Drift = 0;
audio_decoder->DriftFrac = 0;
Debug(3, "codec/audio: inital drift delay %" PRId64 "ms\n",
delay / 90);
return;
}
// collect over some time
pts_diff = pts - audio_decoder->LastPTS;
if (pts_diff < 10 * 1000 * 90) {
return;
}
tim_diff = (nowtime.tv_sec - audio_decoder->LastTime.tv_sec)
* 1000 * 1000 * 1000 + (nowtime.tv_nsec -
audio_decoder->LastTime.tv_nsec);
drift =
(tim_diff * 90) / (1000 * 1000) - pts_diff + delay -
audio_decoder->LastDelay;
// adjust rounding error
nowtime.tv_nsec -= nowtime.tv_nsec % (1000 * 1000 / 90);
audio_decoder->LastTime = nowtime;
audio_decoder->LastPTS = pts;
audio_decoder->LastDelay = delay;
if (0) {
Debug(3,
"codec/audio: interval P:%5" PRId64 "ms T:%5" PRId64 "ms D:%4"
PRId64 "ms %f %d\n", pts_diff / 90, tim_diff / (1000 * 1000),
delay / 90, drift / 90.0, audio_decoder->DriftCorr);
}
// underruns and av_resample have the same time :(((
if (abs(drift) > 10 * 90) {
// drift too big, pts changed?
Debug(3, "codec/audio: drift(%6d) %3dms reset\n",
audio_decoder->DriftCorr, drift / 90);
audio_decoder->LastDelay = 0;
#ifdef DEBUG
corr = 0; // keep gcc happy
#endif
} else {
drift += audio_decoder->Drift;
audio_decoder->Drift = drift;
corr = (10 * audio_decoder->HwSampleRate * drift) / (90 * 1000);
// SPDIF/HDMI passthrough
if ((CodecAudioDrift & CORRECT_AC3) && (!(CodecPassthrough & CodecAC3)
|| audio_decoder->AudioCtx->codec_id != AV_CODEC_ID_AC3)
&& (!(CodecPassthrough & CodecEAC3)
|| audio_decoder->AudioCtx->codec_id != AV_CODEC_ID_EAC3)) {
audio_decoder->DriftCorr = -corr;
}
if (audio_decoder->DriftCorr < -20000) { // limit correction
audio_decoder->DriftCorr = -20000;
} else if (audio_decoder->DriftCorr > 20000) {
audio_decoder->DriftCorr = 20000;
}
}
if (audio_decoder->Resample && audio_decoder->DriftCorr) {
int distance;
// try workaround for buggy ffmpeg 0.10
if (abs(audio_decoder->DriftCorr) < 2000) {
distance = (pts_diff * audio_decoder->HwSampleRate) / (900 * 1000);
} else {
distance = (pts_diff * audio_decoder->HwSampleRate) / (90 * 1000);
}
if (swr_set_compensation(audio_decoder->Resample,
audio_decoder->DriftCorr / 10, distance)) {
Debug(3, "codec/audio: swr_set_compensation failed\n");
}
}
if (1) {
static int c;
if (!(c++ % 10)) {
Debug(3, "codec/audio: drift(%6d) %8dus %5d\n",
audio_decoder->DriftCorr, drift * 1000 / 90, corr);
}
}
}
/**
** Handle audio format changes.
**
** @param audio_decoder audio decoder data
*/
static void CodecAudioUpdateFormat(AudioDecoder * audio_decoder)
{
int passthrough;
const AVCodecContext *audio_ctx;
if (CodecAudioUpdateHelper(audio_decoder, &passthrough)) {
// FIXME: handle swresample format conversions.
return;
}
if (passthrough) { // pass-through no conversion allowed
return;
}
audio_ctx = audio_decoder->AudioCtx;
#ifdef DEBUG
if (audio_ctx->sample_fmt == AV_SAMPLE_FMT_S16
&& audio_ctx->sample_rate == audio_decoder->HwSampleRate
&& !CodecAudioDrift) {
// FIXME: use Resample only, when it is needed!
fprintf(stderr, "no resample needed\n");
}
#endif
audio_decoder->Resample =
swr_alloc_set_opts(audio_decoder->Resample, audio_ctx->channel_layout,
AV_SAMPLE_FMT_S16, audio_decoder->HwSampleRate,
audio_ctx->channel_layout, audio_ctx->sample_fmt,
audio_ctx->sample_rate, 0, NULL);
if (audio_decoder->Resample) {
swr_init(audio_decoder->Resample);
} else {
Error(_("codec/audio: can't setup resample\n"));
}
}
/**
** Decode an audio packet.
**
** PTS must be handled self.
**
** @note the caller has not aligned avpkt and not cleared the end.
**
** @param audio_decoder audio decoder data
** @param avpkt audio packet
*/
void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
{
AVCodecContext *audio_ctx;
AVFrame frame;
int got_frame;
int n;
audio_ctx = audio_decoder->AudioCtx;
// FIXME: don't need to decode pass-through codecs
frame.data[0] = NULL;
n = avcodec_decode_audio4(audio_ctx, &frame, &got_frame,
(AVPacket *) avpkt);
if (n != avpkt->size) {
if (n == AVERROR(EAGAIN)) {
Error(_("codec/audio: latm\n"));
return;
}
if (n < 0) { // no audio frame could be decompressed
Error(_("codec/audio: bad audio frame\n"));
return;
}
Error(_("codec/audio: error more than one frame data\n"));
}
if (!got_frame) {
Error(_("codec/audio: no frame\n"));
return;
}
// update audio clock
if (avpkt->pts != (int64_t) AV_NOPTS_VALUE) {
CodecAudioSetClock(audio_decoder, avpkt->pts);
}
// format change
if (audio_decoder->Passthrough != CodecPassthrough
|| audio_decoder->SampleRate != audio_ctx->sample_rate
|| audio_decoder->Channels != audio_ctx->channels) {
CodecAudioUpdateFormat(audio_decoder);
}
if (!audio_decoder->HwSampleRate || !audio_decoder->HwChannels) {
return; // unsupported sample format
}
if (CodecAudioPassthroughHelper(audio_decoder, avpkt)) {
return;
}
if (0) {
char strbuf[32];
int data_sz;
int plane_sz;
data_sz =
av_samples_get_buffer_size(&plane_sz, audio_ctx->channels,
frame.nb_samples, audio_ctx->sample_fmt, 1);
fprintf(stderr, "codec/audio: sample_fmt %s\n",
av_get_sample_fmt_name(audio_ctx->sample_fmt));
av_get_channel_layout_string(strbuf, 32, audio_ctx->channels,
audio_ctx->channel_layout);
fprintf(stderr, "codec/audio: layout %s\n", strbuf);
fprintf(stderr,
"codec/audio: channels %d samples %d plane %d data %d\n",
audio_ctx->channels, frame.nb_samples, plane_sz, data_sz);
}
if (audio_decoder->Resample) {
uint8_t outbuf[8192 * 2 * 8];
uint8_t *out[1];
out[0] = outbuf;
n = swr_convert(audio_decoder->Resample, out,
sizeof(outbuf) / (2 * audio_decoder->HwChannels),
(const uint8_t **)frame.extended_data, frame.nb_samples);
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;
}
#ifdef DEBUG
// should be never reached
fprintf(stderr, "oops\n");
#endif
}
#endif
/**
** Flush the audio decoder.
**

12
codec.h
View File

@@ -1,7 +1,7 @@
///
/// @file codec.h @brief Codec module headerfile
///
/// Copyright (c) 2009 - 2012 by Johns. All Rights Reserved.
/// Copyright (c) 2009 - 2013 by Johns. All Rights Reserved.
///
/// Contributor(s):
///
@@ -23,6 +23,16 @@
/// @addtogroup Codec
/// @{
//----------------------------------------------------------------------------
// Defines
//----------------------------------------------------------------------------
#define CodecPCM 0x01 ///< PCM bit mask
#define CodecMPA 0x02 ///< MPA bit mask (planned)
#define CodecAC3 0x04 ///< AC-3 bit mask
#define CodecEAC3 0x08 ///< E-AC-3 bit mask
#define CodecDTS 0x10 ///< DTS bit mask (planned)
//----------------------------------------------------------------------------
// Typedefs
//----------------------------------------------------------------------------

View File

@@ -1,2 +0,0 @@
#!/bin/sh
exec make VDRDIR=/usr/include/vdr LIBDIR=. "$@"

1377
po/de_DE.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
///
/// @file softhddev.h @brief software HD device plugin header file.
///
/// Copyright (c) 2011 - 2012 by Johns. All Rights Reserved.
/// Copyright (c) 2011 - 2013 by Johns. All Rights Reserved.
///
/// Contributor(s):
///
@@ -95,6 +95,19 @@ extern "C"
/// Get decoder statistics
extern void GetStats(int *, int *, int *, int *);
/// C plugin scale video
extern void ScaleVideo(int, int, int, int);
/// Set Pip position
extern void PipSetPosition(int, int, int, int, int, int, int, int);
/// Pip start
extern void PipStart(int, int, int, int, int, int, int, int);
/// Pip stop
extern void PipStop(void);
/// Pip play video packet
extern int PipPlayVideo(const uint8_t *, int);
extern const char *X11DisplayName; ///< x11 display name
#ifdef __cplusplus
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -23,6 +23,7 @@
#pragma once
#define ATMO_GRAB_SERVICE "SoftHDDevice-AtmoGrabService-v1.0"
#define ATMO1_GRAB_SERVICE "SoftHDDevice-AtmoGrabService-v1.1"
#define OSD_3DMODE_SERVICE "SoftHDDevice-Osd3DModeService-v1.0"
enum
@@ -48,3 +49,17 @@ typedef struct
{
int Mode;
} SoftHDDevice_Osd3DModeService_v1_0_t;
typedef struct
{
// request/reply data
int width;
int height;
// reply data
int size;
void *img;
} SoftHDDevice_AtmoGrabService_v1_1_t;

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

@@ -2,73 +2,66 @@
# Distributed under the terms of the GNU General Public License v2
# $Header: $
EAPI="3"
EAPI="5"
inherit eutils vdr-plugin
inherit flag-o-matic toolchain-funcs vdr-plugin-2 eutils
if [[ ${PV} == "9999" ]] ; then
if [ "${PV}" = "9999" ]; then
inherit git-2
EGIT_REPO_URI="git://projects.vdr-developer.org/vdr-plugin-softhddevice.git"
KEYWORDS=""
else
SRC_URI="http://projects.vdr-developer.org/attachments/download/838/${P}.tgz"
SRC_URI="mirror://vdr-developerorg/889/${P}.tgz"
KEYWORDS="~amd64 ~x86"
fi
DESCRIPTION="A software and GPU emulated HD output device plugin for VDR."
DESCRIPTION="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"
IUSE="alsa oss vaapi vdpau opengl yaepg xscreensaver 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
RDEPEND=">=media-video/vdr-1.7
>=virtual/ffmpeg-0.7[vdpau?,vaapi?]
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] )
>=x11-libs/libxcb-1.8
x11-libs/xcb-util-wm
alsa? ( media-libs/alsa-lib )
oss? ( sys-kernel/linux-headers )
"
src_prepare() {
vdr-plugin_src_prepare
}
vdpau? ( x11-libs/libvdpau )
vaapi? ( x11-libs/libva )
opengl? ( virtual/opengl )
alsa? ( media-libs/alsa-lib )
yaepg? ( >=media-video/vdr-1.7[yaepg] )"
DEPEND="${RDEPEND}
x11-libs/xcb-util
sys-devel/gettext
virtual/pkgconfig
oss? ( sys-kernel/linux-headers )"
src_compile() {
local myconf
myconf="-DHAVE_PTHREAD_NAME"
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"
myconf+=" ALSA=$(usex alsa 1 0)"
myconf+=" OSS=$(usex oss 1 0)"
myconf+=" VDPAU=$(usex vdpau 1 0)"
myconf+=" OPENGL=$(usex opengl 1 0)"
myconf+=" VAAPI=$(usex vaapi 1 0)"
myconf+=" SCREENSAVER=$(usex xscreensaver 1 0)"
if has_version ">=media-video/ffmpeg-0.8" ; then
myconf+=" SWRESAMPLE=1"
fi
emake all CC="$(tc-getCC)" CFLAGS="${CFLAGS}" \
LDFLAGS="${LDFLAGS}" CONFIG="${myconf}" LIBDIR="." || die
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() {
vdr-plugin_src_install
vdr-plugin-2_src_install
dodoc README.txt
#dodir /etc/vdr/plugins || die
#insinto /etc/vdr/plugins
#fowners -R vdr:vdr /etc/vdr || die
#insinto /etc/conf.d
#doins vdr.softhddevice
dodoc ChangeLog README.txt
}

2164
video.c

File diff suppressed because it is too large Load Diff

39
video.h
View File

@@ -1,7 +1,7 @@
///
/// @file video.h @brief Video module header file
///
/// Copyright (c) 2009 - 2012 by Johns. All Rights Reserved.
/// Copyright (c) 2009 - 2013 by Johns. All Rights Reserved.
///
/// Contributor(s):
///
@@ -30,6 +30,9 @@
/// Video hardware decoder typedef
typedef struct _video_hw_decoder_ VideoHwDecoder;
/// Video output stream typedef
typedef struct __video_stream__ VideoStream;
//----------------------------------------------------------------------------
// Variables
//----------------------------------------------------------------------------
@@ -37,24 +40,25 @@ typedef struct _video_hw_decoder_ VideoHwDecoder;
extern char VideoHardwareDecoder; ///< flag use hardware decoder
extern char VideoIgnoreRepeatPict; ///< disable repeat pict warning
extern int VideoAudioDelay; ///< audio/video delay
extern char ConfigStartX11Server; ///< flag start the x11 server
//----------------------------------------------------------------------------
// Prototypes
//----------------------------------------------------------------------------
/// Allocate new video hardware decoder.
extern VideoHwDecoder *VideoNewHwDecoder(void);
extern VideoHwDecoder *VideoNewHwDecoder(VideoStream *);
/// Deallocate video hardware decoder.
extern void VideoDelHwDecoder(VideoHwDecoder *);
#ifdef LIBAVCODEC_VERSION
/// Get and allocate a video hardware surface.
extern unsigned VideoGetSurface(VideoHwDecoder *);
extern unsigned VideoGetSurface(VideoHwDecoder *, const AVCodecContext *);
/// Release a video hardware surface
extern void VideoReleaseSurface(VideoHwDecoder *, unsigned);
#ifdef LIBAVCODEC_VERSION
/// Callback to negotiate the PixelFormat.
extern enum PixelFormat Video_get_format(VideoHwDecoder *, AVCodecContext *,
const enum PixelFormat *);
@@ -63,8 +67,8 @@ extern enum PixelFormat Video_get_format(VideoHwDecoder *, AVCodecContext *,
extern void VideoRenderFrame(VideoHwDecoder *, const AVCodecContext *,
const AVFrame *);
/// Get ffmpeg vaapi context.
extern struct vaapi_context *VideoGetVaapiContext(VideoHwDecoder *);
/// Get hwaccel context for ffmpeg.
extern void *VideoGetHwAccelContext(VideoHwDecoder *);
#ifdef AVCODEC_VDPAU_H
/// Draw vdpau render state.
@@ -110,13 +114,16 @@ extern void VideoSetSaturation(int);
extern void VideoSetHue(int);
/// Set video output position.
extern void VideoSetOutputPosition(int, int, int, int);
extern void VideoSetOutputPosition(VideoHwDecoder *, int, int, int, int);
/// Set video mode.
extern void VideoSetVideoMode(int, int, int, int);
/// Set display format.
extern void VideoSetDisplayFormat(int);
/// Set 4:3 display format.
extern void VideoSet4to3DisplayFormat(int);
/// Set other display format.
extern void VideoSetOtherDisplayFormat(int);
/// Set video fullscreen mode.
extern void VideoSetFullscreen(int);
@@ -205,8 +212,16 @@ extern void VideoOsdExit(void); ///< Cleanup osd.
extern void VideoInit(const char *); ///< Setup video module.
extern void VideoExit(void); ///< Cleanup and exit video module.
extern int VideoPollInput(void); ///< Poll video input buffers.
extern int VideoDecodeInput(void); ///< Decode video input buffers.
extern int VideoGetBuffers(void); ///< Get number of input buffers.
/// Poll video input buffers.
extern int VideoPollInput(VideoStream *);
/// Decode video input buffers.
extern int VideoDecodeInput(VideoStream *);
/// Get number of input buffers.
extern int VideoGetBuffers(const VideoStream *);
/// Raise the frontend window
extern int VideoRaiseWindow();
/// @}