mirror of
https://projects.vdr-developer.org/git/vdr-plugin-softhddevice.git
synced 2023-10-10 17:16:51 +00:00
Compare commits
39 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 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -4,7 +4,7 @@
|
||||
.*.swp
|
||||
.gdb_history
|
||||
# work directory
|
||||
chaos
|
||||
.chaos
|
||||
# generated files
|
||||
.dependencies
|
||||
libvdr-softhddevice.so*
|
||||
|
||||
42
ChangeLog
42
ChangeLog
@@ -1,3 +1,45 @@
|
||||
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
|
||||
|
||||
|
||||
2
Makefile
2
Makefile
@@ -18,7 +18,7 @@ GIT_REV = $(shell git describe --always 2>/dev/null)
|
||||
|
||||
### Configuration (edit this for your needs)
|
||||
|
||||
CONFIG := #-DDEBUG
|
||||
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
|
||||
|
||||
5
Todo
5
Todo
@@ -41,7 +41,9 @@ video:
|
||||
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
|
||||
@@ -51,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
|
||||
|
||||
52
codec.c
52
codec.c
@@ -39,7 +39,11 @@
|
||||
|
||||
#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>
|
||||
@@ -359,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");
|
||||
@@ -397,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"));
|
||||
@@ -414,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.
|
||||
@@ -430,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.
|
||||
@@ -443,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);
|
||||
}
|
||||
@@ -549,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);
|
||||
@@ -559,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) {
|
||||
@@ -572,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
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -935,9 +945,9 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
|
||||
|
||||
if (0) {
|
||||
Debug(3,
|
||||
"codec/audio: interval P:%5zdms 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);
|
||||
"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) {
|
||||
|
||||
189
softhddev.c
189
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,15 +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
|
||||
|
||||
@@ -715,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;
|
||||
@@ -750,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
|
||||
@@ -1229,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
|
||||
@@ -1395,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.
|
||||
*/
|
||||
@@ -1411,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) {
|
||||
@@ -1422,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;
|
||||
@@ -1433,6 +1462,12 @@ 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);
|
||||
}
|
||||
|
||||
@@ -1530,17 +1565,16 @@ int VideoDecodeInput(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:
|
||||
@@ -1584,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);
|
||||
@@ -1981,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.
|
||||
**
|
||||
@@ -2013,9 +2088,6 @@ void Clear(void)
|
||||
int i;
|
||||
|
||||
VideoResetPacket(); // terminate work
|
||||
//closing not reset:
|
||||
//VideoSetClosing(MyHwDecoder);
|
||||
VideoResetStart(MyHwDecoder);
|
||||
VideoClearBuffers = 1;
|
||||
AudioFlushBuffers();
|
||||
//NewAudioStream = 1;
|
||||
@@ -2067,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
|
||||
@@ -2084,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;
|
||||
|
||||
@@ -2105,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
|
||||
}
|
||||
@@ -2122,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;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2293,6 +2379,7 @@ 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"
|
||||
" -D\t\tstart in detached mode\n";
|
||||
@@ -2309,6 +2396,13 @@ 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:xD")) {
|
||||
case 'a': // audio device for pcm
|
||||
@@ -2336,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;
|
||||
@@ -2355,6 +2445,11 @@ int ProcessArgs(int argc, char *const argv[])
|
||||
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)) {
|
||||
@@ -2396,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
|
||||
|
||||
@@ -2423,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) {
|
||||
@@ -2442,7 +2543,12 @@ static void StartXServer(void)
|
||||
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;
|
||||
|
||||
@@ -2475,6 +2581,13 @@ 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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
268
softhddevice.cpp
268
softhddevice.cpp
@@ -50,7 +50,7 @@ extern "C"
|
||||
/// vdr-plugin version number.
|
||||
/// Makefile extracts the version number for generating the file name
|
||||
/// for the distribution archive.
|
||||
static const char *const VERSION = "0.5.1"
|
||||
static const char *const VERSION = "0.5.2"
|
||||
#ifdef GIT_REV
|
||||
"-GIT" GIT_REV
|
||||
#endif
|
||||
@@ -88,6 +88,11 @@ static char ConfigVideo60HzMode; ///< config use 60Hz display mode
|
||||
static char ConfigVideoSoftStartSync; ///< config use softstart sync
|
||||
static char ConfigVideoBlackPicture; ///< config enable black picture mode
|
||||
|
||||
static int ConfigVideoBrightness; ///< config video brightness
|
||||
static int ConfigVideoContrast = 1000; ///< config video contrast
|
||||
static int ConfigVideoSaturation = 1000; ///< config video saturation
|
||||
static int ConfigVideoHue; ///< config video hue
|
||||
|
||||
/// config deinterlace
|
||||
static int ConfigVideoDeinterlace[RESOLUTIONS];
|
||||
|
||||
@@ -129,6 +134,10 @@ static int ConfigAudioMaxCompression; ///< config max volume compression
|
||||
static int ConfigAudioStereoDescent; ///< config reduce stereo loudness
|
||||
int ConfigAudioBufferTime; ///< config size ms of audio buffer
|
||||
|
||||
static char *ConfigX11Display; ///< config x11 display
|
||||
static char *ConfigAudioDevice; ///< config audio stereo device
|
||||
static char *ConfigAC3Device; ///< config audio passthrough device
|
||||
|
||||
static volatile int DoMakePrimary; ///< switch primary device to this
|
||||
|
||||
#define SUSPEND_EXTERNAL -1 ///< play external suspend mode
|
||||
@@ -222,9 +231,10 @@ class cSoftOsd:public cOsd
|
||||
{
|
||||
public:
|
||||
static volatile char Dirty; ///< flag force redraw everything
|
||||
int OsdLevel; ///< current osd level
|
||||
|
||||
cSoftOsd(int, int, uint); ///< constructor
|
||||
virtual ~ cSoftOsd(void); ///< destructor
|
||||
cSoftOsd(int, int, uint); ///< osd constructor
|
||||
virtual ~ cSoftOsd(void); ///< osd destructor
|
||||
virtual void Flush(void); ///< commits all data to the hardware
|
||||
virtual void SetActive(bool); ///< sets OSD to be the active one
|
||||
};
|
||||
@@ -241,14 +251,26 @@ volatile char cSoftOsd::Dirty; ///< flag force redraw everything
|
||||
*/
|
||||
void cSoftOsd::SetActive(bool on)
|
||||
{
|
||||
//dsyslog("[softhddev]%s: %d\n", __FUNCTION__, on);
|
||||
#ifdef OSD_DEBUG
|
||||
dsyslog("[softhddev]%s: %d level %d\n", __FUNCTION__, on, OsdLevel);
|
||||
#endif
|
||||
|
||||
if (Active() == on) {
|
||||
return; // already active, no action
|
||||
}
|
||||
cOsd::SetActive(on);
|
||||
|
||||
// ignore sub-title if menu is open
|
||||
if (OsdLevel >= OSD_LEVEL_SUBTITLES && IsOpen()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (on) {
|
||||
Dirty = 1;
|
||||
// only flush here if there are already bitmaps
|
||||
if (GetBitmap(0)) {
|
||||
Flush();
|
||||
}
|
||||
} else {
|
||||
OsdClose();
|
||||
}
|
||||
@@ -266,11 +288,14 @@ void cSoftOsd::SetActive(bool on)
|
||||
cSoftOsd::cSoftOsd(int left, int top, uint level)
|
||||
:cOsd(left, top, level)
|
||||
{
|
||||
#ifdef OSD_DEBUG
|
||||
/* FIXME: OsdWidth/OsdHeight not correct!
|
||||
dsyslog("[softhddev]%s: %dx%d+%d+%d, %d\n", __FUNCTION__, OsdWidth(),
|
||||
OsdHeight(), left, top, level);
|
||||
*/
|
||||
dsyslog("[softhddev]%s: %dx%d+%d+%d, %d\n", __FUNCTION__, OsdWidth(),
|
||||
OsdHeight(), left, top, level);
|
||||
#endif
|
||||
|
||||
OsdLevel = level;
|
||||
SetActive(true);
|
||||
}
|
||||
|
||||
@@ -281,7 +306,10 @@ cSoftOsd::cSoftOsd(int left, int top, uint level)
|
||||
*/
|
||||
cSoftOsd::~cSoftOsd(void)
|
||||
{
|
||||
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
#ifdef OSD_DEBUG
|
||||
dsyslog("[softhddev]%s: level %d\n", __FUNCTION__, OsdLevel);
|
||||
#endif
|
||||
|
||||
SetActive(false);
|
||||
// done by SetActive: OsdClose();
|
||||
|
||||
@@ -306,14 +334,25 @@ void cSoftOsd::Flush(void)
|
||||
{
|
||||
cPixmapMemory *pm;
|
||||
|
||||
if (!Active()) {
|
||||
#ifdef OSD_DEBUG
|
||||
dsyslog("[softhddev]%s: level %d active %d\n", __FUNCTION__, OsdLevel,
|
||||
Active());
|
||||
#endif
|
||||
|
||||
if (!Active()) { // this osd is not active
|
||||
return;
|
||||
}
|
||||
// don't draw sub-title if menu is active
|
||||
if (OsdLevel >= OSD_LEVEL_SUBTITLES && IsOpen()) {
|
||||
return;
|
||||
}
|
||||
#ifdef USE_YAEPG
|
||||
// support yaepghd, video window
|
||||
if (vidWin.bpp) {
|
||||
#ifdef OSD_DEBUG
|
||||
dsyslog("[softhddev]%s: %dx%d+%d+%d\n", __FUNCTION__, vidWin.Width(),
|
||||
vidWin.Height(), vidWin.x1, vidWin.y2);
|
||||
#endif
|
||||
|
||||
// FIXME: vidWin is OSD relative not video window.
|
||||
VideoSetOutputPosition(Left() + vidWin.x1, Top() + vidWin.y1,
|
||||
@@ -321,16 +360,30 @@ void cSoftOsd::Flush(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// VDR draws subtitle without clearing the old
|
||||
//
|
||||
if (OsdLevel >= OSD_LEVEL_SUBTITLES) {
|
||||
VideoOsdClear();
|
||||
cSoftOsd::Dirty = 1;
|
||||
#ifdef OSD_DEBUG
|
||||
dsyslog("[softhddev]%s: subtitle clear\n", __FUNCTION__);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!IsTrueColor()) {
|
||||
static char warned;
|
||||
cBitmap *bitmap;
|
||||
int i;
|
||||
|
||||
#ifdef OSD_DEBUG
|
||||
static char warned;
|
||||
|
||||
if (!warned) {
|
||||
dsyslog("[softhddev]%s: FIXME: should be truecolor\n",
|
||||
__FUNCTION__);
|
||||
warned = 1;
|
||||
}
|
||||
#endif
|
||||
// draw all bitmaps
|
||||
for (i = 0; (bitmap = GetBitmap(i)); ++i) {
|
||||
uint8_t *argb;
|
||||
@@ -383,6 +436,10 @@ void cSoftOsd::Flush(void)
|
||||
bitmap->GetColor(x, y);
|
||||
}
|
||||
}
|
||||
#ifdef OSD_DEBUG
|
||||
dsyslog("[softhddev]%s: draw %dx%d+%d+%d bm\n", __FUNCTION__, w, h,
|
||||
Left() + bitmap->X0() + x1, Top() + bitmap->Y0() + y1);
|
||||
#endif
|
||||
OsdDrawARGB(Left() + bitmap->X0() + x1, Top() + bitmap->Y0() + y1,
|
||||
w, h, argb);
|
||||
|
||||
@@ -406,15 +463,15 @@ void cSoftOsd::Flush(void)
|
||||
w = pm->ViewPort().Width();
|
||||
h = pm->ViewPort().Height();
|
||||
|
||||
/*
|
||||
dsyslog("[softhddev]%s: draw %dx%d+%d+%d %p\n", __FUNCTION__, w, h,
|
||||
x, y, pm->Data());
|
||||
*/
|
||||
|
||||
#ifdef OSD_DEBUG
|
||||
dsyslog("[softhddev]%s: draw %dx%d+%d+%d %p\n", __FUNCTION__, w, h, x,
|
||||
y, pm->Data());
|
||||
#endif
|
||||
OsdDrawARGB(x, y, w, h, pm->Data());
|
||||
|
||||
delete pm;
|
||||
}
|
||||
cSoftOsd::Dirty = 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@@ -427,11 +484,12 @@ void cSoftOsd::Flush(void)
|
||||
class cSoftOsdProvider:public cOsdProvider
|
||||
{
|
||||
private:
|
||||
static cOsd *Osd;
|
||||
static cOsd *Osd; ///< single OSD
|
||||
public:
|
||||
virtual cOsd * CreateOsd(int, int, uint);
|
||||
virtual bool ProvidesTrueColor(void);
|
||||
cSoftOsdProvider(void);
|
||||
cSoftOsdProvider(void); ///< OSD provider constructor
|
||||
//virtual ~cSoftOsdProvider(); ///< OSD provider destructor
|
||||
};
|
||||
|
||||
cOsd *cSoftOsdProvider::Osd; ///< single osd
|
||||
@@ -445,7 +503,9 @@ cOsd *cSoftOsdProvider::Osd; ///< single osd
|
||||
*/
|
||||
cOsd *cSoftOsdProvider::CreateOsd(int left, int top, uint level)
|
||||
{
|
||||
//dsyslog("[softhddev]%s: %d, %d, %d\n", __FUNCTION__, left, top, level);
|
||||
#ifdef OSD_DEBUG
|
||||
dsyslog("[softhddev]%s: %d, %d, %d\n", __FUNCTION__, left, top, level);
|
||||
#endif
|
||||
|
||||
return Osd = new cSoftOsd(left, top, level);
|
||||
}
|
||||
@@ -466,9 +526,19 @@ bool cSoftOsdProvider::ProvidesTrueColor(void)
|
||||
cSoftOsdProvider::cSoftOsdProvider(void)
|
||||
: cOsdProvider()
|
||||
{
|
||||
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
#ifdef OSD_DEBUG
|
||||
dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
** Destroy cOsdProvider class.
|
||||
cSoftOsdProvider::~cSoftOsdProvider()
|
||||
{
|
||||
dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
}
|
||||
*/
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// cMenuSetupPage
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@@ -501,6 +571,11 @@ class cMenuSetupSoft:public cMenuSetupPage
|
||||
int SoftStartSync;
|
||||
int BlackPicture;
|
||||
|
||||
int Brightness;
|
||||
int Contrast;
|
||||
int Saturation;
|
||||
int Hue;
|
||||
|
||||
int ResolutionShown[RESOLUTIONS];
|
||||
int Scaling[RESOLUTIONS];
|
||||
int Deinterlace[RESOLUTIONS];
|
||||
@@ -674,6 +749,15 @@ void cMenuSetupSoft::Create(void)
|
||||
Add(new cMenuEditBoolItem(tr("Black during channel switch"),
|
||||
&BlackPicture, trVDR("no"), trVDR("yes")));
|
||||
|
||||
Add(new cMenuEditIntItem(tr("Brightness (-1000..1000) (vdpau)"),
|
||||
&Brightness, -1000, 1000, tr("min"), tr("max")));
|
||||
Add(new cMenuEditIntItem(tr("Contrast (0..10000) (vdpau)"), &Contrast,
|
||||
0, 10000, tr("min"), tr("max")));
|
||||
Add(new cMenuEditIntItem(tr("Saturation (0..10000) (vdpau)"),
|
||||
&Saturation, 0, 10000, tr("min"), tr("max")));
|
||||
Add(new cMenuEditIntItem(tr("Hue (-3141..3141) (vdpau)"), &Hue, -3141,
|
||||
3141, tr("min"), tr("max")));
|
||||
|
||||
for (i = 0; i < RESOLUTIONS; ++i) {
|
||||
cString msg;
|
||||
|
||||
@@ -840,6 +924,11 @@ cMenuSetupSoft::cMenuSetupSoft(void)
|
||||
SoftStartSync = ConfigVideoSoftStartSync;
|
||||
BlackPicture = ConfigVideoBlackPicture;
|
||||
|
||||
Brightness = ConfigVideoBrightness;
|
||||
Contrast = ConfigVideoContrast;
|
||||
Saturation = ConfigVideoSaturation;
|
||||
Hue = ConfigVideoHue;
|
||||
|
||||
for (i = 0; i < RESOLUTIONS; ++i) {
|
||||
ResolutionShown[i] = 0;
|
||||
Scaling[i] = ConfigVideoScaling[i];
|
||||
@@ -939,6 +1028,15 @@ void cMenuSetupSoft::Store(void)
|
||||
SetupStore("BlackPicture", ConfigVideoBlackPicture = BlackPicture);
|
||||
VideoSetBlackPicture(ConfigVideoBlackPicture);
|
||||
|
||||
SetupStore("Brightness", ConfigVideoBrightness = Brightness);
|
||||
VideoSetBrightness(ConfigVideoBrightness);
|
||||
SetupStore("Contrast", ConfigVideoContrast = Contrast);
|
||||
VideoSetContrast(ConfigVideoContrast);
|
||||
SetupStore("Saturation", ConfigVideoSaturation = Saturation);
|
||||
VideoSetSaturation(ConfigVideoSaturation);
|
||||
SetupStore("Hue", ConfigVideoHue = Hue);
|
||||
VideoSetHue(ConfigVideoHue);
|
||||
|
||||
for (i = 0; i < RESOLUTIONS; ++i) {
|
||||
char buf[128];
|
||||
|
||||
@@ -1059,11 +1157,9 @@ eOSState cSoftHdControl::ProcessKey(eKeys key)
|
||||
{
|
||||
if (SuspendMode == SUSPEND_NORMAL && (!ISMODELESSKEY(key)
|
||||
|| key == kMenu || key == kBack || key == kStop)) {
|
||||
if (Player) {
|
||||
delete Player;
|
||||
delete Player;
|
||||
|
||||
Player = NULL;
|
||||
}
|
||||
Player = NULL;
|
||||
Resume();
|
||||
SuspendMode = NOT_SUSPENDED;
|
||||
return osEnd;
|
||||
@@ -1084,10 +1180,13 @@ cSoftHdControl::cSoftHdControl(void)
|
||||
*/
|
||||
cSoftHdControl::~cSoftHdControl()
|
||||
{
|
||||
if (Player) {
|
||||
delete Player;
|
||||
delete Player;
|
||||
|
||||
Player = NULL;
|
||||
Player = NULL;
|
||||
// loose control resume
|
||||
if (SuspendMode == SUSPEND_NORMAL) {
|
||||
Resume();
|
||||
SuspendMode = NOT_SUSPENDED;
|
||||
}
|
||||
|
||||
dsyslog("[softhddev]%s: dummy player stopped\n", __FUNCTION__);
|
||||
@@ -1649,11 +1748,11 @@ void cSoftHdDevice::SetVideoFormat(bool video_format16_9)
|
||||
** Returns the width, height and video_aspect ratio of the currently
|
||||
** displayed video material.
|
||||
**
|
||||
** @note the size is used to scale the subtitle.
|
||||
** @note the video_aspect is used to scale the subtitle.
|
||||
*/
|
||||
void cSoftHdDevice::GetVideoSize(int &width, int &height, double &video_aspect)
|
||||
{
|
||||
::GetOsdSize(&width, &height, &video_aspect);
|
||||
::GetVideoSize(&width, &height, &video_aspect);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1840,6 +1939,8 @@ cPluginSoftHdDevice::~cPluginSoftHdDevice(void)
|
||||
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
|
||||
::SoftHdDeviceExit();
|
||||
|
||||
// keep ConfigX11Display ...
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1905,8 +2006,9 @@ bool cPluginSoftHdDevice::Start(void)
|
||||
|
||||
switch (::Start()) {
|
||||
case 1:
|
||||
cControl::Launch(new cSoftHdControl);
|
||||
cControl::Attach();
|
||||
//cControl::Launch(new cSoftHdControl);
|
||||
//cControl::Attach();
|
||||
// FIXME: VDR overwrites the control
|
||||
SuspendMode = SUSPEND_NORMAL;
|
||||
break;
|
||||
case -1:
|
||||
@@ -2060,6 +2162,22 @@ bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
|
||||
VideoSetBlackPicture(ConfigVideoBlackPicture = atoi(value));
|
||||
return true;
|
||||
}
|
||||
if (!strcasecmp(name, "Brightness")) {
|
||||
VideoSetBrightness(ConfigVideoBrightness = atoi(value));
|
||||
return true;
|
||||
}
|
||||
if (!strcasecmp(name, "Contrast")) {
|
||||
VideoSetContrast(ConfigVideoContrast = atoi(value));
|
||||
return true;
|
||||
}
|
||||
if (!strcasecmp(name, "Saturation")) {
|
||||
VideoSetSaturation(ConfigVideoSaturation = atoi(value));
|
||||
return true;
|
||||
}
|
||||
if (!strcasecmp(name, "Hue")) {
|
||||
VideoSetHue(ConfigVideoHue = atoi(value));
|
||||
return true;
|
||||
}
|
||||
for (i = 0; i < RESOLUTIONS; ++i) {
|
||||
char buf[128];
|
||||
|
||||
@@ -2196,6 +2314,14 @@ bool cPluginSoftHdDevice::Service(const char *id, void *data)
|
||||
{
|
||||
//dsyslog("[softhddev]%s: id %s\n", __FUNCTION__, id);
|
||||
|
||||
if (strcmp(id, OSD_3DMODE_SERVICE) == 0) {
|
||||
SoftHDDevice_Osd3DModeService_v1_0_t *r;
|
||||
|
||||
r = (SoftHDDevice_Osd3DModeService_v1_0_t *) data;
|
||||
VideoSetOsd3DMode(r->Mode);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (strcmp(id, ATMO_GRAB_SERVICE) == 0) {
|
||||
int width;
|
||||
int height;
|
||||
@@ -2256,9 +2382,11 @@ static const char *SVDRPHelpText[] = {
|
||||
"DETA\n" "\040 Detach plugin.\n\n"
|
||||
" The plugin will be detached from the audio, video and DVB\n"
|
||||
" devices. Other programs or plugins can use them now.\n",
|
||||
"ATTA <-d display>\n" " Attach plugin.\n\n"
|
||||
" Attach the plugin to audio, video and DVB devices.\n"
|
||||
" Use -d display (f.e. -d :0.0) to use another X11 display.\n",
|
||||
"ATTA <-d display> <-a audio> <-p pass>\n" " Attach plugin.\n\n"
|
||||
" Attach the plugin to audio, video and DVB devices. Use:\n"
|
||||
" -d display\tdisplay of x11 server (fe. :0.0)\n"
|
||||
" -a audio\taudio device (fe. alsa: hw:0,0 oss: /dev/dsp)\n"
|
||||
" -p pass\t\taudio device for pass-through (hw:0,1 or /dev/dsp1)\n",
|
||||
"PRIM <n>\n" " Make <n> the primary device.\n\n"
|
||||
" <n> is the number of device. Without number softhddevice becomes\n"
|
||||
" the primary device. If becoming primary, the plugin is attached\n"
|
||||
@@ -2284,6 +2412,9 @@ static const char *SVDRPHelpText[] = {
|
||||
" NOT_SUSPENDED == 0 (910)\n"
|
||||
" SUSPEND_NORMAL == 1 (911)\n"
|
||||
" SUSPEND_DETACHED == 2 (912)\n",
|
||||
"3DOF\n" "\040 3D OSD off.\n",
|
||||
"3DTB\n" "\040 3D OSD Top and Bottom.\n",
|
||||
"3DSB\n" "\040 3D OSD Side by Side.\n",
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -2365,16 +2496,64 @@ cString cPluginSoftHdDevice::SVDRPCommand(const char *command,
|
||||
return "SoftHdDevice is detached";
|
||||
}
|
||||
if (!strcasecmp(command, "ATTA")) {
|
||||
char *tmp;
|
||||
char *t;
|
||||
char *s;
|
||||
char *o;
|
||||
|
||||
if (SuspendMode != SUSPEND_DETACHED) {
|
||||
return "can't attach SoftHdDevice not detached";
|
||||
}
|
||||
if (!strncmp(option, "-d ", 3)) {
|
||||
// FIXME: loose memory here
|
||||
X11DisplayName = strdup(option + 3);
|
||||
} else if (!strncmp(option, "-d", 2)) {
|
||||
// FIXME: loose memory here
|
||||
X11DisplayName = strdup(option + 2);
|
||||
if (!(tmp = strdup(option))) {
|
||||
return "out of memory";
|
||||
}
|
||||
t = tmp;
|
||||
while ((s = strsep(&t, " \t\n\r"))) {
|
||||
if (!strcmp(s, "-d")) {
|
||||
if (!(o = strsep(&t, " \t\n\r"))) {
|
||||
free(tmp);
|
||||
return "missing option argument";
|
||||
}
|
||||
free(ConfigX11Display);
|
||||
ConfigX11Display = strdup(o);
|
||||
X11DisplayName = ConfigX11Display;
|
||||
} else if (!strncmp(s, "-d", 2)) {
|
||||
free(ConfigX11Display);
|
||||
ConfigX11Display = strdup(s + 2);
|
||||
X11DisplayName = ConfigX11Display;
|
||||
|
||||
} else if (!strcmp(s, "-a")) {
|
||||
if (!(o = strsep(&t, " \t\n\r"))) {
|
||||
free(tmp);
|
||||
return "missing option argument";
|
||||
}
|
||||
free(ConfigAudioDevice);
|
||||
ConfigAudioDevice = strdup(o);
|
||||
AudioSetDevice(ConfigAudioDevice);
|
||||
} else if (!strncmp(s, "-a", 2)) {
|
||||
free(ConfigAudioDevice);
|
||||
ConfigAudioDevice = strdup(s + 2);
|
||||
AudioSetDevice(ConfigAudioDevice);
|
||||
|
||||
} else if (!strcmp(s, "-p")) {
|
||||
if (!(o = strsep(&t, " \t\n\r"))) {
|
||||
free(tmp);
|
||||
return "missing option argument";
|
||||
}
|
||||
free(ConfigAC3Device);
|
||||
ConfigAC3Device = strdup(o);
|
||||
AudioSetDeviceAC3(ConfigAC3Device);
|
||||
} else if (!strncmp(s, "-p", 2)) {
|
||||
free(ConfigAC3Device);
|
||||
ConfigAC3Device = strdup(s + 2);
|
||||
AudioSetDeviceAC3(ConfigAC3Device);
|
||||
|
||||
} else if ( *s ) {
|
||||
free(tmp);
|
||||
return "unsupported option";
|
||||
}
|
||||
}
|
||||
free(tmp);
|
||||
if (ShutdownHandler.GetUserInactiveTime()) {
|
||||
ShutdownHandler.SetUserInactiveTimeout();
|
||||
}
|
||||
@@ -2403,6 +2582,19 @@ cString cPluginSoftHdDevice::SVDRPCommand(const char *command,
|
||||
DoMakePrimary = primary;
|
||||
return "switching primary device requested";
|
||||
}
|
||||
if (!strcasecmp(command, "3DOF")) {
|
||||
VideoSetOsd3DMode(0);
|
||||
return "3d off";
|
||||
}
|
||||
if (!strcasecmp(command, "3DSB")) {
|
||||
VideoSetOsd3DMode(1);
|
||||
return "3d sbs";
|
||||
}
|
||||
if (!strcasecmp(command, "3DTB")) {
|
||||
VideoSetOsd3DMode(2);
|
||||
return "3d tb";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#pragma once
|
||||
|
||||
#define ATMO_GRAB_SERVICE "SoftHDDevice-AtmoGrabService-v1.0"
|
||||
#define OSD_3DMODE_SERVICE "SoftHDDevice-Osd3DModeService-v1.0"
|
||||
|
||||
enum
|
||||
{ GRAB_IMG_RGBA_FORMAT_B8G8R8A8 };
|
||||
@@ -42,3 +43,8 @@ typedef struct
|
||||
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
|
||||
|
||||
292
video.c
292
video.c
@@ -261,7 +261,7 @@ typedef struct _video_module_
|
||||
|
||||
#define CODEC_SURFACES_MAX 31 ///< maximal of surfaces
|
||||
|
||||
#define CODEC_SURFACES_DEFAULT (21+4) ///< default of surfaces
|
||||
#define CODEC_SURFACES_DEFAULT 21 ///< default of surfaces
|
||||
// FIXME: video-xvba only supports 14
|
||||
#define xCODEC_SURFACES_DEFAULT 14 ///< default of surfaces
|
||||
|
||||
@@ -286,6 +286,7 @@ static xcb_colormap_t VideoColormap; ///< video colormap
|
||||
static xcb_window_t VideoWindow; ///< video window
|
||||
static xcb_screen_t const *VideoScreen; ///< video screen
|
||||
static uint32_t VideoBlankTick; ///< blank cursor timer
|
||||
static xcb_pixmap_t VideoCursorPixmap; ///< blank curosr pixmap
|
||||
static xcb_cursor_t VideoBlankCursor; ///< empty invisible cursor
|
||||
|
||||
static int VideoWindowX; ///< video output window x coordinate
|
||||
@@ -373,6 +374,7 @@ static pthread_mutex_t VideoLockMutex; ///< video lock mutex
|
||||
static int OsdConfigWidth; ///< osd configured width
|
||||
static int OsdConfigHeight; ///< osd configured height
|
||||
static char OsdShown; ///< flag show osd
|
||||
static char Osd3DMode; ///< 3D OSD mode
|
||||
static int OsdWidth; ///< osd width
|
||||
static int OsdHeight; ///< osd height
|
||||
static int OsdDirtyX; ///< osd dirty area x
|
||||
@@ -1270,9 +1272,10 @@ static void AutoCropDetect(AutoCropCtx * autocrop, int width, int height,
|
||||
|
||||
#ifdef USE_VAAPI
|
||||
|
||||
static int VaapiBuggyVdpau; ///< fix libva-driver-vdpau bugs
|
||||
static int VaapiBuggyIntel; ///< fix libva-driver-intel bugs
|
||||
static int VaapiNewIntel; ///< new libva-driver-intel driver
|
||||
static char VaapiBuggyXvBA; ///< fix xvba-video bugs
|
||||
static char VaapiBuggyVdpau; ///< fix libva-driver-vdpau bugs
|
||||
static char VaapiBuggyIntel; ///< fix libva-driver-intel bugs
|
||||
static char VaapiNewIntel; ///< new libva-driver-intel driver
|
||||
|
||||
static VADisplay *VaDisplay; ///< VA-API display
|
||||
|
||||
@@ -1590,7 +1593,10 @@ static VASurfaceID VaapiGetSurface(VaapiDecoder * decoder)
|
||||
surface = decoder->SurfacesFree[i];
|
||||
if (vaQuerySurfaceStatus(decoder->VaDisplay, surface, &status)
|
||||
!= VA_STATUS_SUCCESS) {
|
||||
Error(_("video/vaapi: vaQuerySurface failed\n"));
|
||||
// this fails with XvBA und mpeg softdecoder
|
||||
if (!VaapiBuggyXvBA) {
|
||||
Error(_("video/vaapi: vaQuerySurface failed\n"));
|
||||
}
|
||||
status = VASurfaceReady;
|
||||
}
|
||||
// surface still in use, try next
|
||||
@@ -2110,6 +2116,8 @@ static int VaapiInit(const char *display_name)
|
||||
display_name);
|
||||
return 0;
|
||||
}
|
||||
// XvBA needs this:
|
||||
setenv("DISPLAY", display_name, 1);
|
||||
|
||||
if (vaInitialize(VaDisplay, &major, &minor) != VA_STATUS_SUCCESS) {
|
||||
Error(_("video/vaapi: Can't inititialize VA-API on '%s'\n"),
|
||||
@@ -2129,6 +2137,9 @@ static int VaapiInit(const char *display_name)
|
||||
setenv("VDPAU_VIDEO_PUTSURFACE_FAST", "0", 0);
|
||||
VaapiBuggyVdpau = 1;
|
||||
}
|
||||
if (strstr(s, "XvBA")) {
|
||||
VaapiBuggyXvBA = 1;
|
||||
}
|
||||
if (strstr(s, "Intel i965")) {
|
||||
VaapiBuggyIntel = 1;
|
||||
}
|
||||
@@ -4534,7 +4545,10 @@ static int64_t VaapiGetClock(const VaapiDecoder * decoder)
|
||||
static void VaapiSetTrickSpeed(VaapiDecoder * decoder, int speed)
|
||||
{
|
||||
decoder->TrickSpeed = speed;
|
||||
decoder->TrickCounter = 0;
|
||||
decoder->TrickCounter = speed;
|
||||
if (speed) {
|
||||
decoder->Closing = 0;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
@@ -4652,11 +4666,13 @@ static void VaapiSyncDecoder(VaapiDecoder * decoder)
|
||||
if (!err) {
|
||||
VaapiMessage(0, NULL);
|
||||
}
|
||||
Info("video: %s%+5" PRId64 " %4" PRId64 " %3d/\\ms %3d v-buf\n",
|
||||
Info("video: %s%+5" PRId64 " %4" PRId64 " %3d/\\ms %3d+%d v-buf\n",
|
||||
Timestamp2String(video_clock),
|
||||
abs((video_clock - audio_clock) / 90) <
|
||||
8888 ? ((video_clock - audio_clock) / 90) : 8888,
|
||||
AudioGetDelay() / 90, (int)VideoDeltaPTS / 90, VideoGetBuffers());
|
||||
AudioGetDelay() / 90, (int)VideoDeltaPTS / 90, VideoGetBuffers(),
|
||||
(1 + decoder->Interlaced) * atomic_read(&decoder->SurfacesFilled)
|
||||
- decoder->SurfaceField);
|
||||
if (!(decoder->FramesDisplayed % (5 * 60 * 60))) {
|
||||
VaapiPrintFrames(decoder);
|
||||
}
|
||||
@@ -5335,7 +5351,7 @@ static void VdpauCreateSurfaces(VdpauDecoder * decoder, int width, int height)
|
||||
|
||||
#ifdef DEBUG
|
||||
if (!decoder->SurfacesNeeded) {
|
||||
Error(_("video/vaapi: surface needed not set\n"));
|
||||
Error(_("video/vdpau: surface needed not set\n"));
|
||||
decoder->SurfacesNeeded = 3 + VIDEO_SURFACES_MAX;
|
||||
}
|
||||
#endif
|
||||
@@ -6662,11 +6678,11 @@ static enum PixelFormat Vdpau_get_format(VdpauDecoder * decoder,
|
||||
// check profile
|
||||
switch (video_ctx->codec_id) {
|
||||
case CODEC_ID_MPEG1VIDEO:
|
||||
max_refs = 2;
|
||||
max_refs = CODEC_SURFACES_MPEG2;
|
||||
profile = VdpauCheckProfile(decoder, VDP_DECODER_PROFILE_MPEG1);
|
||||
break;
|
||||
case CODEC_ID_MPEG2VIDEO:
|
||||
max_refs = 2;
|
||||
max_refs = CODEC_SURFACES_MPEG2;
|
||||
profile =
|
||||
VdpauCheckProfile(decoder, VDP_DECODER_PROFILE_MPEG2_MAIN);
|
||||
break;
|
||||
@@ -7371,14 +7387,8 @@ static void VdpauRenderFrame(VdpauDecoder * decoder,
|
||||
decoder->InputWidth = video_ctx->width;
|
||||
decoder->InputHeight = video_ctx->height;
|
||||
|
||||
//
|
||||
// detect interlaced input
|
||||
//
|
||||
Debug(3, "video/vdpau: interlaced %d top-field-first %d\n",
|
||||
frame->interlaced_frame, frame->top_field_first);
|
||||
// FIXME: I hope this didn't change in the middle of the stream
|
||||
|
||||
VdpauCleanup(decoder);
|
||||
decoder->SurfacesNeeded = VIDEO_SURFACES_MAX + 2;
|
||||
VdpauSetupOutput(decoder);
|
||||
}
|
||||
//
|
||||
@@ -7392,6 +7402,7 @@ static void VdpauRenderFrame(VdpauDecoder * decoder,
|
||||
default:
|
||||
Fatal(_("video/vdpau: pixel format %d not supported\n"),
|
||||
video_ctx->pix_fmt);
|
||||
// FIXME: no fatals!
|
||||
}
|
||||
|
||||
// convert ffmpeg order to vdpau
|
||||
@@ -7411,6 +7422,8 @@ static void VdpauRenderFrame(VdpauDecoder * decoder,
|
||||
VdpauGetErrorString(status));
|
||||
}
|
||||
|
||||
Debug(4, "video/vdpau: sw render hw surface %#08x\n", surface);
|
||||
|
||||
VdpauQueueSurface(decoder, surface, 1);
|
||||
}
|
||||
|
||||
@@ -7427,6 +7440,7 @@ static void VdpauMixOsd(void)
|
||||
VdpOutputSurfaceRenderBlendState blend_state;
|
||||
VdpRect source_rect;
|
||||
VdpRect output_rect;
|
||||
VdpRect output_double_rect;
|
||||
VdpStatus status;
|
||||
|
||||
//uint32_t start;
|
||||
@@ -7474,6 +7488,25 @@ static void VdpauMixOsd(void)
|
||||
output_rect.y1 = VideoWindowHeight;
|
||||
}
|
||||
|
||||
output_double_rect = output_rect;
|
||||
|
||||
switch (Osd3DMode) {
|
||||
case 1:
|
||||
output_rect.x0 = output_rect.x0 / 2;
|
||||
output_rect.x1 = output_rect.x1 / 2;
|
||||
output_double_rect.x0 = output_rect.x0 + (VideoWindowWidth / 2);
|
||||
output_double_rect.x1 = output_rect.x1 + (VideoWindowWidth / 2);
|
||||
break;
|
||||
case 2:
|
||||
output_rect.y0 = output_rect.y0 / 2;
|
||||
output_rect.y1 = output_rect.y1 / 2;
|
||||
output_double_rect.y0 = output_rect.y0 + (VideoWindowHeight / 2);
|
||||
output_double_rect.y1 = output_rect.y1 + (VideoWindowHeight / 2);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
//start = GetMsTicks();
|
||||
|
||||
// FIXME: double buffered osd disabled
|
||||
@@ -7489,6 +7522,19 @@ static void VdpauMixOsd(void)
|
||||
Error(_("video/vdpau: can't render bitmap surface: %s\n"),
|
||||
VdpauGetErrorString(status));
|
||||
}
|
||||
|
||||
if (Osd3DMode > 0) {
|
||||
status =
|
||||
VdpauOutputSurfaceRenderBitmapSurface(VdpauSurfacesRb
|
||||
[VdpauSurfaceIndex], &output_double_rect,
|
||||
VdpauOsdOutputSurface[!VdpauOsdSurfaceIndex], &source_rect, NULL,
|
||||
VideoTransparentOsd ? &blend_state : NULL,
|
||||
VDP_OUTPUT_SURFACE_RENDER_ROTATE_0);
|
||||
if (status != VDP_STATUS_OK) {
|
||||
Error(_("video/vdpau: can't render output surface: %s\n"),
|
||||
VdpauGetErrorString(status));
|
||||
}
|
||||
}
|
||||
#else
|
||||
status =
|
||||
VdpauOutputSurfaceRenderOutputSurface(VdpauSurfacesRb
|
||||
@@ -7500,6 +7546,19 @@ static void VdpauMixOsd(void)
|
||||
Error(_("video/vdpau: can't render output surface: %s\n"),
|
||||
VdpauGetErrorString(status));
|
||||
}
|
||||
|
||||
if (Osd3DMode > 0) {
|
||||
status =
|
||||
VdpauOutputSurfaceRenderOutputSurface(VdpauSurfacesRb
|
||||
[VdpauSurfaceIndex], &output_double_rect,
|
||||
VdpauOsdOutputSurface[!VdpauOsdSurfaceIndex], &source_rect, NULL,
|
||||
VideoTransparentOsd ? &blend_state : NULL,
|
||||
VDP_OUTPUT_SURFACE_RENDER_ROTATE_0);
|
||||
if (status != VDP_STATUS_OK) {
|
||||
Error(_("video/vdpau: can't render output surface: %s\n"),
|
||||
VdpauGetErrorString(status));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
//end = GetMsTicks();
|
||||
/*
|
||||
@@ -7634,7 +7693,12 @@ static void VdpauMixVideo(VdpauDecoder * decoder)
|
||||
&video_src_rect, VdpauSurfacesRb[VdpauSurfaceIndex], &dst_rect,
|
||||
&dst_video_rect, 0, NULL);
|
||||
} else {
|
||||
current = decoder->SurfacesRb[decoder->SurfaceRead];
|
||||
if (decoder->Interlaced) {
|
||||
current = decoder->SurfacesRb[(decoder->SurfaceRead + 1)
|
||||
% VIDEO_SURFACES_MAX];
|
||||
} else {
|
||||
current = decoder->SurfacesRb[decoder->SurfaceRead];
|
||||
}
|
||||
|
||||
status =
|
||||
VdpauVideoMixerRender(decoder->VideoMixer, VDP_INVALID_HANDLE,
|
||||
@@ -7760,8 +7824,8 @@ static void VdpauDisplayFrame(void)
|
||||
// FIXME: 21 only correct for 50Hz
|
||||
if (last_time && first_time > last_time + 21 * 1000 * 1000) {
|
||||
// FIXME: ignore still-frame, trick-speed
|
||||
Debug(3, "video/vdpau: %ld display time %ld\n", first_time / 1000,
|
||||
(first_time - last_time) / 1000);
|
||||
Debug(3, "video/vdpau: %" PRId64 " display time %" PRId64 "\n",
|
||||
first_time / 1000, (first_time - last_time) / 1000);
|
||||
// FIXME: can be more than 1 frame long shown
|
||||
for (i = 0; i < VdpauDecoderN; ++i) {
|
||||
VdpauDecoders[i]->FramesMissed++;
|
||||
@@ -7787,7 +7851,8 @@ static void VdpauDisplayFrame(void)
|
||||
// need 1 frame for progressive, 3 frames for interlaced
|
||||
if (filled < 1 + 2 * decoder->Interlaced) {
|
||||
// FIXME: rewrite MixVideo to support less surfaces
|
||||
if (VideoShowBlackPicture || decoder->Closing < -300) {
|
||||
if ((VideoShowBlackPicture && !decoder->TrickSpeed)
|
||||
|| decoder->Closing < -300) {
|
||||
VdpauBlackSurface(decoder);
|
||||
VdpauMessage(3, "video/vdpau: black surface displayed\n");
|
||||
}
|
||||
@@ -7876,6 +7941,9 @@ static void VdpauSetTrickSpeed(VdpauDecoder * decoder, int speed)
|
||||
{
|
||||
decoder->TrickSpeed = speed;
|
||||
decoder->TrickCounter = speed;
|
||||
if (speed) {
|
||||
decoder->Closing = 0;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
@@ -7992,11 +8060,13 @@ static void VdpauSyncDecoder(VdpauDecoder * decoder)
|
||||
if (!err) {
|
||||
VdpauMessage(0, NULL);
|
||||
}
|
||||
Info("video: %s%+5" PRId64 " %4" PRId64 " %3d/\\ms %3d v-buf\n",
|
||||
Info("video: %s%+5" PRId64 " %4" PRId64 " %3d/\\ms %3d+%d v-buf\n",
|
||||
Timestamp2String(video_clock),
|
||||
abs((video_clock - audio_clock) / 90) <
|
||||
8888 ? ((video_clock - audio_clock) / 90) : 8888,
|
||||
AudioGetDelay() / 90, (int)VideoDeltaPTS / 90, VideoGetBuffers());
|
||||
AudioGetDelay() / 90, (int)VideoDeltaPTS / 90, VideoGetBuffers(),
|
||||
(1 + decoder->Interlaced) * atomic_read(&decoder->SurfacesFilled)
|
||||
- decoder->SurfaceField);
|
||||
if (!(decoder->FramesDisplayed % (5 * 60 * 60))) {
|
||||
VdpauPrintFrames(decoder);
|
||||
}
|
||||
@@ -8273,7 +8343,7 @@ static void VdpauSetOutputPosition(VdpauDecoder * decoder, int x, int y,
|
||||
// VDPAU OSD
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
static const uint8_t OsdZeros[1920 * 1080 * 4]; ///< 0 for clear osd
|
||||
static const uint8_t OsdZeros[1920 * 1200 * 4]; ///< 0 for clear osd
|
||||
|
||||
///
|
||||
/// Clear subpicture image.
|
||||
@@ -8301,7 +8371,7 @@ static void VdpauOsdClear(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (OsdWidth * OsdHeight > 1920 * 1080) {
|
||||
if (OsdWidth * OsdHeight > 1920 * 1200) {
|
||||
Error(_("video/vdpau: osd too big: unsupported\n"));
|
||||
return;
|
||||
}
|
||||
@@ -8812,6 +8882,16 @@ void VideoSetOsdSize(int width, int height)
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Set the 3d OSD mode.
|
||||
///
|
||||
/// @pram mode OSD mode (0=off, 1=SBS, 2=Top Bottom)
|
||||
///
|
||||
void VideoSetOsd3DMode(int mode)
|
||||
{
|
||||
Osd3DMode = mode;
|
||||
}
|
||||
|
||||
///
|
||||
/// Setup osd.
|
||||
///
|
||||
@@ -9315,7 +9395,6 @@ enum PixelFormat Video_get_format(VideoHwDecoder * hw_decoder,
|
||||
Timestamp2String(VideoGetClock(hw_decoder)), ms_delay);
|
||||
#endif
|
||||
|
||||
//AudioVideoReady(VideoGetClock(hw_decoder));
|
||||
return VideoUsedModule->get_format(hw_decoder, video_ctx, fmt);
|
||||
}
|
||||
|
||||
@@ -9329,6 +9408,10 @@ enum PixelFormat Video_get_format(VideoHwDecoder * hw_decoder,
|
||||
void VideoRenderFrame(VideoHwDecoder * hw_decoder,
|
||||
const AVCodecContext * video_ctx, const AVFrame * frame)
|
||||
{
|
||||
#if 0
|
||||
fprintf(stderr, "video: render frame pts %s closing %d\n",
|
||||
Timestamp2String(frame->pkt_pts), hw_decoder->Vdpau.Closing);
|
||||
#endif
|
||||
if (frame->repeat_pict && !VideoIgnoreRepeatPict) {
|
||||
Warning(_("video: repeated pict %d found, but not handled\n"),
|
||||
frame->repeat_pict);
|
||||
@@ -9400,8 +9483,8 @@ void VideoDrawRenderState(VideoHwDecoder * hw_decoder,
|
||||
}
|
||||
if (end - start > 35) {
|
||||
// report this
|
||||
Info(_("video/vdpau: decoder render too slow %ums\n"),
|
||||
end - start);
|
||||
Info(_("video/vdpau: %s: decoder render too slow %ums\n"),
|
||||
Timestamp2String(decoder->PTS), end - start);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -9454,7 +9537,7 @@ void VideoSetClosing(VideoHwDecoder * hw_decoder)
|
||||
hw_decoder->Vdpau.Closing = 1;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_VAPI
|
||||
#ifdef USE_VAAPI
|
||||
if (VideoUsedModule == &VaapiModule) {
|
||||
hw_decoder->Vaapi.Closing = 1;
|
||||
}
|
||||
@@ -9477,7 +9560,7 @@ void VideoResetStart(VideoHwDecoder * hw_decoder)
|
||||
hw_decoder->Vdpau.StartCounter = 0;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_VAPI
|
||||
#ifdef USE_VAAPI
|
||||
if (VideoUsedModule == &VaapiModule) {
|
||||
hw_decoder->Vaapi.StartCounter = 0;
|
||||
}
|
||||
@@ -9663,7 +9746,7 @@ void VideoGetStats(VideoHwDecoder * hw_decoder, int *missed, int *duped,
|
||||
*counter = hw_decoder->Vdpau.FrameCounter;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_VAPI
|
||||
#ifdef USE_VAAPI
|
||||
if (VideoUsedModule == &VaapiModule) {
|
||||
*missed = hw_decoder->Vaapi.FramesMissed;
|
||||
*duped = hw_decoder->Vaapi.FramesDuped;
|
||||
@@ -9673,6 +9756,46 @@ void VideoGetStats(VideoHwDecoder * hw_decoder, int *missed, int *duped,
|
||||
#endif
|
||||
}
|
||||
|
||||
///
|
||||
/// Get decoder video stream size.
|
||||
///
|
||||
/// @param hw_decoder video hardware decoder
|
||||
/// @param[out] width video stream width
|
||||
/// @param[out] height video stream height
|
||||
/// @param[out] aspect_num video stream aspect numerator
|
||||
/// @param[out] aspect_den video stream aspect denominator
|
||||
///
|
||||
void VideoGetVideoSize(VideoHwDecoder * hw_decoder, int *width, int *height,
|
||||
int *aspect_num, int *aspect_den)
|
||||
{
|
||||
*width = 1920;
|
||||
*height = 1080;
|
||||
*aspect_num = 16;
|
||||
*aspect_den = 9;
|
||||
// FIXME: test to check if working, than make module function
|
||||
#ifdef USE_VDPAU
|
||||
if (VideoUsedModule == &VdpauModule) {
|
||||
*width = hw_decoder->Vdpau.InputWidth;
|
||||
*height = hw_decoder->Vdpau.InputHeight;
|
||||
av_reduce(aspect_num, aspect_den,
|
||||
hw_decoder->Vdpau.InputWidth * hw_decoder->Vdpau.InputAspect.num,
|
||||
hw_decoder->Vdpau.InputHeight * hw_decoder->Vdpau.InputAspect.den,
|
||||
1024 * 1024);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_VAAPI
|
||||
if (VideoUsedModule == &VaapiModule) {
|
||||
*width = hw_decoder->Vaapi.InputWidth;
|
||||
*height = hw_decoder->Vaapi.InputHeight;
|
||||
av_reduce(aspect_num, aspect_den,
|
||||
hw_decoder->Vaapi.InputWidth * hw_decoder->Vaapi.InputAspect.num,
|
||||
hw_decoder->Vaapi.InputHeight * hw_decoder->Vaapi.InputAspect.den,
|
||||
1024 * 1024);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#ifdef USE_SCREENSAVER
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -9917,9 +10040,9 @@ static void VideoCreateWindow(xcb_window_t parent, xcb_visualid_t visual,
|
||||
values[0] = cursor;
|
||||
xcb_change_window_attributes(Connection, VideoWindow, XCB_CW_CURSOR,
|
||||
values);
|
||||
VideoCursorPixmap = pixmap;
|
||||
VideoBlankCursor = cursor;
|
||||
VideoBlankTick = 0;
|
||||
// FIXME: free cursor/pixmap needed?
|
||||
}
|
||||
|
||||
///
|
||||
@@ -9932,6 +10055,19 @@ void VideoSetDevice(const char *device)
|
||||
VideoDevice = device;
|
||||
}
|
||||
|
||||
///
|
||||
/// Get video driver name.
|
||||
///
|
||||
/// @returns name of current video driver.
|
||||
///
|
||||
const char *VideoGetDriverName(void)
|
||||
{
|
||||
if (VideoUsedModule) {
|
||||
return VideoUsedModule->Name;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
///
|
||||
/// Set video geometry.
|
||||
///
|
||||
@@ -9977,6 +10113,70 @@ void VideoSetBlackPicture(int onoff)
|
||||
VideoShowBlackPicture = onoff;
|
||||
}
|
||||
|
||||
///
|
||||
/// Set brightness adjustment.
|
||||
///
|
||||
/// @param brightness between -1000 and 1000.
|
||||
/// 0 represents no modification
|
||||
///
|
||||
void VideoSetBrightness(int brightness)
|
||||
{
|
||||
#ifdef USE_VDPAU
|
||||
if (VideoUsedModule == &VdpauModule) {
|
||||
VdpauDecoders[0]->Procamp.brightness = brightness / 1000;
|
||||
}
|
||||
#endif
|
||||
// FIXME: VA-API support
|
||||
}
|
||||
|
||||
///
|
||||
/// Set contrast adjustment.
|
||||
///
|
||||
/// @param contrast between 0 and 10000.
|
||||
/// 1000 represents no modification
|
||||
///
|
||||
void VideoSetContrast(int contrast)
|
||||
{
|
||||
#ifdef USE_VDPAU
|
||||
if (VideoUsedModule == &VdpauModule) {
|
||||
VdpauDecoders[0]->Procamp.contrast = contrast / 1000;
|
||||
}
|
||||
#endif
|
||||
// FIXME: VA-API support
|
||||
}
|
||||
|
||||
///
|
||||
/// Set saturation adjustment.
|
||||
///
|
||||
/// @param saturation between 0 and 10000.
|
||||
/// 1000 represents no modification
|
||||
///
|
||||
void VideoSetSaturation(int saturation)
|
||||
{
|
||||
#ifdef USE_VDPAU
|
||||
if (VideoUsedModule == &VdpauModule) {
|
||||
VdpauDecoders[0]->Procamp.saturation = saturation / 1000;
|
||||
}
|
||||
#endif
|
||||
// FIXME: VA-API support
|
||||
}
|
||||
|
||||
///
|
||||
/// Set hue adjustment.
|
||||
///
|
||||
/// @param hue between -PI*1000 and PI*1000.
|
||||
/// 0 represents no modification
|
||||
///
|
||||
void VideoSetHue(int hue)
|
||||
{
|
||||
#ifdef USE_VDPAU
|
||||
if (VideoUsedModule == &VdpauModule) {
|
||||
VdpauDecoders[0]->Procamp.hue = hue / 1000;
|
||||
}
|
||||
#endif
|
||||
// FIXME: VA-API support
|
||||
}
|
||||
|
||||
///
|
||||
/// Set video output position.
|
||||
///
|
||||
@@ -10004,7 +10204,7 @@ void VideoSetOutputPosition(int x, int y, int width, int height)
|
||||
VdpauSetOutputPosition(VdpauDecoders[0], x, y, width, height);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_VAPI
|
||||
#ifdef USE_VAAPI
|
||||
// FIXME: not supported by vaapi without unscaled OSD,
|
||||
// FIXME: if used to position video inside osd
|
||||
#endif
|
||||
@@ -10412,7 +10612,9 @@ void VideoExit(void)
|
||||
if (!XlibDisplay) { // no init or failed
|
||||
return;
|
||||
}
|
||||
// reenable x11 screensaver
|
||||
//
|
||||
// Reenable screensaver / DPMS.
|
||||
//
|
||||
X11DPMSReenable(Connection);
|
||||
X11SuspendScreenSaver(Connection, 0);
|
||||
|
||||
@@ -10430,12 +10632,6 @@ void VideoExit(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// Reenable screensaver / DPMS.
|
||||
//
|
||||
//X11SuspendScreenSaver(XlibDisplay, False);
|
||||
//X11DPMSEnable(XlibDisplay);
|
||||
|
||||
//
|
||||
// FIXME: cleanup.
|
||||
//
|
||||
@@ -10448,11 +10644,25 @@ void VideoExit(void)
|
||||
xcb_destroy_window(Connection, VideoWindow);
|
||||
VideoWindow = XCB_NONE;
|
||||
}
|
||||
if (VideoColormap != XCB_NONE) {
|
||||
xcb_free_colormap(Connection, VideoColormap);
|
||||
VideoColormap = XCB_NONE;
|
||||
}
|
||||
if (VideoBlankCursor != XCB_NONE) {
|
||||
xcb_free_cursor(Connection, VideoBlankCursor);
|
||||
VideoBlankCursor = XCB_NONE;
|
||||
}
|
||||
if (VideoCursorPixmap != XCB_NONE) {
|
||||
xcb_free_pixmap(Connection, VideoCursorPixmap);
|
||||
VideoCursorPixmap = XCB_NONE;
|
||||
}
|
||||
xcb_flush(Connection);
|
||||
if (XlibDisplay) {
|
||||
if (XCloseDisplay(XlibDisplay)) {
|
||||
Error(_("video: error closing display\n"));
|
||||
}
|
||||
XlibDisplay = NULL;
|
||||
Connection = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
21
video.h
21
video.h
@@ -82,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 *);
|
||||
|
||||
@@ -94,6 +97,18 @@ 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);
|
||||
|
||||
@@ -154,6 +169,9 @@ 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);
|
||||
|
||||
@@ -178,6 +196,9 @@ 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.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user