39 Commits
0.5.1 ... 0.5.2

Author SHA1 Message Date
Johns
9a2b6f860a Version 0.5.2 released. 2012-11-15 22:30:55 +01:00
10075aa501 Fix 3d OSD position. 2012-11-05 23:13:42 +01:00
Johns
cb91c779d3 Correct offsets for 3D OSD. Allow 1920x1200 OSD. 2012-11-05 12:03:50 +01:00
Johns
aad3742670 Log subtitle clear. 2012-11-01 14:12:31 +01:00
Johns
1b23074de7 Ignore empty options. 2012-10-31 10:20:07 +01:00
Johns
78015d90fb 3D update. 2012-10-30 16:53:40 +01:00
0286c434b4 Add support to change OSD for 3d SBS/TB streams. 2012-10-30 16:50:31 +01:00
Johns
6e9e641453 Comment how to change the error recognition. 2012-10-30 12:11:25 +01:00
Johns
d36e4c22b6 Removes debug output slipped into GIT. 2012-10-30 12:10:25 +01:00
Johns
7e4657e615 Use software decoder for still-pictures. 2012-10-29 23:06:00 +01:00
Johns
84e8e58c91 Don't show black picture during still-pictures. 2012-10-29 19:29:43 +01:00
Johns
141eb5cf71 Flush X11 output buffer before close. 2012-10-29 17:24:58 +01:00
Johns
a9e664ac52 Add Feature #1103: change audio without vdr restart. 2012-10-29 16:00:45 +01:00
Johns
30952face4 Fix bug #1089: vdpau wrong number of mpeg refs. 2012-10-24 15:38:09 +02:00
Johns
0519aff4d8 Removed double comment. 2012-10-19 15:38:05 +02:00
Johns
92b4203644 Fix bug: possible endless loop in pes audio parser. 2012-10-19 15:36:41 +02:00
Johns
f640ebdeb5 Report correct size in cSoftHdDevice::GetVideoSize. 2012-10-10 17:26:49 +02:00
Johns
de7c4b2a96 Workaround for bug #1069.
Option -s (start in suspended mode) does not work anymore.
2012-10-06 19:16:10 +02:00
Johns
0cf4598f68 Jpeg isn't longer used. 2012-09-15 21:40:04 +02:00
Johns
80dfa4a80f Close all filehandles before exec.
Add stillpicture debug.
Some small stillpicture fixes.
2012-09-15 21:38:54 +02:00
Johns
0a78944996 Fix bug: hue menu entry changes brightness. 2012-09-14 16:53:13 +02:00
Johns
142c3b16f6 Fix bug: didn't compile without vdpau support. 2012-09-11 00:24:27 +02:00
Johns
73fe963c36 Add picture adjustment support for vdpau. 2012-09-03 16:39:33 +02:00
Johns
a61cbcb65a Add PTS to render too slow message. 2012-08-29 17:00:36 +02:00
Johns
3df9acc034 Add number of buffered video output frames to info. 2012-08-28 19:15:11 +02:00
Johns
d9c9061a7c Reset closing only, if trickspeed is set. 2012-08-18 15:53:14 +02:00
Johns
e9fbe6b54f Need get_format for software decoder. 2012-08-17 10:35:52 +02:00
Johns
5e93fb2756 Fix bug: VA-API trickspeed. 2012-08-17 10:33:10 +02:00
Johns
e02c1fa5f9 Revert "mpeg_vdpau" back to "mpegvideo_vdpau". 2012-08-14 16:02:44 +02:00
Johns
c07ec82e6d Fix bug: Can't use software decoder with VDPAU. 2012-08-13 16:57:36 +02:00
Johns
ecb48a5d63 Resume plugin, if dummy player looses control. 2012-08-09 16:22:06 +02:00
Johns
9efc73144d Removes old audio code (!USE_AUDIORING). 2012-08-08 22:58:57 +02:00
a920da652b Osd work:
Use -DOSD_DEBUG to debug OSD.
Fix bug #909: Subtitles destroy menu.
Fix bug #1003: Subtitles overlapping.
2012-08-07 16:46:23 +02:00
Johns
9ec077ec8a VA-API/XvBA backend improvements. 2012-07-27 19:15:48 +02:00
Johns
8b0d8d8446 Free used X11 resources colormap, pixmap, cursor. 2012-07-25 16:07:36 +02:00
Johns
15583a79c4 FreeBSD compatibility fix. 2012-07-09 17:17:16 +02:00
Johns
2cdce610d6 Fix bug: spelling USE_VAPI wrong, missing function. 2012-07-06 00:04:08 +02:00
Johns
2d6d151b85 Fix compiler warnings. 2012-07-05 23:59:28 +02:00
Johns
ca4f519a1f Force ffmpeg with hardware codec support. 2012-07-05 17:10:05 +02:00
13 changed files with 765 additions and 1693 deletions

2
.gitignore vendored
View File

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

View File

@@ -1,3 +1,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

View File

@@ -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
View File

@@ -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

1568
audio.c

File diff suppressed because it is too large Load Diff

52
codec.c
View File

@@ -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) {

View File

@@ -22,6 +22,9 @@
#include <sys/types.h>
#include <sys/stat.h>
#ifdef __FreeBSD__
#include <signal.h>
#endif
#include <fcntl.h>
#include <stdio.h>
@@ -56,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);

View File

@@ -53,6 +53,8 @@ extern "C"
extern int SetPlayMode(int);
/// C plugin get current system time counter
extern int64_t GetSTC(void);
/// C plugin get video stream size and aspect
extern void GetVideoSize(int *, int *, double *);
/// C plugin set trick speed
extern void TrickSpeed(int);
/// C plugin clears all video and audio data from the device

View File

@@ -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;
}

View File

@@ -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;

View File

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

292
video.c
View File

@@ -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
View File

@@ -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.