mirror of
				https://projects.vdr-developer.org/git/vdr-plugin-softhddevice.git
				synced 2023-10-10 17:16:51 +00:00 
			
		
		
		
	Crash and thread fixes.
Check if PTS is valid, otherwise debug code does false abort. Fix bug: audio new stream is not thread safe.
This commit is contained in:
		
							
								
								
									
										117
									
								
								softhddev.c
									
									
									
									
									
								
							
							
						
						
									
										117
									
								
								softhddev.c
									
									
									
									
									
								
							@@ -54,6 +54,7 @@ static char ConfigVdpauDecoder = 1;	///< use vdpau decoder, if possible
 | 
				
			|||||||
//	Audio
 | 
					//	Audio
 | 
				
			||||||
//////////////////////////////////////////////////////////////////////////////
 | 
					//////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static volatile char NewAudioStream;	///< new audio stream
 | 
				
			||||||
static AudioDecoder *MyAudioDecoder;	///< audio decoder
 | 
					static AudioDecoder *MyAudioDecoder;	///< audio decoder
 | 
				
			||||||
static enum CodecID AudioCodecID;	///< current codec id
 | 
					static enum CodecID AudioCodecID;	///< current codec id
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -192,6 +193,12 @@ void PlayAudio(const uint8_t * data, int size, uint8_t id)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    // channel switch: SetAudioChannelDevice: SetDigitalAudioDevice:
 | 
					    // channel switch: SetAudioChannelDevice: SetDigitalAudioDevice:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (NewAudioStream) {
 | 
				
			||||||
 | 
						// FIXME: does this clear the audio ringbuffer?
 | 
				
			||||||
 | 
						CodecAudioClose(MyAudioDecoder);
 | 
				
			||||||
 | 
						AudioCodecID = CODEC_ID_NONE;
 | 
				
			||||||
 | 
						NewAudioStream = 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    // PES header 0x00 0x00 0x01 ID
 | 
					    // PES header 0x00 0x00 0x01 ID
 | 
				
			||||||
    // ID 0xBD 0xC0-0xCF
 | 
					    // ID 0xBD 0xC0-0xCF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -318,13 +325,13 @@ void SetVolumeDevice(int volume)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <alsa/iatomic.h>		// portable atomic_t
 | 
					#include <alsa/iatomic.h>		// portable atomic_t
 | 
				
			||||||
 | 
					
 | 
				
			||||||
uint32_t VideoSwitch;
 | 
					uint32_t VideoSwitch;			///< debug video switch ticks
 | 
				
			||||||
static int NewVideoStream;		///< new video stream
 | 
					static volatile char NewVideoStream;	///< new video stream
 | 
				
			||||||
static VideoDecoder *MyVideoDecoder;	///< video decoder
 | 
					static VideoDecoder *MyVideoDecoder;	///< video decoder
 | 
				
			||||||
static enum CodecID VideoCodecID;	///< current codec id
 | 
					static enum CodecID VideoCodecID;	///< current codec id
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const char *X11DisplayName;	///< x11 display name
 | 
					static const char *X11DisplayName;	///< x11 display name
 | 
				
			||||||
static volatile int Usr1Signal;		///< true got usr1 signal
 | 
					static volatile char Usr1Signal;	///< true got usr1 signal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// video PES buffer default size
 | 
					    /// video PES buffer default size
 | 
				
			||||||
#define VIDEO_BUFFER_SIZE (512 * 1024)
 | 
					#define VIDEO_BUFFER_SIZE (512 * 1024)
 | 
				
			||||||
@@ -334,8 +341,8 @@ static AVPacket VideoPacketRb[VIDEO_PACKET_MAX];
 | 
				
			|||||||
static int VideoPacketWrite;		///< write pointer
 | 
					static int VideoPacketWrite;		///< write pointer
 | 
				
			||||||
static int VideoPacketRead;		///< read pointer
 | 
					static int VideoPacketRead;		///< read pointer
 | 
				
			||||||
static atomic_t VideoPacketsFilled;	///< how many of the buffer is used
 | 
					static atomic_t VideoPacketsFilled;	///< how many of the buffer is used
 | 
				
			||||||
static char VideoFreezed;		///< video freezed
 | 
					static volatile char VideoFreezed;	///< video freezed
 | 
				
			||||||
static char VideoClearBuffers;		///< clear video buffers
 | 
					static volatile char VideoClearBuffers;	///< clear video buffers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef DEBUG
 | 
					#ifdef DEBUG
 | 
				
			||||||
static int VideoMaxPacketSize;		///< biggest used packet buffer
 | 
					static int VideoMaxPacketSize;		///< biggest used packet buffer
 | 
				
			||||||
@@ -411,6 +418,9 @@ static void VideoEnqueue(int64_t pts, const void *data, int size)
 | 
				
			|||||||
		/ (VIDEO_BUFFER_SIZE / 2)) * (VIDEO_BUFFER_SIZE / 2));
 | 
							/ (VIDEO_BUFFER_SIZE / 2)) * (VIDEO_BUFFER_SIZE / 2));
 | 
				
			||||||
#ifdef DEBUG
 | 
					#ifdef DEBUG
 | 
				
			||||||
	if (avpkt->size <= avpkt->stream_index + size) {
 | 
						if (avpkt->size <= avpkt->stream_index + size) {
 | 
				
			||||||
 | 
						    fprintf(stderr, "%d %d %d\n", avpkt->size, avpkt->stream_index,
 | 
				
			||||||
 | 
							size);
 | 
				
			||||||
 | 
						    fflush(stderr);
 | 
				
			||||||
	    abort();
 | 
						    abort();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@@ -510,6 +520,7 @@ int VideoDecode(void)
 | 
				
			|||||||
		CodecVideoClose(MyVideoDecoder);
 | 
							CodecVideoClose(MyVideoDecoder);
 | 
				
			||||||
		goto skip;
 | 
							goto skip;
 | 
				
			||||||
	    }
 | 
						    }
 | 
				
			||||||
 | 
						    goto skip;
 | 
				
			||||||
	    break;
 | 
						    break;
 | 
				
			||||||
	case CODEC_ID_MPEG2VIDEO:
 | 
						case CODEC_ID_MPEG2VIDEO:
 | 
				
			||||||
	    if (last_codec_id != CODEC_ID_MPEG2VIDEO) {
 | 
						    if (last_codec_id != CODEC_ID_MPEG2VIDEO) {
 | 
				
			||||||
@@ -568,6 +579,44 @@ static void StartVideo(void)
 | 
				
			|||||||
    VideoPacketInit();
 | 
					    VideoPacketInit();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef DEBUG
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					**	Validate mpeg video packet.
 | 
				
			||||||
 | 
					**
 | 
				
			||||||
 | 
					**	Function to validate a mpeg packet, not needed.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					static int ValidateMpeg(const uint8_t * data, int size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int pes_l;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    do {
 | 
				
			||||||
 | 
						if (size < 9) {
 | 
				
			||||||
 | 
						    return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (data[0] || data[1] || data[2] != 0x01) {
 | 
				
			||||||
 | 
						    printf("%02x: %02x %02x %02x %02x %02x\n", data[-1], data[0],
 | 
				
			||||||
 | 
							data[1], data[2], data[3], data[4]);
 | 
				
			||||||
 | 
						    return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pes_l = (data[4] << 8) | data[5];
 | 
				
			||||||
 | 
						if (!pes_l) {			// contains unknown length
 | 
				
			||||||
 | 
						    return 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (6 + pes_l > size) {
 | 
				
			||||||
 | 
						    return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						data += 6 + pes_l;
 | 
				
			||||||
 | 
						size -= 6 + pes_l;
 | 
				
			||||||
 | 
					    } while (size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
**	Play video packet.
 | 
					**	Play video packet.
 | 
				
			||||||
**
 | 
					**
 | 
				
			||||||
@@ -597,7 +646,7 @@ int PlayVideo(const uint8_t * data, int size)
 | 
				
			|||||||
    if (!MyVideoDecoder) {		// no x11 video started
 | 
					    if (!MyVideoDecoder) {		// no x11 video started
 | 
				
			||||||
	return size;
 | 
						return size;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (NewVideoStream) {
 | 
					    if (NewVideoStream) {		// channel switched
 | 
				
			||||||
	Debug(3, "video: new stream %d\n", GetMsTicks() - VideoSwitch);
 | 
						Debug(3, "video: new stream %d\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) {
 | 
				
			||||||
@@ -616,13 +665,15 @@ int PlayVideo(const uint8_t * data, int size)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    n = data[8];			// header size
 | 
					    n = data[8];			// header size
 | 
				
			||||||
    // wrong size
 | 
					    // wrong size
 | 
				
			||||||
    if (size < 9 + n) {
 | 
					    if (size < 9 + n + 4) {
 | 
				
			||||||
	Error(_("[softhddev] invalid video packet\n"));
 | 
						Error(_("[softhddev] invalid video packet\n"));
 | 
				
			||||||
	return size;
 | 
						return size;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    check = data + 9 + n;
 | 
					    // FIXME: hack to test results
 | 
				
			||||||
 | 
					    if (atomic_read(&VideoPacketsFilled) >= VIDEO_PACKET_MAX - 1) {
 | 
				
			||||||
    // FIXME: get pts/dts, when we need it
 | 
						return 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // get pts/dts
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pts = AV_NOPTS_VALUE;
 | 
					    pts = AV_NOPTS_VALUE;
 | 
				
			||||||
    if (data[7] & 0x80) {
 | 
					    if (data[7] & 0x80) {
 | 
				
			||||||
@@ -630,6 +681,10 @@ int PlayVideo(const uint8_t * data, int size)
 | 
				
			|||||||
	    (int64_t) (data[9] & 0x0E) << 29 | data[10] << 22 | (data[11] &
 | 
						    (int64_t) (data[9] & 0x0E) << 29 | data[10] << 22 | (data[11] &
 | 
				
			||||||
	    0xFE) << 14 | data[12] << 7 | (data[13] & 0xFE) >> 1;
 | 
						    0xFE) << 14 | data[12] << 7 | (data[13] & 0xFE) >> 1;
 | 
				
			||||||
#ifdef DEBUG
 | 
					#ifdef DEBUG
 | 
				
			||||||
 | 
						if (!(data[13] & 1) || !(data[11] & 1) || !(data[9] & 1)) {
 | 
				
			||||||
 | 
						    Error(_("[softhddev] invalid pts in video packet\n"));
 | 
				
			||||||
 | 
						    return size;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	//Debug(3, "video: pts %#012" PRIx64 "\n", pts);
 | 
						//Debug(3, "video: pts %#012" PRIx64 "\n", pts);
 | 
				
			||||||
	if (data[13] != (((pts & 0x7F) << 1) | 1)) {
 | 
						if (data[13] != (((pts & 0x7F) << 1) | 1)) {
 | 
				
			||||||
	    abort();
 | 
						    abort();
 | 
				
			||||||
@@ -643,35 +698,36 @@ int PlayVideo(const uint8_t * data, int size)
 | 
				
			|||||||
	if (data[10] != ((pts >> 22) & 0xFF)) {
 | 
						if (data[10] != ((pts >> 22) & 0xFF)) {
 | 
				
			||||||
	    abort();
 | 
						    abort();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if ((data[9] & 0x0F) != (((pts >> 30) << 1) | 1)) {
 | 
				
			||||||
 | 
						    abort();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // FIXME: no valid mpeg2/h264 detection yet
 | 
					    // FIXME: no valid mpeg2/h264 detection yet
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    check = data + 9 + n;
 | 
				
			||||||
    if (0) {
 | 
					    if (0) {
 | 
				
			||||||
	printf("%02x: %02x %02x %02x %02x %02x\n", data[6], check[0], check[1],
 | 
						printf("%02x: %02x %02x %02x %02x %02x\n", data[6], check[0], check[1],
 | 
				
			||||||
	    check[2], check[3], check[4]);
 | 
						    check[2], check[3], check[4]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // PES_VIDEO_STREAM 0xE0 or PES start code
 | 
					    // PES_VIDEO_STREAM 0xE0 or PES start code
 | 
				
			||||||
    if ((data[6] & 0xC0) != 0x80 || (!check[0] && !check[1]
 | 
					    //(data[6] & 0xC0) != 0x80 ||
 | 
				
			||||||
	    && check[2] == 0x1)) {
 | 
					    if ((!check[0] && !check[1] && check[2] == 0x1)) {
 | 
				
			||||||
	if (VideoCodecID == CODEC_ID_MPEG2VIDEO) {
 | 
						if (VideoCodecID == CODEC_ID_MPEG2VIDEO) {
 | 
				
			||||||
	    // FIXME: hack to test results
 | 
					 | 
				
			||||||
	    if (atomic_read(&VideoPacketsFilled) >= VIDEO_PACKET_MAX - 1) {
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
	    }
 | 
					 | 
				
			||||||
	    VideoNextPacket(CODEC_ID_MPEG2VIDEO);
 | 
						    VideoNextPacket(CODEC_ID_MPEG2VIDEO);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
	    Debug(3, "video: mpeg2 detected\n");
 | 
						    Debug(3, "video: mpeg2 detected ID %02x\n", check[3]);
 | 
				
			||||||
	    VideoCodecID = CODEC_ID_MPEG2VIDEO;
 | 
						    VideoCodecID = CODEC_ID_MPEG2VIDEO;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// Access Unit Delimiter
 | 
					#ifdef DEBUG
 | 
				
			||||||
    } else if (!check[0] && !check[1] && !check[2] && check[3] == 0x1
 | 
						if (ValidateMpeg(data, size)) {
 | 
				
			||||||
	&& check[4] == 0x09) {
 | 
						    Debug(3, "softhddev/video: invalid mpeg2 video packet\n");
 | 
				
			||||||
	if (VideoCodecID == CODEC_ID_H264) {
 | 
					 | 
				
			||||||
	    // FIXME: hack to test results
 | 
					 | 
				
			||||||
	    if (atomic_read(&VideoPacketsFilled) >= VIDEO_PACKET_MAX - 1) {
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
						// Access Unit Delimiter
 | 
				
			||||||
 | 
					    } else if ((data[6] & 0xC0) == 0x80 && !check[0] && !check[1]
 | 
				
			||||||
 | 
						&& !check[2] && check[3] == 0x1 && check[4] == 0x09) {
 | 
				
			||||||
 | 
						if (VideoCodecID == CODEC_ID_H264) {
 | 
				
			||||||
	    VideoNextPacket(CODEC_ID_H264);
 | 
						    VideoNextPacket(CODEC_ID_H264);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
	    Debug(3, "video: h264 detected\n");
 | 
						    Debug(3, "video: h264 detected\n");
 | 
				
			||||||
@@ -684,11 +740,8 @@ int PlayVideo(const uint8_t * data, int size)
 | 
				
			|||||||
	    return size;
 | 
						    return size;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (VideoCodecID == CODEC_ID_MPEG2VIDEO) {
 | 
						if (VideoCodecID == CODEC_ID_MPEG2VIDEO) {
 | 
				
			||||||
	    // mpeg codec supports incomplete packages
 | 
						    // mpeg codec supports incomplete packets
 | 
				
			||||||
	    // FIXME: hack to test results
 | 
						    // waiting for a full complete packages, increases needed delays
 | 
				
			||||||
	    if (atomic_read(&VideoPacketsFilled) >= VIDEO_PACKET_MAX - 1) {
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
	    }
 | 
					 | 
				
			||||||
	    VideoNextPacket(CODEC_ID_MPEG2VIDEO);
 | 
						    VideoNextPacket(CODEC_ID_MPEG2VIDEO);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -716,9 +769,7 @@ void SetPlayMode(void)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (MyAudioDecoder) {
 | 
					    if (MyAudioDecoder) {
 | 
				
			||||||
	// FIXME: does this clear the audio ringbuffer?
 | 
						NewAudioStream = 1;
 | 
				
			||||||
	CodecAudioClose(MyAudioDecoder);
 | 
					 | 
				
			||||||
	AudioCodecID = CODEC_ID_NONE;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1015,10 +1066,12 @@ void Stop(void)
 | 
				
			|||||||
    // no it doesn't do a good thread cleanup
 | 
					    // no it doesn't do a good thread cleanup
 | 
				
			||||||
    if (MyVideoDecoder) {
 | 
					    if (MyVideoDecoder) {
 | 
				
			||||||
	CodecVideoClose(MyVideoDecoder);
 | 
						CodecVideoClose(MyVideoDecoder);
 | 
				
			||||||
 | 
						// FIXME: CodecDelVideoDecoder(MyVideoDecoder);
 | 
				
			||||||
	MyVideoDecoder = NULL;
 | 
						MyVideoDecoder = NULL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (MyAudioDecoder) {
 | 
					    if (MyAudioDecoder) {
 | 
				
			||||||
	CodecAudioClose(MyAudioDecoder);
 | 
						CodecAudioClose(MyAudioDecoder);
 | 
				
			||||||
 | 
						// FIXME: CodecDelAudioDecoder(MyAudioDecoder);
 | 
				
			||||||
	MyAudioDecoder = NULL;
 | 
						MyAudioDecoder = NULL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user