mirror of
https://projects.vdr-developer.org/git/vdr-plugin-softhddevice.git
synced 2023-10-10 17:16:51 +00:00
Compare commits
94 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9a2b6f860a | ||
| 10075aa501 | |||
|
|
cb91c779d3 | ||
|
|
aad3742670 | ||
|
|
1b23074de7 | ||
|
|
78015d90fb | ||
| 0286c434b4 | |||
|
|
6e9e641453 | ||
|
|
d36e4c22b6 | ||
|
|
7e4657e615 | ||
|
|
84e8e58c91 | ||
|
|
141eb5cf71 | ||
|
|
a9e664ac52 | ||
|
|
30952face4 | ||
|
|
0519aff4d8 | ||
|
|
92b4203644 | ||
|
|
f640ebdeb5 | ||
|
|
de7c4b2a96 | ||
|
|
0cf4598f68 | ||
|
|
80dfa4a80f | ||
|
|
0a78944996 | ||
|
|
142c3b16f6 | ||
|
|
73fe963c36 | ||
|
|
a61cbcb65a | ||
|
|
3df9acc034 | ||
|
|
d9c9061a7c | ||
|
|
e9fbe6b54f | ||
|
|
5e93fb2756 | ||
|
|
e02c1fa5f9 | ||
|
|
c07ec82e6d | ||
|
|
ecb48a5d63 | ||
|
|
9efc73144d | ||
| a920da652b | |||
|
|
9ec077ec8a | ||
|
|
8b0d8d8446 | ||
|
|
15583a79c4 | ||
|
|
2cdce610d6 | ||
|
|
2d6d151b85 | ||
|
|
ca4f519a1f | ||
|
|
583b6f246e | ||
|
|
e6ce7832ba | ||
|
|
696bb8e934 | ||
|
|
3bb7782d40 | ||
|
|
b5162bae5c | ||
|
|
d486fb2ca1 | ||
|
|
73d65968ae | ||
|
|
3be69730f0 | ||
|
|
6f1c4d6ef6 | ||
|
|
6aa8601f7d | ||
|
|
0f62a521f4 | ||
|
|
57af986367 | ||
|
|
a2311748ca | ||
|
|
2c5a14ae4a | ||
|
|
ed1e16dccf | ||
|
|
da9886e9f1 | ||
|
|
32527f832e | ||
|
|
57bbd02c57 | ||
|
|
940849d03f | ||
|
|
c112b850d8 | ||
|
|
752ee356fa | ||
|
|
43e70b6a3f | ||
|
|
541754a619 | ||
|
|
3772b2160c | ||
|
|
465c68d839 | ||
| aca508114b | |||
|
|
49ae1c7211 | ||
|
|
0cf110da81 | ||
|
|
8d5ff6f6fb | ||
|
|
5456164dce | ||
|
|
6dd7c2680a | ||
|
|
3b5c1adef2 | ||
|
|
47d840bbff | ||
|
|
207871fd9b | ||
|
|
ebe0beb400 | ||
|
|
93ddd26a4a | ||
|
|
e30e1e5aad | ||
|
|
d26c34f34f | ||
| 24a8c7f763 | |||
|
|
3e39ffd5e0 | ||
|
|
53f22a2ed2 | ||
|
|
44ca71fedb | ||
|
|
8039e8ae04 | ||
|
|
79e78bf235 | ||
|
|
c9ef8b759a | ||
|
|
80db7c6656 | ||
|
|
3ba18d8720 | ||
|
|
2ffcb874bb | ||
|
|
5b765f02bd | ||
|
|
2c52955ac0 | ||
|
|
09d8588588 | ||
|
|
71f786711b | ||
|
|
deea34eb5e | ||
|
|
1f14af6590 | ||
|
|
aeae505bd4 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -4,7 +4,7 @@
|
||||
.*.swp
|
||||
.gdb_history
|
||||
# work directory
|
||||
chaos
|
||||
.chaos
|
||||
# generated files
|
||||
.dependencies
|
||||
libvdr-softhddevice.so*
|
||||
|
||||
95
ChangeLog
95
ChangeLog
@@ -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
|
||||
|
||||
|
||||
6
Makefile
6
Makefile
@@ -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:
|
||||
|
||||
|
||||
55
README.txt
55
README.txt
@@ -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
14
Todo
@@ -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
|
||||
|
||||
4
audio.h
4
audio.h
@@ -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
113
codec.c
@@ -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
10
codec.h
@@ -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 *);
|
||||
|
||||
20
ringbuffer.c
20
ringbuffer.c
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
424
softhddev.c
424
softhddev.c
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
1052
softhddevice.cpp
1052
softhddevice.cpp
File diff suppressed because it is too large
Load Diff
50
softhddevice_service.h
Normal file
50
softhddevice_service.h
Normal 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;
|
||||
@@ -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
|
||||
|
||||
44
video.h
44
video.h
@@ -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.
|
||||
|
||||
/// @}
|
||||
|
||||
Reference in New Issue
Block a user