94 Commits
0.5.0 ... 0.5.2

Author SHA1 Message Date
Johns
9a2b6f860a Version 0.5.2 released. 2012-11-15 22:30:55 +01:00
10075aa501 Fix 3d OSD position. 2012-11-05 23:13:42 +01:00
Johns
cb91c779d3 Correct offsets for 3D OSD. Allow 1920x1200 OSD. 2012-11-05 12:03:50 +01:00
Johns
aad3742670 Log subtitle clear. 2012-11-01 14:12:31 +01:00
Johns
1b23074de7 Ignore empty options. 2012-10-31 10:20:07 +01:00
Johns
78015d90fb 3D update. 2012-10-30 16:53:40 +01:00
0286c434b4 Add support to change OSD for 3d SBS/TB streams. 2012-10-30 16:50:31 +01:00
Johns
6e9e641453 Comment how to change the error recognition. 2012-10-30 12:11:25 +01:00
Johns
d36e4c22b6 Removes debug output slipped into GIT. 2012-10-30 12:10:25 +01:00
Johns
7e4657e615 Use software decoder for still-pictures. 2012-10-29 23:06:00 +01:00
Johns
84e8e58c91 Don't show black picture during still-pictures. 2012-10-29 19:29:43 +01:00
Johns
141eb5cf71 Flush X11 output buffer before close. 2012-10-29 17:24:58 +01:00
Johns
a9e664ac52 Add Feature #1103: change audio without vdr restart. 2012-10-29 16:00:45 +01:00
Johns
30952face4 Fix bug #1089: vdpau wrong number of mpeg refs. 2012-10-24 15:38:09 +02:00
Johns
0519aff4d8 Removed double comment. 2012-10-19 15:38:05 +02:00
Johns
92b4203644 Fix bug: possible endless loop in pes audio parser. 2012-10-19 15:36:41 +02:00
Johns
f640ebdeb5 Report correct size in cSoftHdDevice::GetVideoSize. 2012-10-10 17:26:49 +02:00
Johns
de7c4b2a96 Workaround for bug #1069.
Option -s (start in suspended mode) does not work anymore.
2012-10-06 19:16:10 +02:00
Johns
0cf4598f68 Jpeg isn't longer used. 2012-09-15 21:40:04 +02:00
Johns
80dfa4a80f Close all filehandles before exec.
Add stillpicture debug.
Some small stillpicture fixes.
2012-09-15 21:38:54 +02:00
Johns
0a78944996 Fix bug: hue menu entry changes brightness. 2012-09-14 16:53:13 +02:00
Johns
142c3b16f6 Fix bug: didn't compile without vdpau support. 2012-09-11 00:24:27 +02:00
Johns
73fe963c36 Add picture adjustment support for vdpau. 2012-09-03 16:39:33 +02:00
Johns
a61cbcb65a Add PTS to render too slow message. 2012-08-29 17:00:36 +02:00
Johns
3df9acc034 Add number of buffered video output frames to info. 2012-08-28 19:15:11 +02:00
Johns
d9c9061a7c Reset closing only, if trickspeed is set. 2012-08-18 15:53:14 +02:00
Johns
e9fbe6b54f Need get_format for software decoder. 2012-08-17 10:35:52 +02:00
Johns
5e93fb2756 Fix bug: VA-API trickspeed. 2012-08-17 10:33:10 +02:00
Johns
e02c1fa5f9 Revert "mpeg_vdpau" back to "mpegvideo_vdpau". 2012-08-14 16:02:44 +02:00
Johns
c07ec82e6d Fix bug: Can't use software decoder with VDPAU. 2012-08-13 16:57:36 +02:00
Johns
ecb48a5d63 Resume plugin, if dummy player looses control. 2012-08-09 16:22:06 +02:00
Johns
9efc73144d Removes old audio code (!USE_AUDIORING). 2012-08-08 22:58:57 +02:00
a920da652b Osd work:
Use -DOSD_DEBUG to debug OSD.
Fix bug #909: Subtitles destroy menu.
Fix bug #1003: Subtitles overlapping.
2012-08-07 16:46:23 +02:00
Johns
9ec077ec8a VA-API/XvBA backend improvements. 2012-07-27 19:15:48 +02:00
Johns
8b0d8d8446 Free used X11 resources colormap, pixmap, cursor. 2012-07-25 16:07:36 +02:00
Johns
15583a79c4 FreeBSD compatibility fix. 2012-07-09 17:17:16 +02:00
Johns
2cdce610d6 Fix bug: spelling USE_VAPI wrong, missing function. 2012-07-06 00:04:08 +02:00
Johns
2d6d151b85 Fix compiler warnings. 2012-07-05 23:59:28 +02:00
Johns
ca4f519a1f Force ffmpeg with hardware codec support. 2012-07-05 17:10:05 +02:00
Johns
583b6f246e Release Version 0.5.1 2012-07-03 16:36:53 +02:00
Johns
e6ce7832ba Add commandline support to disable hardware decoder. 2012-07-03 15:48:44 +02:00
Johns
696bb8e934 Display frame statistics in plugin menu. 2012-07-02 17:05:36 +02:00
Johns
3bb7782d40 Remove not working hotkeys from setup menu. 2012-07-02 15:20:14 +02:00
Johns
b5162bae5c Fix bug: 100% CPU use during playback. 2012-06-30 15:40:33 +02:00
Johns
d486fb2ca1 Fix bug: audio use 100% CPU during pause. 2012-06-30 00:19:36 +02:00
Johns
73d65968ae Remove video display format until it is working. 2012-06-29 15:23:17 +02:00
Johns
3be69730f0 Suggested change. 2012-06-29 15:13:38 +02:00
Johns
6f1c4d6ef6 Video_get_format AudioVideoReady feeds old PTS. 2012-06-27 21:47:30 +02:00
Johns
6aa8601f7d Guard audio skip against old PTS values. 2012-06-27 21:22:25 +02:00
Johns
0f62a521f4 Improved audio skip, after channel switch. 2012-06-25 17:30:30 +02:00
Johns
57af986367 Setup add preview of collapsed tree. 2012-06-23 16:47:04 +02:00
Johns
a2311748ca Removed gcc 4.6 warnings.
avcodec_flush_buffers crash fix.
2012-06-22 19:28:48 +02:00
Johns
2c5a14ae4a Removed gcc 4.6 warnings. Va sync experiment. 2012-06-22 19:27:15 +02:00
Johns
ed1e16dccf Removed warnings and old code. 2012-06-22 19:12:00 +02:00
Johns
da9886e9f1 Fix bug: dvd plugin times out. Readme update. 2012-06-08 15:27:42 +02:00
Johns
32527f832e Makes OSD size configurable. 2012-05-21 15:34:33 +02:00
Johns
57bbd02c57 Fix bug: Black screen is sometimes not shown. 2012-05-17 16:52:08 +02:00
Johns
940849d03f Safer 4:3 detection, 4:3 crop correction. 2012-05-17 16:50:40 +02:00
Johns
c112b850d8 Fix bug: 100% cpu use.
Fix bug: audio/video out of sync after jump in recordings.
2012-05-16 20:35:35 +02:00
Johns
752ee356fa Poll input buffers, if display buffers are full. 2012-05-13 18:33:24 +02:00
Johns
43e70b6a3f Reduce errors during suspend mode. 2012-05-13 16:58:45 +02:00
Johns
541754a619 Support display with non-square pixels. 2012-05-10 16:03:56 +02:00
Johns
3772b2160c Initial ADTS (AAC+) support. 2012-05-09 20:16:46 +02:00
Johns
465c68d839 Fix bug #959: log flooded with service messages. 2012-05-03 15:26:58 +02:00
aca508114b Adds VDR DFAtmo Plugin support. 2012-04-30 14:47:08 +02:00
Johns
49ae1c7211 Fix bug: PTS are 1/90ms and use AudioVideoDelay. 2012-04-30 13:56:26 +02:00
Johns
0cf110da81 Less logging. 2012-04-28 12:38:41 +02:00
Johns
8d5ff6f6fb Skip audio to sync with video. 2012-04-28 12:24:03 +02:00
Johns
5456164dce Mute pass-through, if volume is 0. 2012-04-27 12:31:40 +02:00
Johns
6dd7c2680a Skip audio sync while trick play. 2012-04-26 15:33:51 +02:00
Johns
3b5c1adef2 Fix bug: don't normalize or compress AC3 samples. 2012-04-24 16:02:07 +02:00
Johns
47d840bbff Force black picture after start or suspend. 2012-04-22 21:01:34 +02:00
Johns
207871fd9b Make audio ring buffer size a multiple of 3,5,7,8. 2012-04-22 17:17:54 +02:00
Johns
ebe0beb400 Add upmix from 5 to 6 channels. 2012-04-21 16:45:56 +02:00
Johns
93ddd26a4a Fix bug: alloca wrong size for audio buffer. 2012-04-21 15:47:50 +02:00
Johns
e30e1e5aad Handle jump in stream like stream start. 2012-04-21 12:59:04 +02:00
Johns
d26c34f34f Always compile audio drift correction.
Add audio drift correction configuration to the setup.
2012-04-20 18:28:25 +02:00
24a8c7f763 Add support for svdr command "stat". 2012-04-20 16:51:04 +02:00
Johns
3e39ffd5e0 New audio ring buffer code, now OSS part. 2012-04-20 16:05:40 +02:00
Johns
53f22a2ed2 Made showing black picture configurable. 2012-04-20 15:40:14 +02:00
Johns
44ca71fedb Adds audio normalize support. 2012-04-19 16:01:20 +02:00
Johns
8039e8ae04 New audio filters next part. 2012-04-19 00:47:34 +02:00
Johns
79e78bf235 Show black picture, if no video stream available.
New audio ring code.
New audio filters (first part).
2012-04-17 16:45:27 +02:00
Johns
c9ef8b759a Fix bug: autocrop toggle didn't work. 2012-04-15 23:03:40 +02:00
Johns
80db7c6656 Setup split into foldable sections. 2012-04-15 22:59:52 +02:00
Johns
3ba18d8720 Add -D option to getopt. 2012-04-15 14:46:57 +02:00
Johns
2ffcb874bb Adds show cursor on mouse move + hide after 200ms. 2012-04-14 21:58:14 +02:00
Johns
5b765f02bd Add Hot-key support for auto-crop enable/disable. 2012-04-14 21:25:44 +02:00
Johns
2c52955ac0 Adds detached start mode. 2012-04-14 21:16:01 +02:00
Johns
09d8588588 Fix buf: VDPAU looses preemption callback. 2012-04-12 15:38:22 +02:00
Johns
71f786711b Fix bug: X11 server keeps sending USR1 signals. 2012-04-12 15:37:19 +02:00
Johns
deea34eb5e Show message for hot-keys. 2012-04-11 18:20:08 +02:00
Johns
1f14af6590 Fix bug: playback errors with old PES recordings. 2012-04-11 12:16:00 +02:00
Johns
aeae505bd4 Adds Hot-key support for 4:3 zoom modes. 2012-04-11 12:15:12 +02:00
18 changed files with 3709 additions and 1461 deletions

2
.gitignore vendored
View File

@@ -4,7 +4,7 @@
.*.swp
.gdb_history
# work directory
chaos
.chaos
# generated files
.dependencies
libvdr-softhddevice.so*

View File

@@ -1,3 +1,98 @@
User johns
Date: Thu Nov 15 22:28:55 CET 2012
Release Version 0.5.2
User maverick-me
Date: Mon Nov 5 23:13:42 CET 2012
Fix 3d OSD position.
User maverick-me
Date: Tue Oct 30 16:50:25 CET 2012
Add support to change the OSD for 3d SBS/TB streams.
User johns
Date: Tue Oct 30 12:11:25 CEST 2012
Use software decoder for still-pictures.
Add Feature #1103: change audio devices without vdr restart.
Fix bug #1089: Vdpau decoder used wrong number of mpeg reference frames.
Fix bug: with some streams endless loop in pes audio parser.
Report correct video size in cSoftHdDevice::GetVideoSize.
Add picture adjustment support for vdpau.
Revert "mpeg_vdpau" back to "mpegvideo_vdpau".
Fix bug: Can't use software decoder with VDPAU.
Resume plugin, if suspend control stops.
Removes old audio code (!USE_AUDIORING).
Use -DOSD_DEBUG to debug OSD.
User arttupii
Date: Tue Aug 7 16:46:23 2012 +0200
Fix bug #909: Subtitles destroy menu.
Fix bug #1003: Subtitles overlapping.
User johns
Date: Fri Jul 27 19:15:48 CEST 2012
Free used X11 resources colormap, pixmap, cursor.
Fix bug: spelling USE_VAPI wrong, missing functions.
User johns
Date: Tue Jul 3 16:35:46 CEST 2012
Release Version 0.5.1
Add commandline support to disable hardware decoder.
Display frame statistics in plugin menu.
Fix bug: 100% CPU use during playback.
Fix bug: audio use 100% CPU during pause.
Guard audio skip against old PTS values.
Improved audio skip, after channel switch.
Setup add preview of collapsed tree.
Fix bug: dvd plugin times out.
Makes OSD size configurable.
Support display with non-square pixels.
Initial ADTS (AAC+) support.
Fix bug #959: log flooded with service messages.
User durchflieger
Date: Mon Apr 30 14:46:51 CEST 2012
Adds VDR DFAtmo Plugin support.
User johns
Date: Mon Apr 30 13:56:26 CEST 2012
Fix bug: don't normalize or compress pass-through samples.
Make audio ring buffer size a multiple of 3,5,7,8.
Add reset ring buffer support.
Fix bug: alloca wrong size for audio buffer.
Handle jump in stream like stream start.
Always compile audio drift correction.
Add audio drift correction configuration to the setup.
User mini73
Date: Fri Apr 20 16:51:14 CEST 2012
Add support for svdr command "stat".
User johns
Date: Fri Apr 20 16:05:40 CEST 2012
Made showing black picture configurable.
Show black picture, if no video stream is available.
Setup split into foldable sections.
Adds show cursor on pointer move and hide after 200ms.
Adds Hot-key support for auto-crop enable/disable/toggle.
Adds detached start mode.
Fix bug: VDPAU looses preemption callback.
Fix bug: X11 server keeps sending USR1 signals, which confuses suspend.
Show message for hot-keys.
Fix bug: playback errors with old PES recordings.
Adds Hot-key support for 4:3 zoom modes.
User johns
Date: Sat Apr 7 20:21:16 CEST 2012

View File

@@ -18,9 +18,7 @@ GIT_REV = $(shell git describe --always 2>/dev/null)
### Configuration (edit this for your needs)
CONFIG := #-DDEBUG
#CONFIG += -DUSE_AUDIO_DRIFT_CORRECTION # build new audio drift code
#CONFIG += -DUSE_AC3_DRIFT_CORRECTION # build new ac-3 drift code
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
@@ -47,7 +45,7 @@ TMPDIR ?= /tmp
### Make sure that necessary options are included:
include $(VDRDIR)/Make.global
-include $(VDRDIR)/Make.global
### Allow user defined options to overwrite defaults:

View File

@@ -26,19 +26,19 @@ A software and GPU emulated HD output device plugin for VDR.
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 Software deinterlacer Bob (VA-API only)
o Autocrop
o Grab image (VDPAU only)
o Suspend
o Letterbox, Stretch and Center cut-out video display modes
o atmo light support with plugin http://github.com/durchflieger/DFAtmo
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: software volume, software channel resample
o planned: atmo light support
To compile you must have the 'requires' installed.
@@ -108,12 +108,17 @@ Setup: /etc/vdr/setup.conf
------
Following is supported:
softhddevice.MakePrimary = 1
softhddevice.MakePrimary = 0
0 = no change, 1 make softhddevice primary at start
softhddevice.HideMainMenuEntry = 0
0 = show softhddevice main menu entry, 1 = hide entry
softhddevice.Osd.Width = 0
0 = auto (=display, unscaled) n = fixed osd size scaled for display
softhddevice.Osd.Height = 0
0 = auto (=display, unscaled) n = fixed osd size scaled for display
<res> of the next parameters is 576i, 720p, 1080i_fake or 1080i.
1080i_fake is 1280x1080 or 1440x1080
1080i is "real" 1920x1080
@@ -157,6 +162,29 @@ Setup: /etc/vdr/setup.conf
0 = none, 1 = downmix
downmix AC-3 to stero.
softhddevice.AudioSoftvol = 0
0 = off, use hardware volume control
1 = on, use software volume control
softhddevice.AudioNormalize = 0
0 = off, 1 = enable audio normalize
softhddevice.AudioMaxNormalize = 0
maximal volume factor/1000 of the normalize filter
softhddevice.AudioCompression = 0
0 = off, 1 = enable audio compression
softhddevice.AudioMaxCompression = 0
maximal volume factor/1000 of the compression filter
softhddevice.AudioStereoDescent = 0
reduce volume level (/1000) for stereo sources
softhddevice.AudioBufferTime = 0
0 = default (336 ms)
1 - 1000 = size of the buffer in ms
softhddevice.AutoCrop.Interval = 0
0 disables auto-crop
n each 'n' frames auto-crop is checked.
@@ -196,6 +224,10 @@ Setup: /etc/vdr/setup.conf
0 disable soft start of audio/video sync
1 enable soft start of audio/video sync
softhddevice.BlackPicture = 0
0 disable black picture during channel switch
1 enable black picture during channel switch
VideoDisplayFormat = ?
0 pan and scan
1 letter box
@@ -248,6 +280,18 @@ Keymacros:
@softhddevice Blue 1 0 disable pass-through
@softhddevice Blue 1 1 enable pass-through
@softhddevice Blue 1 2 toggle pass-through
@softhddevice Blue 1 3 decrease audio delay by 10ms
@softhddevice Blue 1 4 increase audio delay by 10ms
@softhddevice Blue 2 0 disable fullscreen
@softhddevice Blue 2 1 enable fullscreen
@softhddevice Blue 2 2 toggle fullscreen
@softhddevice Blue 2 3 disable auto-crop
@softhddevice Blue 2 4 enable auto-crop
@softhddevice Blue 2 5 toggle auto-crop
@softhddevice Blue 3 0 stretch 4:3 to 16:9
@softhddevice Blue 3 1 letter box 4:3 in 16:9
@softhddevice Blue 3 2 center cut-out 4:3 to 16:9
@softhddevice Blue 3 9 rotate 4:3 to 16:9 zoom mode
Running:
--------
@@ -259,6 +303,11 @@ Warning:
--------
libav is not supported, expect many bugs with it.
Known Bugs:
-----------
VA-API doesn't v-sync 1080i streams
vdr-image not working
Requires:
---------
media-video/ffmpeg (version >=0.7)

14
Todo
View File

@@ -37,9 +37,13 @@ video:
radio no need to wait on video buffers
starting with radio and own X11 server, shows no video
some low-bandwidth tv channels have hiccups.
check start with 24Hz display rate
crash with ffmpeg without vaapi and vdpau.
vdpau:
software decoder path not working
software deinterlace path not working.
OSD looses transparency, during channel switch.
OSD looses transparency, while moving cut marks.
libva:
yaepghd (VaapiSetOutputPosition) support
@@ -49,6 +53,7 @@ libva:
still many: (workaround export NO_MPEG_HW=1)
[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.
libva: branch vaapi-ext / staging
add support for vaapi-ext / staging
@@ -73,10 +78,8 @@ x11:
support embedded mode
audio:
Combine alsa+oss ringbuffer code.
Make alsa thread/polled and oss thread/polled output module runtime
selectable.
software volume support (could be done with asound.conf)
Mute should do a real mute and not only set volume to zero.
Starting suspended and muted, didn't register the mute.
Relaxed audio sync checks at end of packet and already in sync
@@ -84,12 +87,10 @@ audio:
only wait for video start, if video is running.
Not primary device, don't use and block audio/video.
multiple open of audio device, reduce them.
Not all channel conversions are written (f.e. 2->3 ... 5->6 ...)
audio/alsa:
better downmix of >2 channels on 2 channel hardware
remix support of unsupported sample rates
libav supports only resample of mono to 2 channels
ffmpeg didn't support resample of 5 to 2 channels
audio/oss:
alsa oss emulation mixer "pcm" not working
@@ -124,7 +125,6 @@ future features (not planed for 1.0 - 1.5)
video out with opengl
video out with xvba
software decoder for xv / opengl
atmolight support
multistream handling
pip support
save and use auto-crop with channel zapping

2369
audio.c

File diff suppressed because it is too large Load Diff

View File

@@ -42,6 +42,10 @@ extern void AudioPlay(void); ///< play audio
extern void AudioPause(void); ///< pause audio
extern void AudioSetBufferTime(int); ///< set audio buffer time
extern void AudioSetSoftvol(int); ///< enable/disable softvol
extern void AudioSetNormalize(int, int); ///< set normalize parameters
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

113
codec.c
View File

@@ -33,11 +33,17 @@
/// compile with passthrough support (stable, ac3 only)
#define USE_PASSTHROUGH
/// compile audio drift correction support (experimental)
#define noUSE_AUDIO_DRIFT_CORRECTION
#define USE_AUDIO_DRIFT_CORRECTION
/// compile AC3 audio drift correction support (experimental)
#define USE_AC3_DRIFT_CORRECTION
#include <stdio.h>
#include <unistd.h>
#ifdef __FreeBSD__
#include <sys/endian.h>
#else
#include <endian.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
@@ -357,22 +363,6 @@ void CodecVideoOpen(VideoDecoder * decoder, const char *name, int codec_id)
if (decoder->VideoCtx) {
Error(_("codec: missing close\n"));
}
//
// ffmpeg compatibility hack
//
#if 1 || (LIBAVCODEC_VERSION_INT <= AV_VERSION_INT(52,96,0))
if (name) {
if (!strcmp(name, "h264video_vdpau")) {
name = "h264_vdpau";
} else if (!strcmp(name, "mpeg4video_vdpau")) {
name = "mpeg4_vdpau";
} else if (!strcmp(name, "vc1video_vdpau")) {
name = "vc1_vdpau";
} else if (!strcmp(name, "wmv3video_vdpau")) {
name = "wmv3_vdpau";
}
}
#endif
if (name && (video_codec = avcodec_find_decoder_by_name(name))) {
Debug(3, "codec: vdpau decoder found\n");
@@ -395,6 +385,17 @@ void CodecVideoOpen(VideoDecoder * decoder, const char *name, int codec_id)
Fatal(_("codec: can't open video codec!\n"));
}
#else
if (video_codec->capabilities & (CODEC_CAP_HWACCEL_VDPAU |
CODEC_CAP_HWACCEL)) {
Debug(3, "codec: video mpeg hack active\n");
// HACK around badly placed checks in mpeg_mc_decode_init
// taken from mplayer vd_ffmpeg.c
decoder->VideoCtx->slice_flags =
SLICE_FLAG_CODED_ORDER | SLICE_FLAG_ALLOW_FIELD;
decoder->VideoCtx->thread_count = 1;
decoder->VideoCtx->active_thread_type = 0;
}
if (avcodec_open2(decoder->VideoCtx, video_codec, NULL) < 0) {
pthread_mutex_unlock(&CodecLockMutex);
Fatal(_("codec: can't open video codec!\n"));
@@ -412,7 +413,7 @@ void CodecVideoOpen(VideoDecoder * decoder, const char *name, int codec_id)
}
if (video_codec->capabilities & CODEC_CAP_TRUNCATED) {
Debug(3, "codec: video can use truncated packets\n");
// we do not send complete frames
// we send incomplete frames, for old PES recordings
decoder->VideoCtx->flags |= CODEC_FLAG_TRUNCATED;
}
// FIXME: own memory management for video frames.
@@ -428,6 +429,7 @@ void CodecVideoOpen(VideoDecoder * decoder, const char *name, int codec_id)
}
#endif
//decoder->VideoCtx->debug = FF_DEBUG_STARTCODE;
//decoder->VideoCtx->err_recognition |= AV_EF_EXPLODE;
if (video_codec->capabilities & CODEC_CAP_HWACCEL_VDPAU) {
// FIXME: get_format never called.
@@ -441,6 +443,7 @@ void CodecVideoOpen(VideoDecoder * decoder, const char *name, int codec_id)
decoder->VideoCtx->thread_count = 1;
decoder->VideoCtx->active_thread_type = 0;
} else {
decoder->VideoCtx->get_format = Codec_get_format;
decoder->VideoCtx->hwaccel_context =
VideoGetVaapiContext(decoder->HwDecoder);
}
@@ -547,6 +550,11 @@ void CodecVideoDecode(VideoDecoder * decoder, const AVPacket * avpkt)
Debug(4, "%s: %p %d -> %d %d\n", __FUNCTION__, pkt->data, pkt->size, used,
got_frame);
if (used < 0) {
Debug(3, "codec: bad video frame\n");
return;
}
if (got_frame) { // frame completed
//DisplayPts(video_ctx, frame);
VideoRenderFrame(decoder->HwDecoder, video_ctx, frame);
@@ -557,6 +565,9 @@ void CodecVideoDecode(VideoDecoder * decoder, const AVPacket * avpkt)
Debug(4, "codec: %8d incomplete interlaced frame %d bytes used\n",
video_ctx->frame_number, used);
}
#if 1
// old code to support truncated or multi frame packets
if (used != pkt->size) {
// ffmpeg 0.8.7 dislikes our seq_end_h264 and enters endless loop here
if (used == 0 && pkt->size == 5 && pkt->data[4] == 0x0A) {
@@ -570,10 +581,11 @@ void CodecVideoDecode(VideoDecoder * decoder, const AVPacket * avpkt)
used, pkt->size);
pkt->size -= used;
pkt->data += used;
// FIXME: align problem?
goto next_part;
}
Debug(3, "codec: bad frame %d\n", used);
}
#endif
}
/**
@@ -583,7 +595,9 @@ void CodecVideoDecode(VideoDecoder * decoder, const AVPacket * avpkt)
*/
void CodecVideoFlushBuffers(VideoDecoder * decoder)
{
avcodec_flush_buffers(decoder->VideoCtx);
if (decoder->VideoCtx) {
avcodec_flush_buffers(decoder->VideoCtx);
}
}
//----------------------------------------------------------------------------
@@ -631,6 +645,11 @@ struct _audio_decoder_
int RemainCount; ///< number of remaining samples
};
#ifdef USE_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
@@ -773,8 +792,23 @@ void CodecAudioClose(AudioDecoder * audio_decoder)
}
}
/**
** Set audio drift correction.
**
** @param mask enable mask (PCM, AC3)
*/
void CodecSetAudioDrift(int mask)
{
#ifdef USE_AUDIO_DRIFT_CORRECTION
CodecAudioDrift = mask & 3;
#endif
(void)mask;
}
/**
** Set audio pass-through.
**
** @param mask enable mask (PCM, AC3)
*/
void CodecSetAudioPassthrough(int mask)
{
@@ -791,6 +825,10 @@ void CodecSetAudioPassthrough(int mask)
*/
void CodecSetAudioDownmix(int onoff)
{
if (onoff == -1) {
CodecDownmix ^= 1;
return;
}
CodecDownmix = onoff;
}
@@ -882,7 +920,7 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
audio_decoder->LastDelay = delay;
audio_decoder->Drift = 0;
audio_decoder->DriftFrac = 0;
Debug(3, "codec/audio: inital delay %zd ms\n", delay / 90);
Debug(3, "codec/audio: inital delay %" PRId64 "ms\n", delay / 90);
return;
}
// collect over some time
@@ -906,9 +944,10 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
audio_decoder->LastDelay = delay;
if (0) {
Debug(3, "codec/audio: interval P:%5zdms T:%5zdms D:%4zdms %f %d\n",
pts_diff / 90, tim_diff / (1000 * 1000), delay / 90, drift / 90.0,
audio_decoder->DriftCorr);
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) {
@@ -916,17 +955,17 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
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);
#if defined(USE_PASSTHROUGH) && !defined(USE_AC3_DRIFT_CORRECTION)
// SPDIF/HDMI passthrough
if (!CodecPassthroughAC3
|| audio_decoder->AudioCtx->codec_id != CODEC_ID_AC3)
#endif
{
if ((CodecAudioDrift & 2) && (!CodecPassthroughAC3
|| audio_decoder->AudioCtx->codec_id != CODEC_ID_AC3)) {
audio_decoder->DriftCorr = -corr;
}
@@ -949,8 +988,14 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
av_resample_compensate(audio_decoder->AvResample,
audio_decoder->DriftCorr / 10, distance);
}
Debug(3, "codec/audio: drift(%6d) %8dus %5d\n", audio_decoder->DriftCorr,
drift * 1000 / 90, corr);
if (1) {
static int c;
if (!(c++ % 10)) {
Debug(3, "codec/audio: drift(%6d) %8dus %5d\n",
audio_decoder->DriftCorr, drift * 1000 / 90, corr);
}
}
}
/**
@@ -1025,7 +1070,7 @@ static void CodecAudioUpdateFormat(AudioDecoder * audio_decoder)
}
// prepare audio drift resample
#ifdef USE_AUDIO_DRIFT_CORRECTION
if (!isAC3) {
if ((CodecAudioDrift & 1) && !isAC3) {
if (audio_decoder->AvResample) {
Error(_("codec/audio: overwrite resample\n"));
}
@@ -1056,7 +1101,7 @@ static void CodecAudioUpdateFormat(AudioDecoder * audio_decoder)
void CodecAudioEnqueue(AudioDecoder * audio_decoder, int16_t * data, int count)
{
#ifdef USE_AUDIO_DRIFT_CORRECTION
if (audio_decoder->AvResample) {
if ((CodecAudioDrift & 1) && 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];
@@ -1211,7 +1256,7 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
buf_sz = 6144;
#ifdef USE_AC3_DRIFT_CORRECTION
if (1) {
if (CodecAudioDrift & 2) {
int x;
x = (audio_decoder->DriftFrac +

10
codec.h
View File

@@ -67,8 +67,14 @@ extern void CodecAudioOpen(AudioDecoder *, const char *, int);
/// Close audio codec.
extern void CodecAudioClose(AudioDecoder *);
/// Decode an audio packet.
extern void CodecAudioDecodeOld(AudioDecoder *, const AVPacket *);
/// Set audio drift correction.
extern void CodecSetAudioDrift(int);
/// Set audio pass-through.
extern void CodecSetAudioPassthrough(int);
/// Set audio downmix.
extern void CodecSetAudioDownmix(int);
/// Decode an audio packet.
extern void CodecAudioDecode(AudioDecoder *, const AVPacket *);

View File

@@ -48,6 +48,18 @@ struct _ring_buffer_
atomic_t Filled; ///< how many of the buffer is used
};
/**
** Reset ring buffer pointers.
**
** @param rb Ring buffer to reset read/write pointers.
*/
void RingBufferReset(RingBuffer * rb)
{
rb->ReadPointer = rb->Buffer;
rb->WritePointer = rb->Buffer;
atomic_set(&rb->Filled, 0);
}
/**
** Allocate a new ring buffer.
**
@@ -69,10 +81,8 @@ RingBuffer *RingBufferNew(size_t size)
}
rb->Size = size;
rb->ReadPointer = rb->Buffer;
rb->WritePointer = rb->Buffer;
rb->BufferEnd = rb->Buffer + size;
atomic_set(&rb->Filled, 0);
RingBufferReset(rb);
return rb;
}
@@ -89,7 +99,7 @@ void RingBufferDel(RingBuffer * rb)
/**
** Advance write pointer in ring buffer.
**
** @param rb Ring buffer to adance write pointer.
** @param rb Ring buffer to advance write pointer.
** @param cnt Number of bytes to be adavanced.
**
** @returns Number of bytes that could be advanced in ring buffer.
@@ -198,7 +208,7 @@ size_t RingBufferGetWritePointer(RingBuffer * rb, void **wp)
/**
** Advance read pointer in ring buffer.
**
** @param rb Ring buffer to adance read pointer.
** @param rb Ring buffer to advance read pointer.
** @param cnt Number of bytes to be advanced.
**
** @returns Number of bytes that could be advanced in ring buffer.

View File

@@ -23,13 +23,16 @@
/// @addtogroup Ringbuffer
/// @{
///< ring buffer typedef
/// ring buffer typedef
typedef struct _ring_buffer_ RingBuffer;
///< create new ring buffer
/// reset ring buffer pointers
extern void RingBufferReset(RingBuffer *);
/// create new ring buffer
extern RingBuffer *RingBufferNew(size_t);
///< free ring buffer
/// free ring buffer
extern void RingBufferDel(RingBuffer *);
/// write into ring buffer

View File

@@ -22,6 +22,9 @@
#include <sys/types.h>
#include <sys/stat.h>
#ifdef __FreeBSD__
#include <signal.h>
#endif
#include <fcntl.h>
#include <stdio.h>
@@ -56,14 +59,16 @@ static int H264Dump(const uint8_t * data, int size);
//////////////////////////////////////////////////////////////////////////////
#ifdef USE_VDPAU
static char ConfigVdpauDecoder = 1; ///< use vdpau decoder, if possible
static char VdpauDecoder = 1; ///< vdpau decoder used
#else
#define ConfigVdpauDecoder 0 ///< no vdpau decoder configured
#define VdpauDecoder 0 ///< no vdpau decoder configured
#endif
extern int ConfigAudioBufferTime; ///< config size ms of audio buffer
static char ConfigStartSuspended; ///< flag to start in suspend mode
static char ConfigFullscreen; ///< fullscreen modus
static char ConfigStartX11Server; ///< flag start the x11 server
static char ConfigStillDecoder; ///< hw/sw decoder for still picture
static pthread_mutex_t SuspendLockMutex; ///< suspend lock mutex
@@ -347,8 +352,8 @@ static int Ac3Check(const uint8_t * data, int size)
frmsizcod = data[4] & 0x3F; // invalid is checked by fast
frame_size = Ac3FrameSizeTable[frmsizcod][fscod] * 2;
if (frame_size + 2 > size) {
return -frame_size - 2;
if (frame_size + 5 > size) {
return -frame_size - 5;
}
// check if after this frame a new AC-3 frame starts
if (FastAc3Check(data + frame_size)) {
@@ -358,6 +363,71 @@ static int Ac3Check(const uint8_t * data, int size)
return 0;
}
///
/// Fast check for ADTS Audio Data Transport Stream.
///
/// 7/9 bytes 0xFFFxxxxxxxxxxx(xxxx) ADTS audio
///
static inline int FastAdtsCheck(const uint8_t * p)
{
if (p[0] != 0xFF) { // 12bit sync
return 0;
}
if ((p[1] & 0xF6) != 0xF0) { // sync + layer must be 0
return 0;
}
if ((p[2] & 0x3C) == 0x3C) { // sampling frequency index != 15
return 0;
}
return 1;
}
///
/// Check for ADTS Audio Data Transport Stream.
///
/// 0xFFF already checked.
///
/// @param data incomplete PES packet
/// @param size number of bytes
///
/// @retval <0 possible ADTS audio, but need more data
/// @retval 0 no valid ADTS audio
/// @retval >0 valid AC-3 audio
///
/// AAAAAAAA AAAABCCD EEFFFFGH HHIJKLMM MMMMMMMM MMMOOOOO OOOOOOPP
/// (QQQQQQQQ QQQQQQQ)
///
/// o A*12 syncword 0xFFF
/// o B*1 MPEG Version: 0 for MPEG-4, 1 for MPEG-2
/// o C*2 layer: always 0
/// o ..
/// o F*4 sampling frequency index (15 is invalid)
/// o ..
/// o M*13 frame length
///
static int AdtsCheck(const uint8_t * data, int size)
{
int frame_size;
if (size < 6) {
return -6;
}
frame_size = (data[3] & 0x03) << 11;
frame_size |= (data[4] & 0xFF) << 3;
frame_size |= (data[5] & 0xE0) >> 5;
if (frame_size + 3 > size) {
return -frame_size - 3;
}
// check if after this frame a new ADTS frame starts
if (FastAdtsCheck(data + frame_size)) {
return frame_size;
}
return 0;
}
#ifndef NO_TS_AUDIO
//////////////////////////////////////////////////////////////////////////////
@@ -540,11 +610,13 @@ static void PesParse(PesDemux * pesdx, const uint8_t * data, int size,
unsigned codec_id;
// 4 bytes 0xFFExxxxx Mpeg audio
// 3 bytes 0x56Exxx AAC LATM audio
// 5 bytes 0x0B77xxxxxx AC3 audio
// 3 bytes 0x56Exxx AAC LATM audio
// 7/9 bytes 0xFFFxxxxxxxxxxx ADTS audio
// PCM audio can't be found
// FIXME: simple+faster detection, if codec already known
r = 0;
if (FastMpegCheck(q)) {
if (!r && FastMpegCheck(q)) {
r = MpegCheck(q, n);
codec_id = CODEC_ID_MP2;
}
@@ -556,6 +628,10 @@ static void PesParse(PesDemux * pesdx, const uint8_t * data, int size,
r = LatmCheck(q, n);
codec_id = CODEC_ID_AAC_LATM;
}
if (!r && FastAdtsCheck(q)) {
r = AdtsCheck(q, n);
codec_id = CODEC_ID_AAC;
}
if (r < 0) { // need more bytes
break;
}
@@ -583,6 +659,12 @@ static void PesParse(PesDemux * pesdx, const uint8_t * data, int size,
//pesdx->State = PES_MPEG_DECODE;
break;
}
if (AudioCodecID != CODEC_ID_NONE) {
// shouldn't happen after we have a vaild codec
// detected
Debug(4, "pesdemux: skip @%d %02x\n", pesdx->Skip,
q[0]);
}
// try next byte
++pesdx->Skip;
++q;
@@ -637,13 +719,16 @@ static void PesParse(PesDemux * pesdx, const uint8_t * data, int size,
// have header upto size bits
if (pesdx->HeaderIndex == PES_HEADER_SIZE) {
if ((pesdx->Header[6] & 0xC0) == 0x80) {
pesdx->HeaderSize += pesdx->Header[8];
} else {
if ((pesdx->Header[6] & 0xC0) != 0x80) {
Error(_("pesdemux: mpeg1 pes packet unsupported\n"));
pesdx->State = PES_SKIP;
return;
}
// have pes extension
if (!pesdx->Header[8]) {
goto empty_header;
}
pesdx->HeaderSize += pesdx->Header[8];
// have complete header
} else if (pesdx->HeaderIndex == pesdx->HeaderSize) {
int64_t pts;
@@ -672,6 +757,7 @@ static void PesParse(PesDemux * pesdx, const uint8_t * data, int size,
pts, dts);
}
empty_header:
pesdx->State = PES_INIT;
if (pesdx->StartCode == PES_PRIVATE_STREAM1) {
// only private stream 1, has sub streams
@@ -802,7 +888,9 @@ static int TsDemuxer(TsDemux * tsdx, const uint8_t * data, int size)
p = data;
while (size >= TS_PACKET_SIZE) {
#ifdef DEBUG
int pid;
#endif
int payload;
if (p[0] != TS_PACKET_SYNC) {
@@ -816,11 +904,11 @@ static int TsDemuxer(TsDemux * tsdx, const uint8_t * data, int size)
// FIXME: kill all buffers
goto next_packet;
}
#ifdef DEBUG
pid = (p[1] & 0x1F) << 8 | p[2];
Debug(4, "tsdemux: PID: %#04x%s%s\n", pid, p[1] & 0x40 ? " start" : "",
p[3] & 0x10 ? " payload" : "");
#endif
// skip adaptation field
switch (p[3] & 0x30) { // adaption field
case 0x00: // reserved
@@ -887,7 +975,8 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id)
if (NewAudioStream) {
// this clears the audio ringbuffer indirect, open and setup does it
CodecAudioClose(MyAudioDecoder);
AudioSetBufferTime(0);
AudioFlushBuffers();
AudioSetBufferTime(ConfigAudioBufferTime);
AudioCodecID = CODEC_ID_NONE;
AudioChannelID = -1;
NewAudioStream = 0;
@@ -972,6 +1061,7 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id)
samplerate = samplerates[p[5] >> 4];
channels = (p[5] & 0x7) + 1;
// FIXME: ConfigAudioBufferTime + x
AudioSetBufferTime(400);
AudioSetup(&samplerate, &channels, 0);
if (samplerate != samplerates[p[5] >> 4]) {
@@ -1002,6 +1092,7 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id)
p += 4;
n -= 4; // skip track header
if (AudioCodecID == CODEC_ID_NONE) {
// FIXME: ConfigAudioBufferTime + x
AudioSetBufferTime(400);
}
}
@@ -1018,6 +1109,7 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id)
// 4 bytes 0xFFExxxxx Mpeg audio
// 3 bytes 0x56Exxx AAC LATM audio
// 5 bytes 0x0B77xxxxxx AC3 audio
// 7/9 bytes 0xFFFxxxxxxxxxxx ADTS audio
// PCM audio can't be found
r = 0;
codec_id = CODEC_ID_NONE; // keep compiler happy
@@ -1038,6 +1130,10 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id)
}
*/
}
if (id != 0xbd && !r && FastAdtsCheck(p)) {
r = AdtsCheck(p, n);
codec_id = CODEC_ID_AAC;
}
if (r < 0) { // need more bytes
break;
}
@@ -1100,8 +1196,9 @@ int PlayTsAudio(const uint8_t * data, int size)
if (NewAudioStream) {
// this clears the audio ringbuffer indirect, open and setup does it
CodecAudioClose(MyAudioDecoder);
AudioFlushBuffers();
// max time between audio packets 200ms + 24ms hw buffer
AudioSetBufferTime(264);
AudioSetBufferTime(ConfigAudioBufferTime);
AudioCodecID = CODEC_ID_NONE;
AudioChannelID = -1;
NewAudioStream = 0;
@@ -1128,7 +1225,7 @@ int PlayTsAudio(const uint8_t * data, int size)
*/
void SetVolumeDevice(int volume)
{
AudioSetVolume((volume * 100) / 255);
AudioSetVolume((volume * 1000) / 255);
}
//////////////////////////////////////////////////////////////////////////////
@@ -1140,6 +1237,10 @@ void SetVolumeDevice(int volume)
#ifdef DEBUG
uint32_t VideoSwitch; ///< debug video switch ticks
#endif
//#define STILL_DEBUG 2
#ifdef STILL_DEBUG
static char InStillPicture; ///< flag still picture
#endif
static volatile char NewVideoStream; ///< flag new video stream
static volatile char ClosingVideoStream; ///< flag closing video stream
static VideoHwDecoder *MyHwDecoder; ///< video hw decoder
@@ -1306,7 +1407,7 @@ static void VideoNextPacket(int codec_id)
/**
** Fix packet for FFMpeg.
**
** Some tv-stations sends mulitple pictures in a singe PES packet.
** Some tv-stations sends mulitple pictures in a single PES packet.
** Current ffmpeg 0.10 and libav-0.8 has problems with this.
** Split the packet into single picture packets.
*/
@@ -1322,7 +1423,18 @@ void FixPacketForFFMpeg(VideoDecoder * MyVideoDecoder, AVPacket * avpkt)
*tmp = *avpkt;
first = 1;
while (n > 4) {
#if STILL_DEBUG>1
if (InStillPicture) {
fprintf(stderr, "fix:");
}
#endif
while (n > 3) {
#if STILL_DEBUG>1
if (InStillPicture && !p[0] && !p[1] && p[2] == 0x01) {
fprintf(stderr, " %02x", p[3]);
}
#endif
// scan for picture header 0x00000100
if (!p[0] && !p[1] && p[2] == 0x01 && !p[3]) {
if (first) {
@@ -1333,6 +1445,12 @@ void FixPacketForFFMpeg(VideoDecoder * MyVideoDecoder, AVPacket * avpkt)
}
// packet has already an picture header
tmp->size = p - tmp->data;
#if STILL_DEBUG>1
if (InStillPicture) {
fprintf(stderr, "\nfix:%9d,%02x %02x %02x %02x\n", tmp->size,
tmp->data[0], tmp->data[1], tmp->data[2], tmp->data[3]);
}
#endif
CodecVideoDecode(MyVideoDecoder, tmp);
// time-stamp only valid for first packet
tmp->pts = AV_NOPTS_VALUE;
@@ -1344,9 +1462,38 @@ void FixPacketForFFMpeg(VideoDecoder * MyVideoDecoder, AVPacket * avpkt)
++p;
}
#if STILL_DEBUG>1
if (InStillPicture) {
fprintf(stderr, "\nfix:%9d.%02x %02x %02x %02x\n", tmp->size,
tmp->data[0], tmp->data[1], tmp->data[2], tmp->data[3]);
}
#endif
CodecVideoDecode(MyVideoDecoder, tmp);
}
/**
** Poll PES packet ringbuffer.
**
** Called if video frame buffers are full.
*/
int VideoPollInput(void)
{
if (VideoClearBuffers) {
atomic_set(&VideoPacketsFilled, 0);
VideoPacketRead = VideoPacketWrite;
if (MyVideoDecoder) {
CodecVideoFlushBuffers(MyVideoDecoder);
VideoResetStart(MyHwDecoder);
}
VideoClearBuffers = 0;
return 1;
}
if (!atomic_read(&VideoPacketsFilled)) {
return -1;
}
return 1;
}
/**
** Decode from PES packet ringbuffer.
**
@@ -1354,25 +1501,27 @@ void FixPacketForFFMpeg(VideoDecoder * MyVideoDecoder, AVPacket * avpkt)
** @retval 1 stream paused
** @retval -1 empty stream
*/
int VideoDecode(void)
int VideoDecodeInput(void)
{
int filled;
AVPacket *avpkt;
int saved_size;
static int last_codec_id = CODEC_ID_NONE;
if (StreamFreezed) { // stream freezed
return 1;
}
if (VideoClearBuffers) {
atomic_set(&VideoPacketsFilled, 0);
VideoPacketRead = VideoPacketWrite;
if (MyVideoDecoder) {
CodecVideoFlushBuffers(MyVideoDecoder);
VideoResetStart(MyHwDecoder);
}
VideoClearBuffers = 0;
return 1;
}
if (StreamFreezed) { // stream freezed
// clear is called during freezed
return 1;
}
filled = atomic_read(&VideoPacketsFilled);
if (!filled) {
@@ -1416,17 +1565,16 @@ int VideoDecode(void)
case CODEC_ID_MPEG2VIDEO:
if (last_codec_id != CODEC_ID_MPEG2VIDEO) {
last_codec_id = CODEC_ID_MPEG2VIDEO;
CodecVideoOpen(MyVideoDecoder,
ConfigVdpauDecoder ? "mpegvideo_vdpau" : NULL,
CodecVideoOpen(MyVideoDecoder, VideoHardwareDecoder < 0
&& VdpauDecoder ? "mpegvideo_vdpau" : NULL,
CODEC_ID_MPEG2VIDEO);
}
break;
case CODEC_ID_H264:
if (last_codec_id != CODEC_ID_H264) {
last_codec_id = CODEC_ID_H264;
CodecVideoOpen(MyVideoDecoder,
ConfigVdpauDecoder ? "h264video_vdpau" : NULL,
CODEC_ID_H264);
CodecVideoOpen(MyVideoDecoder, VideoHardwareDecoder
&& VdpauDecoder ? "h264_vdpau" : NULL, CODEC_ID_H264);
}
break;
default:
@@ -1438,33 +1586,6 @@ int VideoDecode(void)
avpkt->size = avpkt->stream_index;
avpkt->stream_index = 0;
if (0) {
static int done;
if (done < 2) {
int fildes;
int who_designed_this_is____;
if (done == 0)
fildes =
open("frame0.pes", O_WRONLY | O_TRUNC | O_CREAT, 0666);
else if (done == 1)
fildes =
open("frame1.pes", O_WRONLY | O_TRUNC | O_CREAT, 0666);
else
fildes =
open("frame2.pes", O_WRONLY | O_TRUNC | O_CREAT, 0666);
done++;
who_designed_this_is____ = write(fildes, avpkt->data, avpkt->size);
close(fildes);
}
}
if (ClosingVideoStream) { // closing don't sync
avpkt->pts = AV_NOPTS_VALUE;
avpkt->dts = AV_NOPTS_VALUE;
}
if (last_codec_id == CODEC_ID_MPEG2VIDEO) {
FixPacketForFFMpeg(MyVideoDecoder, avpkt);
} else {
@@ -1497,6 +1618,10 @@ int VideoGetBuffers(void)
static void StartVideo(void)
{
VideoInit(X11DisplayName);
#ifdef USE_VDPAU
VdpauDecoder = !strcasecmp(VideoGetDriverName(), "vdpau");
#endif
if (ConfigFullscreen) {
// FIXME: not good looking, mapped and then resized.
VideoSetFullscreen(1);
@@ -1638,8 +1763,6 @@ int PlayVideo(const uint8_t * data, int size)
}
VideoNextPacket(CODEC_ID_NONE);
VideoCodecID = CODEC_ID_NONE;
// clear clock until new stream starts
VideoSetClock(MyHwDecoder, AV_NOPTS_VALUE);
ClosingVideoStream = 1;
NewVideoStream = 0;
}
@@ -1732,8 +1855,8 @@ int PlayVideo(const uint8_t * data, int size)
Debug(3, "softhddev/video: invalid mpeg2 video packet\n");
}
#endif
// SKIP PES header
VideoEnqueue(pts, check - 2, l + 2);
// SKIP PES header, begin of start code
VideoEnqueue(pts, check - z, l + z);
return size;
}
// this happens when vdr sends incomplete packets
@@ -1856,6 +1979,9 @@ int SetPlayMode(int play_mode)
if (MyVideoDecoder) { // tell video parser we have new stream
if (VideoCodecID != CODEC_ID_NONE) {
NewVideoStream = 1;
// tell hw decoder we are closing stream
VideoSetClosing(MyHwDecoder);
VideoResetStart(MyHwDecoder);
#ifdef DEBUG
VideoSwitch = GetMsTicks();
#endif
@@ -1871,11 +1997,9 @@ int SetPlayMode(int play_mode)
break;
case 2: // audio only
Debug(3, "softhddev: FIXME: audio only, silence video errors\n");
VideoSetClock(MyHwDecoder, AV_NOPTS_VALUE);
break;
case 3: // audio only, black screen
Debug(3, "softhddev: FIXME: audio only, silence video errors\n");
VideoSetClock(MyHwDecoder, AV_NOPTS_VALUE);
break;
case 4: // video only
break;
@@ -1895,10 +2019,47 @@ int64_t GetSTC(void)
if (MyHwDecoder) {
return VideoGetClock(MyHwDecoder);
}
Error(_("softhddev: %s called without hw decoder\n"), __FUNCTION__);
// could happen during dettached
Warning(_("softhddev: %s called without hw decoder\n"), __FUNCTION__);
return AV_NOPTS_VALUE;
}
/**
** Get video stream size and aspect.
**
** @param width[OUT] width of video stream
** @param height[OUT] height of video stream
** @param aspect[OUT] aspect ratio (4/3, 16/9, ...) of video stream
*/
void GetVideoSize(int *width, int *height, double *aspect)
{
#ifdef DEBUG
static int done_width;
static int done_height;
#endif
int aspect_num;
int aspect_den;
if (MyHwDecoder) {
VideoGetVideoSize(MyHwDecoder, width, height, &aspect_num,
&aspect_den);
*aspect = (double)aspect_num / (double)aspect_den;
} else {
*width = 0;
*height = 0;
*aspect = 1.0; // like default cDevice::GetVideoSize
}
#ifdef DEBUG
if (done_width != *width || done_height != *height) {
Debug(3, "[softhddev]%s: %dx%d %g\n", __FUNCTION__, *width, *height,
*aspect);
done_width = *width;
done_height = *height;
}
#endif
}
/**
** Set trick play speed.
**
@@ -1933,10 +2094,12 @@ void Clear(void)
// FIXME: audio avcodec_flush_buffers, video is done by VideoClearBuffers
// wait for empty buffers
// FIXME: without softstart sync VideoDecode isn't called.
for (i = 0; VideoClearBuffers && i < 20; ++i) {
usleep(1 * 1000);
}
Debug(3, "[softhddev]%s: buffers %d\n", __FUNCTION__, VideoGetBuffers());
Debug(3, "[softhddev]%s: %dms buffers %d\n", __FUNCTION__, i,
VideoGetBuffers());
}
/**
@@ -1976,16 +2139,26 @@ void Mute(void)
*/
void StillPicture(const uint8_t * data, int size)
{
int i;
static uint8_t seq_end_mpeg[] = { 0x00, 0x00, 0x01, 0xB7 };
// H264 NAL End of Sequence
static uint8_t seq_end_h264[] = { 0x00, 0x00, 0x00, 0x01, 0x0A };
int i;
int old_video_hardware_decoder;
// must be a PES start code
if (size < 9 || !data || data[0] || data[1] || data[2] != 0x01) {
Error(_("[softhddev] invalid still video packet\n"));
return;
}
#ifdef STILL_DEBUG
InStillPicture = 1;
#endif
VideoSetTrickSpeed(MyHwDecoder, 1);
VideoResetPacket();
old_video_hardware_decoder = VideoHardwareDecoder;
// enable/disable hardware decoder for still picture
VideoHardwareDecoder = ConfigStillDecoder;
VideoNextPacket(CODEC_ID_NONE); // close last stream
if (VideoCodecID == CODEC_ID_NONE) {
// FIXME: should detect codec, see PlayVideo
@@ -1993,7 +2166,10 @@ void StillPicture(const uint8_t * data, int size)
}
// FIXME: can check video backend, if a frame was produced.
// output for max reference frames
for (i = 0; i < (VideoCodecID == CODEC_ID_MPEG2VIDEO ? 3 : 17); ++i) {
#ifdef STILL_DEBUG
fprintf(stderr, "still-picture\n");
#endif
for (i = 0; i < (VideoCodecID == CODEC_ID_MPEG2VIDEO ? 4 : 4); ++i) {
const uint8_t *split;
int n;
@@ -2014,14 +2190,14 @@ void StillPicture(const uint8_t * data, int size)
len = (split[4] << 8) + split[5];
if (!len || len + 6 > n) {
// video only
if ((data[3] & 0xF0) == 0xE0) {
if ((split[3] & 0xF0) == 0xE0) {
// video only
while (!PlayVideo(split, n)) { // feed remaining bytes
}
}
break;
}
if ((data[3] & 0xF0) == 0xE0) {
if ((split[3] & 0xF0) == 0xE0) {
// video only
while (!PlayVideo(split, len + 6)) { // feed it
}
@@ -2031,32 +2207,33 @@ void StillPicture(const uint8_t * data, int size)
} while (n > 6);
VideoNextPacket(VideoCodecID); // terminate last packet
if (VideoCodecID == CODEC_ID_H264) {
VideoEnqueue(AV_NOPTS_VALUE, seq_end_h264,
sizeof(seq_end_h264));
} else {
VideoEnqueue(AV_NOPTS_VALUE, seq_end_mpeg,
sizeof(seq_end_mpeg));
}
VideoNextPacket(VideoCodecID); // terminate last packet
} else { // ES packet
if (VideoCodecID != CODEC_ID_MPEG2VIDEO) {
VideoNextPacket(CODEC_ID_NONE); // close last stream
VideoCodecID = CODEC_ID_MPEG2VIDEO;
}
VideoEnqueue(AV_NOPTS_VALUE, data, size);
VideoEnqueue(AV_NOPTS_VALUE, seq_end_mpeg, sizeof(seq_end_mpeg));
VideoNextPacket(VideoCodecID); // terminate last packet
}
if (VideoCodecID == CODEC_ID_H264) {
VideoEnqueue(AV_NOPTS_VALUE, seq_end_h264, sizeof(seq_end_h264));
} else {
VideoEnqueue(AV_NOPTS_VALUE, seq_end_mpeg, sizeof(seq_end_mpeg));
}
VideoNextPacket(VideoCodecID); // terminate last packet
}
// wait for empty buffers
for (i = 0; VideoGetBuffers() && i < 30; ++i) {
usleep(10 * 1000);
}
Debug(3, "[softhddev]%s: buffers %d\n", __FUNCTION__, VideoGetBuffers());
Debug(3, "[softhddev]%s: buffers %d %dms\n", __FUNCTION__,
VideoGetBuffers(), i * 10);
#ifdef STILL_DEBUG
InStillPicture = 0;
#endif
VideoNextPacket(CODEC_ID_NONE); // close last stream
VideoSetTrickSpeed(MyHwDecoder, 0);
VideoHardwareDecoder = old_video_hardware_decoder;
}
/**
@@ -2090,10 +2267,15 @@ int Poll(int timeout)
#else
int full;
int t;
int used;
int filled;
// one buffer is full
full = AudioFreeBytes() >= AUDIO_MIN_BUFFER_FREE
|| atomic_read(&VideoPacketsFilled) < VIDEO_PACKET_MAX - 3;
used = AudioUsedBytes();
filled = atomic_read(&VideoPacketsFilled);
// soft limit + hard limit
full = (used > AUDIO_MIN_BUFFER_FREE && filled > 3)
|| AudioFreeBytes() < AUDIO_MIN_BUFFER_FREE
|| filled >= VIDEO_PACKET_MAX - 3;
if (!full || !timeout) {
return !full;
@@ -2197,8 +2379,10 @@ const char *CommandLineHelp(void)
" -w workaround\tenable/disable workarounds\n"
"\tno-hw-decoder\t\tdisable hw decoder, use software decoder only\n"
"\tno-mpeg-hw-decoder\tdisable hw decoder for mpeg only\n"
"\tstill-hw-decoder\tenable hardware decoder for still-pictures\n"
"\talsa-driver-broken\tdisable broken alsa driver message\n"
"\tignore-repeat-pict\tdisable repeat pict message\n";
"\tignore-repeat-pict\tdisable repeat pict message\n"
" -D\t\tstart in detached mode\n";
}
/**
@@ -2212,8 +2396,15 @@ int ProcessArgs(int argc, char *const argv[])
//
// Parse arguments.
//
#ifdef __FreeBSD__
if (!strcmp(*argv, "softhddevice")) {
++argv;
--argc;
}
#endif
for (;;) {
switch (getopt(argc, argv, "-a:c:d:fg:p:sv:w:x")) {
switch (getopt(argc, argv, "-a:c:d:fg:p:sv:w:xD")) {
case 'a': // audio device for pcm
AudioSetDevice(optarg);
continue;
@@ -2239,10 +2430,6 @@ int ProcessArgs(int argc, char *const argv[])
continue;
case 'v': // video driver
VideoSetDevice(optarg);
#ifdef USE_VDPAU
// FIXME: this is a big hack
ConfigVdpauDecoder = !strcasecmp(optarg, "vdpau");
#endif
continue;
case 'x': // x11 server
ConfigStartX11Server = 1;
@@ -2250,9 +2437,19 @@ int ProcessArgs(int argc, char *const argv[])
case 's': // start in suspend mode
ConfigStartSuspended = 1;
continue;
case 'D': // start in detached mode
ConfigStartSuspended = -1;
continue;
case 'w': // workarounds
if (!strcasecmp("no-hw-decoder", optarg)) {
VideoHardwareDecoder = 0;
} else if (!strcasecmp("no-mpeg-hw-decoder", optarg)) {
VideoHardwareDecoder = 1;
if (ConfigStillDecoder) {
ConfigStillDecoder = 1;
}
} else if (!strcasecmp("still-hw-decoder", optarg)) {
ConfigStillDecoder = -1;
} else if (!strcasecmp("alsa-driver-broken", optarg)) {
AudioAlsaDriverBroken = 1;
} else if (!strcasecmp("ignore-repeat-pict", optarg)) {
@@ -2294,7 +2491,11 @@ int ProcessArgs(int argc, char *const argv[])
#define XSERVER_MAX_ARGS 512 ///< how many arguments support
#ifndef __FreeBSD__
static const char *X11Server = "/usr/bin/X"; ///< default x11 server
#else
static const char *X11Server = LOCALBASE "/bin/X"; ///< default x11 server
#endif
static const char *X11ServerArguments; ///< default command arguments
static pid_t X11ServerPid; ///< x11 server pid
@@ -2321,6 +2522,8 @@ static void StartXServer(void)
const char *args[XSERVER_MAX_ARGS];
int argn;
char *buf;
int maxfd;
int fd;
// X server
if (X11Server) {
@@ -2333,12 +2536,19 @@ static void StartXServer(void)
argn = 1;
if (X11DisplayName) { // append display name
args[argn++] = X11DisplayName;
// export display for childs
setenv("DISPLAY", X11DisplayName, 1);
}
// split X server arguments string into words
if ((sval = X11ServerArguments)) {
char *s;
#ifndef __FreeBSD__
s = buf = strdupa(sval);
#else
s = buf = alloca(strlen(sval) + 1);
strcpy(buf, sval);
#endif
while ((sval = strsep(&s, " \t"))) {
args[argn++] = sval;
@@ -2370,10 +2580,19 @@ static void StartXServer(void)
}
// child
signal(SIGUSR1, SIG_IGN); // ignore to force answer
//setpgid(0,getpid());
// close all open file-handles
maxfd = sysconf(_SC_OPEN_MAX);
for (fd = 3; fd < maxfd; fd++) { // keep stdin, stdout, stderr
close(fd); // vdr should open with O_CLOEXEC
}
// start the X server
execvp(args[0], (char *const *)args);
Error(_("x-setup: Failed to start X server '%s'\n"), args[0]);
exit(-1);
}
/**
@@ -2436,6 +2655,10 @@ void SoftHdDeviceExit(void)
/**
** Prepare plugin.
**
** @retval 0 normal start
** @retval 1 suspended start
** @retval -1 detached start
*/
int Start(void)
{
@@ -2465,9 +2688,11 @@ int Start(void)
#ifndef NO_TS_AUDIO
PesInit(PesDemuxAudio);
#endif
Info(_("[softhddev] ready%s\n"), ConfigStartSuspended ? " suspended" : "");
Info(_("[softhddev] ready%s\n"),
ConfigStartSuspended ? ConfigStartSuspended ==
-1 ? "detached" : " suspended" : "");
return !ConfigStartSuspended;
return ConfigStartSuspended;
}
/**
@@ -2495,6 +2720,8 @@ void Housekeeping(void)
void MainThreadHook(void)
{
if (Usr1Signal) { // x11 server ready
// FIYME: x11 server keeps sending sigusr1 signals
signal(SIGUSR1, SIG_IGN); // ignore further signals
Usr1Signal = 0;
StartVideo();
VideoDisplayWakeup();
@@ -2577,3 +2804,22 @@ void Resume(void)
pthread_mutex_unlock(&SuspendLockMutex);
}
/*
** Get decoder statistics.
**
** @param[out] missed missed frames
** @param[out] duped duped frames
** @param[out] dropped dropped frames
** @param[out] count number of decoded frames
*/
void GetStats(int *missed, int *duped, int *dropped, int *counter)
{
*missed = 0;
*duped = 0;
*dropped = 0;
*counter = 0;
if (MyHwDecoder) {
VideoGetStats(MyHwDecoder, missed, duped, dropped, counter);
}
}

View File

@@ -53,6 +53,8 @@ extern "C"
extern int SetPlayMode(int);
/// C plugin get current system time counter
extern int64_t GetSTC(void);
/// C plugin get video stream size and aspect
extern void GetVideoSize(int *, int *, double *);
/// C plugin set trick speed
extern void TrickSpeed(int);
/// C plugin clears all video and audio data from the device
@@ -90,6 +92,9 @@ extern "C"
extern void Suspend(int, int, int);
/// Resume plugin
extern void Resume(void);
/// Get decoder statistics
extern void GetStats(int *, int *, int *, int *);
#ifdef __cplusplus
}
#endif

File diff suppressed because it is too large Load Diff

50
softhddevice_service.h Normal file
View File

@@ -0,0 +1,50 @@
///
/// @file softhddev_service.h @brief software HD device service header file.
///
/// Copyright (c) 2012 by durchflieger. All Rights Reserved.
///
/// Contributor(s):
///
/// License: AGPLv3
///
/// This program is free software: you can redistribute it and/or modify
/// it under the terms of the GNU Affero General Public License as
/// published by the Free Software Foundation, either version 3 of the
/// License.
///
/// This program is distributed in the hope that it will be useful,
/// but WITHOUT ANY WARRANTY; without even the implied warranty of
/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
/// GNU Affero General Public License for more details.
///
/// $Id$
//////////////////////////////////////////////////////////////////////////////
#pragma once
#define ATMO_GRAB_SERVICE "SoftHDDevice-AtmoGrabService-v1.0"
#define OSD_3DMODE_SERVICE "SoftHDDevice-Osd3DModeService-v1.0"
enum
{ GRAB_IMG_RGBA_FORMAT_B8G8R8A8 };
typedef struct
{
int structSize;
// request data
int analyseSize;
int clippedOverscan;
// reply data
int imgType;
int imgSize;
int width;
int height;
void *img;
} SoftHDDevice_AtmoGrabService_v1_0_t;
typedef struct
{
int Mode;
} SoftHDDevice_Osd3DModeService_v1_0_t;

View File

@@ -21,7 +21,7 @@ SRC_URI=""
LICENSE="AGPL-3"
SLOT="0"
KEYWORDS="~x86 ~amd64"
IUSE="vaapi vdpau alsa oss yaepg opengl jpeg"
IUSE="vaapi vdpau alsa oss yaepg opengl debug"
DEPEND=">=x11-libs/libxcb-1.8
x11-libs/xcb-util
@@ -36,11 +36,10 @@ DEPEND=">=x11-libs/libxcb-1.8
dev-util/pkgconfig
yaepg? ( >=media-video/vdr-1.7.23[yaepg] )
!yaepg? ( >=media-video/vdr-1.7.23 )
vdpau? ( x11-libs/libvdpau )
vaapi? ( x11-libs/libva )
vdpau? ( x11-libs/libvdpau virtual/ffmpeg[vdpau] )
vaapi? ( x11-libs/libva virtual/ffmpeg[vaapi] )
alsa? ( media-libs/alsa-lib )
oss? ( sys-kernel/linux-headers )
jpeg? ( virtual/jpeg )
"
src_prepare() {
@@ -55,7 +54,7 @@ src_compile() {
use vaapi && myconf="${myconf} -DUSE_VAAPI"
use alsa && myconf="${myconf} -DUSE_ALSA"
use oss && myconf="${myconf} -DUSE_OSS"
use jpeg && myconf="${myconf} -DUSE_JPEG"
use debug && myconf="${myconf} -DDEBUG"
emake all CC="$(tc-getCC)" CFLAGS="${CFLAGS}" \
LDFLAGS="${LDFLAGS}" CONFIG="${myconf}" LIBDIR="." || die

889
video.c

File diff suppressed because it is too large Load Diff

44
video.h
View File

@@ -34,6 +34,7 @@ typedef struct _video_hw_decoder_ VideoHwDecoder;
// Variables
//----------------------------------------------------------------------------
extern char VideoHardwareDecoder; ///< flag use hardware decoder
extern char VideoIgnoreRepeatPict; ///< disable repeat pict warning
extern int VideoAudioDelay; ///< audio/video delay
@@ -81,6 +82,9 @@ extern void VideoDisplayWakeup(void);
/// Set video device.
extern void VideoSetDevice(const char *);
/// Get video driver name.
extern const char *VideoGetDriverName(void);
/// Set video geometry.
extern int VideoSetGeometry(const char *);
@@ -90,6 +94,21 @@ extern void VideoSet60HzMode(int);
/// Set soft start audio/video sync.
extern void VideoSetSoftStartSync(int);
/// Set show black picture during channel switch.
extern void VideoSetBlackPicture(int);
/// Set brightness adjustment.
extern void VideoSetBrightness(int);
/// Set contrast adjustment.
extern void VideoSetContrast(int);
/// Set saturation adjustment.
extern void VideoSetSaturation(int);
/// Set hue adjustment.
extern void VideoSetHue(int);
/// Set video output position.
extern void VideoSetOutputPosition(int, int, int, int);
@@ -147,26 +166,47 @@ extern void VideoOsdDrawARGB(int, int, int, int, const uint8_t *);
/// Get OSD size.
extern void VideoGetOsdSize(int *, int *);
/// Set OSD size.
extern void VideoSetOsdSize(int, int);
/// Set Osd 3D Mode
extern void VideoSetOsd3DMode(int);
/// Set video clock.
extern void VideoSetClock(VideoHwDecoder *, int64_t);
/// Get video clock.
extern int64_t VideoGetClock(const VideoHwDecoder *);
/// Set closing flag.
extern void VideoSetClosing(VideoHwDecoder *);
/// Reset start of frame counter
extern void VideoResetStart(VideoHwDecoder *);
/// Set trick play speed.
extern void VideoSetTrickSpeed(VideoHwDecoder *, int);
/// Grab screen.
extern uint8_t *VideoGrab(int *, int *, int *, int);
/// Grab screen raw.
extern uint8_t *VideoGrabService(int *, int *, int *);
/// Get decoder statistics.
extern void VideoGetStats(VideoHwDecoder *, int *, int *, int *, int *);
/// Get video stream size
extern void VideoGetVideoSize(VideoHwDecoder *, int *, int *, int *, int *);
extern void VideoOsdInit(void); ///< Setup osd.
extern void VideoOsdExit(void); ///< Cleanup osd.
extern void VideoInit(const char *); ///< Setup video module.
extern void VideoExit(void); ///< Cleanup and exit video module.
extern void VideoFlushInput(void); ///< Flush video input buffers.
extern int VideoDecode(void); ///< Decode video input buffers.
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.
/// @}