mirror of
https://projects.vdr-developer.org/git/vdr-plugin-softhddevice.git
synced 2023-10-10 19:16:51 +02:00
Audio/Video sync rewrite.
Trick-speed support moved to video module. Reduce video messages.
This commit is contained in:
parent
b41f934c37
commit
c9b344a3fd
@ -2,6 +2,7 @@ User johns
|
|||||||
Date:
|
Date:
|
||||||
|
|
||||||
Release Version 0.5.0
|
Release Version 0.5.0
|
||||||
|
Audio/Video sync rewrite, trick-speed support moved to video.
|
||||||
Faster VdpauBlackSurface version.
|
Faster VdpauBlackSurface version.
|
||||||
Fix bug: VideoSetPts wrong position for multi frame packets.
|
Fix bug: VideoSetPts wrong position for multi frame packets.
|
||||||
|
|
||||||
@ -13,7 +14,6 @@ Date: Mon Mar 26 20:45:54 CEST 2012
|
|||||||
User johns
|
User johns
|
||||||
Date: Fri Mar 23 18:43:20 CET 2012
|
Date: Fri Mar 23 18:43:20 CET 2012
|
||||||
|
|
||||||
Audio/Video sync rewrite, trick-speed support moved to video.
|
|
||||||
Add optional argument (display) to ATTA svdrp commmand.
|
Add optional argument (display) to ATTA svdrp commmand.
|
||||||
Wakeup display to show OSD for remote learning mode.
|
Wakeup display to show OSD for remote learning mode.
|
||||||
Support switching the primary device with svdrp.
|
Support switching the primary device with svdrp.
|
||||||
|
97
softhddev.c
97
softhddev.c
@ -1130,8 +1130,11 @@ void SetVolumeDevice(int volume)
|
|||||||
|
|
||||||
#include <alsa/iatomic.h> // portable atomic_t
|
#include <alsa/iatomic.h> // portable atomic_t
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
uint32_t VideoSwitch; ///< debug video switch ticks
|
uint32_t VideoSwitch; ///< debug video switch ticks
|
||||||
|
#endif
|
||||||
static volatile char NewVideoStream; ///< flag new video stream
|
static volatile char NewVideoStream; ///< flag new video stream
|
||||||
|
static volatile char ClosingVideoStream; ///< flag closing video stream
|
||||||
static VideoHwDecoder *MyHwDecoder; ///< video hw decoder
|
static VideoHwDecoder *MyHwDecoder; ///< video hw decoder
|
||||||
static VideoDecoder *MyVideoDecoder; ///< video decoder
|
static VideoDecoder *MyVideoDecoder; ///< video decoder
|
||||||
static enum CodecID VideoCodecID; ///< current codec id
|
static enum CodecID VideoCodecID; ///< current codec id
|
||||||
@ -1150,8 +1153,7 @@ static atomic_t VideoPacketsFilled; ///< how many of the buffer is used
|
|||||||
static volatile char VideoClearBuffers; ///< clear video buffers
|
static volatile char VideoClearBuffers; ///< clear video buffers
|
||||||
static volatile char VideoClearClose; ///< clear video buffers upto close
|
static volatile char VideoClearClose; ///< clear video buffers upto close
|
||||||
static volatile char SkipVideo; ///< skip video
|
static volatile char SkipVideo; ///< skip video
|
||||||
static volatile char VideoTrickSpeed; ///< current trick speed
|
static volatile char CurrentTrickSpeed; ///< current trick speed
|
||||||
static volatile char VideoTrickCounter; ///< current trick speed counter
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
static int VideoMaxPacketSize; ///< biggest used packet buffer
|
static int VideoMaxPacketSize; ///< biggest used packet buffer
|
||||||
@ -1340,6 +1342,10 @@ void FixPacketForFFMpeg(VideoDecoder * MyVideoDecoder, AVPacket * avpkt)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
** Decode from PES packet ringbuffer.
|
** Decode from PES packet ringbuffer.
|
||||||
|
**
|
||||||
|
** @retval 0 packet decoded
|
||||||
|
** @retval 1 stream paused
|
||||||
|
** @retval -1 empty stream
|
||||||
*/
|
*/
|
||||||
int VideoDecode(void)
|
int VideoDecode(void)
|
||||||
{
|
{
|
||||||
@ -1360,19 +1366,13 @@ int VideoDecode(void)
|
|||||||
VideoClearBuffers = 0;
|
VideoClearBuffers = 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (VideoTrickSpeed) {
|
|
||||||
if (VideoTrickCounter++ < VideoTrickSpeed * 2) {
|
|
||||||
usleep(5 * 1000);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
VideoTrickCounter = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
filled = atomic_read(&VideoPacketsFilled);
|
filled = atomic_read(&VideoPacketsFilled);
|
||||||
if (!filled) {
|
if (!filled) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (VideoClearClose) {
|
// clearing for normal channel switch has no advantage
|
||||||
|
if (VideoClearClose /*|| ClosingVideoStream */ ) {
|
||||||
int f;
|
int f;
|
||||||
|
|
||||||
// flush buffers, if close is in the queue
|
// flush buffers, if close is in the queue
|
||||||
@ -1388,6 +1388,7 @@ int VideoDecode(void)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ClosingVideoStream = 0;
|
||||||
}
|
}
|
||||||
avpkt = &VideoPacketRb[VideoPacketRead];
|
avpkt = &VideoPacketRb[VideoPacketRead];
|
||||||
|
|
||||||
@ -1396,11 +1397,13 @@ int VideoDecode(void)
|
|||||||
//
|
//
|
||||||
switch ((int)(size_t) avpkt->priv) {
|
switch ((int)(size_t) avpkt->priv) {
|
||||||
case CODEC_ID_NONE:
|
case CODEC_ID_NONE:
|
||||||
|
ClosingVideoStream = 0;
|
||||||
if (last_codec_id != CODEC_ID_NONE) {
|
if (last_codec_id != CODEC_ID_NONE) {
|
||||||
last_codec_id = CODEC_ID_NONE;
|
last_codec_id = CODEC_ID_NONE;
|
||||||
CodecVideoClose(MyVideoDecoder);
|
CodecVideoClose(MyVideoDecoder);
|
||||||
goto skip;
|
goto skip;
|
||||||
}
|
}
|
||||||
|
// FIXME: look if more close are in the queue
|
||||||
// size can be zero
|
// size can be zero
|
||||||
goto skip;
|
goto skip;
|
||||||
case CODEC_ID_MPEG2VIDEO:
|
case CODEC_ID_MPEG2VIDEO:
|
||||||
@ -1450,6 +1453,11 @@ int VideoDecode(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ClosingVideoStream) { // closing don't sync
|
||||||
|
avpkt->pts = AV_NOPTS_VALUE;
|
||||||
|
avpkt->dts = AV_NOPTS_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
if (last_codec_id == CODEC_ID_MPEG2VIDEO) {
|
if (last_codec_id == CODEC_ID_MPEG2VIDEO) {
|
||||||
FixPacketForFFMpeg(MyVideoDecoder, avpkt);
|
FixPacketForFFMpeg(MyVideoDecoder, avpkt);
|
||||||
} else {
|
} else {
|
||||||
@ -1618,7 +1626,7 @@ int PlayVideo(const uint8_t * data, int size)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (NewVideoStream) { // channel switched
|
if (NewVideoStream) { // channel switched
|
||||||
Debug(3, "video: new stream %d\n", GetMsTicks() - VideoSwitch);
|
Debug(3, "video: new stream %dms\n", GetMsTicks() - VideoSwitch);
|
||||||
// FIXME: hack to test results
|
// FIXME: hack to test results
|
||||||
if (atomic_read(&VideoPacketsFilled) >= VIDEO_PACKET_MAX - 1) {
|
if (atomic_read(&VideoPacketsFilled) >= VIDEO_PACKET_MAX - 1) {
|
||||||
Debug(3, "video: new video stream lost\n");
|
Debug(3, "video: new video stream lost\n");
|
||||||
@ -1627,6 +1635,9 @@ int PlayVideo(const uint8_t * data, int size)
|
|||||||
}
|
}
|
||||||
VideoNextPacket(CODEC_ID_NONE);
|
VideoNextPacket(CODEC_ID_NONE);
|
||||||
VideoCodecID = CODEC_ID_NONE;
|
VideoCodecID = CODEC_ID_NONE;
|
||||||
|
// clear clock until new stream starts
|
||||||
|
VideoSetClock(MyHwDecoder, AV_NOPTS_VALUE);
|
||||||
|
ClosingVideoStream = 1;
|
||||||
NewVideoStream = 0;
|
NewVideoStream = 0;
|
||||||
}
|
}
|
||||||
// must be a PES start code
|
// must be a PES start code
|
||||||
@ -1638,13 +1649,14 @@ int PlayVideo(const uint8_t * data, int size)
|
|||||||
if (data[3] == PES_PADDING_STREAM) { // from DVD plugin
|
if (data[3] == PES_PADDING_STREAM) { // from DVD plugin
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
n = data[8]; // header size
|
|
||||||
|
|
||||||
if (size < 9 + n + 4) { // wrong size
|
n = data[8]; // header size
|
||||||
|
if (size <= 9 + n) { // wrong size
|
||||||
if (size == 9 + n) {
|
if (size == 9 + n) {
|
||||||
Warning(_("[softhddev] empty video packet\n"));
|
Warning(_("[softhddev] empty video packet\n"));
|
||||||
} else {
|
} else {
|
||||||
Error(_("[softhddev] invalid video packet %d bytes\n"), size);
|
Error(_("[softhddev] invalid video packet %d/%d bytes\n"), 9 + n,
|
||||||
|
size);
|
||||||
}
|
}
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
@ -1653,7 +1665,6 @@ int PlayVideo(const uint8_t * data, int size)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// get pts/dts
|
// get pts/dts
|
||||||
|
|
||||||
pts = AV_NOPTS_VALUE;
|
pts = AV_NOPTS_VALUE;
|
||||||
if (data[7] & 0x80) {
|
if (data[7] & 0x80) {
|
||||||
pts =
|
pts =
|
||||||
@ -1665,10 +1676,12 @@ int PlayVideo(const uint8_t * data, int size)
|
|||||||
l = size - 9 - n;
|
l = size - 9 - n;
|
||||||
z = 0;
|
z = 0;
|
||||||
while (!*check) { // count leading zeros
|
while (!*check) { // count leading zeros
|
||||||
if (--l < 2) {
|
if (l < 3) {
|
||||||
Warning(_("[softhddev] empty video packet %d bytes\n"), size);
|
Warning(_("[softhddev] empty video packet %d bytes\n"), size);
|
||||||
return size;
|
z = 0;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
--l;
|
||||||
++check;
|
++check;
|
||||||
++z;
|
++z;
|
||||||
}
|
}
|
||||||
@ -1677,7 +1690,7 @@ int PlayVideo(const uint8_t * data, int size)
|
|||||||
if ((data[6] & 0xC0) == 0x80 && z > 2 && check[0] == 0x01
|
if ((data[6] & 0xC0) == 0x80 && z > 2 && check[0] == 0x01
|
||||||
&& check[1] == 0x09) {
|
&& check[1] == 0x09) {
|
||||||
if (VideoCodecID == CODEC_ID_H264) {
|
if (VideoCodecID == CODEC_ID_H264) {
|
||||||
if (VideoTrickSpeed && pts != (int64_t) AV_NOPTS_VALUE) {
|
if (CurrentTrickSpeed && pts != (int64_t) AV_NOPTS_VALUE) {
|
||||||
// H264 NAL End of Sequence
|
// H264 NAL End of Sequence
|
||||||
static uint8_t seq_end_h264[] =
|
static uint8_t seq_end_h264[] =
|
||||||
{ 0x00, 0x00, 0x00, 0x01, 0x0A };
|
{ 0x00, 0x00, 0x00, 0x01, 0x0A };
|
||||||
@ -1716,7 +1729,6 @@ int PlayVideo(const uint8_t * data, int size)
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
// this happens when vdr sends incomplete packets
|
// this happens when vdr sends incomplete packets
|
||||||
|
|
||||||
if (VideoCodecID == CODEC_ID_NONE) {
|
if (VideoCodecID == CODEC_ID_NONE) {
|
||||||
Debug(3, "video: not detected\n");
|
Debug(3, "video: not detected\n");
|
||||||
return size;
|
return size;
|
||||||
@ -1836,7 +1848,9 @@ int SetPlayMode(int play_mode)
|
|||||||
if (MyVideoDecoder) { // tell video parser we have new stream
|
if (MyVideoDecoder) { // tell video parser we have new stream
|
||||||
if (VideoCodecID != CODEC_ID_NONE) {
|
if (VideoCodecID != CODEC_ID_NONE) {
|
||||||
NewVideoStream = 1;
|
NewVideoStream = 1;
|
||||||
|
#ifdef DEBUG
|
||||||
VideoSwitch = GetMsTicks();
|
VideoSwitch = GetMsTicks();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (MyAudioDecoder) { // tell audio parser we have new stream
|
if (MyAudioDecoder) { // tell audio parser we have new stream
|
||||||
@ -1844,14 +1858,39 @@ int SetPlayMode(int play_mode)
|
|||||||
NewAudioStream = 1;
|
NewAudioStream = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (play_mode == 2 || play_mode == 3) {
|
switch (play_mode) {
|
||||||
Debug(3, "softhddev: FIXME: audio only, silence video errors\n");
|
case 1: // audio/video from player
|
||||||
|
break;
|
||||||
|
case 2: // audio only
|
||||||
|
Debug(3, "softhddev: FIXME: audio only, silence video errors\n");
|
||||||
|
VideoSetClock(MyHwDecoder, AV_NOPTS_VALUE);
|
||||||
|
break;
|
||||||
|
case 3: // audio only, black screen
|
||||||
|
Debug(3, "softhddev: FIXME: audio only, silence video errors\n");
|
||||||
|
VideoSetClock(MyHwDecoder, AV_NOPTS_VALUE);
|
||||||
|
break;
|
||||||
|
case 4: // video only
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Play();
|
Play();
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Gets the current System Time Counter, which can be used to
|
||||||
|
** synchronize audio, video and subtitles.
|
||||||
|
*/
|
||||||
|
int64_t GetSTC(void)
|
||||||
|
{
|
||||||
|
if (MyHwDecoder) {
|
||||||
|
return VideoGetClock(MyHwDecoder);
|
||||||
|
}
|
||||||
|
Error(_("softhddev: %s called without hw decoder\n"), __FUNCTION__);
|
||||||
|
return AV_NOPTS_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Set trick play speed.
|
** Set trick play speed.
|
||||||
**
|
**
|
||||||
@ -1862,8 +1901,12 @@ int SetPlayMode(int play_mode)
|
|||||||
*/
|
*/
|
||||||
void TrickSpeed(int speed)
|
void TrickSpeed(int speed)
|
||||||
{
|
{
|
||||||
VideoTrickSpeed = speed;
|
CurrentTrickSpeed = speed;
|
||||||
VideoTrickCounter = 0;
|
if (MyHwDecoder) {
|
||||||
|
VideoSetTrickSpeed(MyHwDecoder, speed);
|
||||||
|
} else {
|
||||||
|
Error(_("softhddev: %s called without hw decoder\n"), __FUNCTION__);
|
||||||
|
}
|
||||||
StreamFreezed = 0;
|
StreamFreezed = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1892,9 +1935,7 @@ void Clear(void)
|
|||||||
*/
|
*/
|
||||||
void Play(void)
|
void Play(void)
|
||||||
{
|
{
|
||||||
VideoTrickSpeed = 0;
|
TrickSpeed(0); // normal play
|
||||||
VideoTrickCounter = 0;
|
|
||||||
StreamFreezed = 0;
|
|
||||||
SkipAudio = 0;
|
SkipAudio = 0;
|
||||||
AudioPlay();
|
AudioPlay();
|
||||||
}
|
}
|
||||||
@ -2018,6 +2059,9 @@ void StillPicture(const uint8_t * data, int size)
|
|||||||
** The dvd plugin is using this correct.
|
** The dvd plugin is using this correct.
|
||||||
**
|
**
|
||||||
** @param timeout timeout to become ready in ms
|
** @param timeout timeout to become ready in ms
|
||||||
|
**
|
||||||
|
** @retval true if ready
|
||||||
|
** @retval false if busy
|
||||||
*/
|
*/
|
||||||
int Poll(int timeout)
|
int Poll(int timeout)
|
||||||
{
|
{
|
||||||
@ -2329,7 +2373,6 @@ void SoftHdDeviceExit(void)
|
|||||||
StopVideo();
|
StopVideo();
|
||||||
|
|
||||||
CodecExit();
|
CodecExit();
|
||||||
//VideoPacketExit();
|
|
||||||
|
|
||||||
if (ConfigStartX11Server) {
|
if (ConfigStartX11Server) {
|
||||||
Debug(3, "x-setup: Stop x11 server\n");
|
Debug(3, "x-setup: Stop x11 server\n");
|
||||||
|
@ -51,6 +51,8 @@ extern "C"
|
|||||||
|
|
||||||
/// C plugin set play mode
|
/// C plugin set play mode
|
||||||
extern int SetPlayMode(int);
|
extern int SetPlayMode(int);
|
||||||
|
/// C plugin get current system time counter
|
||||||
|
extern int64_t GetSTC(void);
|
||||||
/// C plugin set trick speed
|
/// C plugin set trick speed
|
||||||
extern void TrickSpeed(int);
|
extern void TrickSpeed(int);
|
||||||
/// C plugin clears all video and audio data from the device
|
/// C plugin clears all video and audio data from the device
|
||||||
|
@ -1085,7 +1085,7 @@ int64_t cSoftHdDevice::GetSTC(void)
|
|||||||
{
|
{
|
||||||
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||||
|
|
||||||
return::VideoGetClock();
|
return::GetSTC();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
9
video.h
9
video.h
@ -146,7 +146,14 @@ extern void VideoOsdDrawARGB(int, int, int, int, const uint8_t *);
|
|||||||
/// Get OSD size.
|
/// Get OSD size.
|
||||||
extern void VideoGetOsdSize(int *, int *);
|
extern void VideoGetOsdSize(int *, int *);
|
||||||
|
|
||||||
extern int64_t VideoGetClock(void); ///< Get video clock.
|
/// Set video clock.
|
||||||
|
extern void VideoSetClock(VideoHwDecoder *, int64_t);
|
||||||
|
|
||||||
|
/// Get video clock.
|
||||||
|
extern int64_t VideoGetClock(const VideoHwDecoder *);
|
||||||
|
|
||||||
|
/// Set trick play speed.
|
||||||
|
extern void VideoSetTrickSpeed(VideoHwDecoder *, int);
|
||||||
|
|
||||||
/// Grab screen.
|
/// Grab screen.
|
||||||
extern uint8_t *VideoGrab(int *, int *, int *, int);
|
extern uint8_t *VideoGrab(int *, int *, int *, int);
|
||||||
|
Loading…
Reference in New Issue
Block a user