| 
									
										
										
										
											2018-02-22 21:52:49 +00:00
										 |  |  | ///////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | // Copyright (C) 2018 F4HKW                                                      //
 | 
					
						
							|  |  |  | // for F4EXB / SDRAngel                                                          //
 | 
					
						
							|  |  |  | //                                                                               //
 | 
					
						
							|  |  |  | // This program is free software; you can redistribute it and/or modify          //
 | 
					
						
							|  |  |  | // it under the terms of the GNU General Public License as published by          //
 | 
					
						
							|  |  |  | // the Free Software Foundation as version 3 of the License, or                  //
 | 
					
						
							| 
									
										
										
										
											2019-04-11 04:39:30 +00:00
										 |  |  | // (at your option) any later version.                                           //
 | 
					
						
							| 
									
										
										
										
											2018-02-22 21:52:49 +00:00
										 |  |  | //                                                                               //
 | 
					
						
							|  |  |  | // This program is distributed in the hope that it will be useful,               //
 | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of                //
 | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the                  //
 | 
					
						
							|  |  |  | // GNU General Public License V3 for more details.                               //
 | 
					
						
							|  |  |  | //                                                                               //
 | 
					
						
							|  |  |  | // You should have received a copy of the GNU General Public License             //
 | 
					
						
							|  |  |  | // along with this program. If not, see <http://www.gnu.org/licenses/>.          //
 | 
					
						
							|  |  |  | ///////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef DATVIDEORENDER_H
 | 
					
						
							|  |  |  | #define DATVIDEORENDER_H
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <QEvent>
 | 
					
						
							|  |  |  | #include <QIODevice>
 | 
					
						
							|  |  |  | #include <QThread>
 | 
					
						
							| 
									
										
										
										
											2019-03-20 00:14:38 +00:00
										 |  |  | #include <QWidget>
 | 
					
						
							| 
									
										
										
										
											2018-02-22 21:52:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "datvideostream.h"
 | 
					
						
							| 
									
										
										
										
											2019-03-20 00:14:38 +00:00
										 |  |  | #include "gui/tvscreen.h"
 | 
					
						
							| 
									
										
										
										
											2018-02-22 21:52:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | extern "C" | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #include "libavcodec/avcodec.h"
 | 
					
						
							|  |  |  | #include "libavformat/avformat.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <libavutil/channel_layout.h>
 | 
					
						
							|  |  |  | #include <libavutil/common.h>
 | 
					
						
							|  |  |  | #include <libavutil/imgutils.h>
 | 
					
						
							|  |  |  | #include <libavutil/mathematics.h>
 | 
					
						
							| 
									
										
										
										
											2019-03-20 00:14:38 +00:00
										 |  |  | #include <libavutil/opt.h>
 | 
					
						
							| 
									
										
										
										
											2018-02-22 21:52:49 +00:00
										 |  |  | #include <libavutil/samplefmt.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "libswscale/swscale.h"
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-19 22:12:54 +00:00
										 |  |  | class AudioFifo; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-22 21:52:49 +00:00
										 |  |  | struct DataTSMetaData2 | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int PID; | 
					
						
							|  |  |  |     int CodecID; | 
					
						
							| 
									
										
										
										
											2018-02-26 00:04:45 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     bool OK_Data; | 
					
						
							|  |  |  |     bool OK_Decoding; | 
					
						
							|  |  |  |     bool OK_TransportStream; | 
					
						
							|  |  |  |     bool OK_VideoStream; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-22 21:52:49 +00:00
										 |  |  |     QString Program; | 
					
						
							|  |  |  |     QString Stream; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int Width; | 
					
						
							|  |  |  |     int Height; | 
					
						
							|  |  |  |     int BitRate; | 
					
						
							|  |  |  |     int Channels; | 
					
						
							| 
									
										
										
										
											2018-02-26 00:04:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-22 21:52:49 +00:00
										 |  |  |     QString CodecDescription; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     DataTSMetaData2() | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2019-03-20 00:14:38 +00:00
										 |  |  |         PID = -1; | 
					
						
							|  |  |  |         CodecID = -1; | 
					
						
							|  |  |  |         Program = ""; | 
					
						
							|  |  |  |         Stream = ""; | 
					
						
							|  |  |  |         Width = -1; | 
					
						
							|  |  |  |         Height = -1; | 
					
						
							|  |  |  |         BitRate = -1; | 
					
						
							|  |  |  |         Channels = -1; | 
					
						
							|  |  |  |         CodecDescription = ""; | 
					
						
							|  |  |  |         OK_Data = false; | 
					
						
							|  |  |  |         OK_Decoding = false; | 
					
						
							|  |  |  |         OK_TransportStream = false; | 
					
						
							|  |  |  |         OK_VideoStream = false; | 
					
						
							| 
									
										
										
										
											2018-02-22 21:52:49 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-11 15:39:02 +00:00
										 |  |  | class DATVideoRender : public TVScreen | 
					
						
							| 
									
										
										
										
											2018-02-22 21:52:49 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     Q_OBJECT | 
					
						
							| 
									
										
										
										
											2018-02-26 00:04:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-20 00:14:38 +00:00
										 |  |  |   public: | 
					
						
							|  |  |  |     explicit DATVideoRender(QWidget *parent); | 
					
						
							| 
									
										
										
										
											2019-03-22 07:05:01 +00:00
										 |  |  |     ~DATVideoRender(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-22 21:52:49 +00:00
										 |  |  |     void SetFullScreen(bool blnFullScreen); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bool OpenStream(DATVideostream *objDevice); | 
					
						
							|  |  |  |     bool RenderStream(); | 
					
						
							|  |  |  |     bool CloseStream(QIODevice *objDevice); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-19 22:12:54 +00:00
										 |  |  |     void setAudioFIFO(AudioFifo *fifo) { m_audioFifo = fifo; } | 
					
						
							| 
									
										
										
										
											2019-03-19 23:07:05 +00:00
										 |  |  |     int getVideoStreamIndex() const { return m_videoStreamIndex; } | 
					
						
							| 
									
										
										
										
											2019-03-19 22:12:54 +00:00
										 |  |  |     int getAudioStreamIndex() const { return m_audioStreamIndex; } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-22 07:05:01 +00:00
										 |  |  |     void setAudioMute(bool audioMute) { m_audioMute = audioMute; } | 
					
						
							| 
									
										
										
										
											2019-03-23 05:06:42 +00:00
										 |  |  |     void setVideoMute(bool videoMute) { m_videoMute = videoMute; } | 
					
						
							| 
									
										
										
										
											2019-03-22 07:05:01 +00:00
										 |  |  |     void setAudioVolume(int audioVolume); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-23 08:38:29 +00:00
										 |  |  |     bool getAudioDecodeOK() const { return m_audioDecodeOK; } | 
					
						
							|  |  |  |     bool getVideoDecodeOK() const { return m_videoDecodeOK; } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-22 21:52:49 +00:00
										 |  |  |     struct DataTSMetaData2 MetaData; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-20 00:14:38 +00:00
										 |  |  |   private: | 
					
						
							| 
									
										
										
										
											2019-03-23 22:37:26 +00:00
										 |  |  |     QWidget *m_parentWidget; | 
					
						
							|  |  |  |     Qt::WindowFlags m_originalWindowFlags; | 
					
						
							|  |  |  |     QSize m_originalSize; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-20 00:14:38 +00:00
										 |  |  |     bool m_running; | 
					
						
							|  |  |  |     bool m_isFullScreen; | 
					
						
							| 
									
										
										
										
											2018-02-22 21:52:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-20 00:14:38 +00:00
										 |  |  |     bool m_isFFMPEGInitialized; | 
					
						
							|  |  |  |     bool m_isOpen; | 
					
						
							| 
									
										
										
										
											2018-02-22 21:52:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-20 00:14:38 +00:00
										 |  |  |     SwsContext *m_swsCtx; | 
					
						
							| 
									
										
										
										
											2019-03-19 23:07:05 +00:00
										 |  |  |     AVFormatContext *m_formatCtx; | 
					
						
							|  |  |  |     AVCodecContext *m_videoDecoderCtx; | 
					
						
							|  |  |  |     AVCodecContext *m_audioDecoderCtx; | 
					
						
							|  |  |  |     AVFrame *m_frame; | 
					
						
							| 
									
										
										
										
											2019-03-19 22:12:54 +00:00
										 |  |  |     AudioFifo *m_audioFifo; | 
					
						
							| 
									
										
										
										
											2019-03-20 01:15:59 +00:00
										 |  |  |     struct SwrContext* m_audioSWR; | 
					
						
							|  |  |  |     int m_audioSampleRate; | 
					
						
							| 
									
										
										
										
											2019-03-21 07:35:29 +00:00
										 |  |  |     static const int m_audioFifoBufferSize = 16000; | 
					
						
							| 
									
										
										
										
											2019-03-23 05:06:42 +00:00
										 |  |  |     int16_t m_audioFifoBuffer[m_audioFifoBufferSize*2]; // 2 channels
 | 
					
						
							| 
									
										
										
										
											2019-03-21 07:35:29 +00:00
										 |  |  |     int m_audioFifoBufferIndex; | 
					
						
							| 
									
										
										
										
											2019-03-22 07:05:01 +00:00
										 |  |  |     bool m_audioMute; | 
					
						
							| 
									
										
										
										
											2019-03-23 05:06:42 +00:00
										 |  |  |     bool m_videoMute; | 
					
						
							|  |  |  |     float m_audioVolume; | 
					
						
							| 
									
										
										
										
											2019-03-22 07:05:01 +00:00
										 |  |  |     bool m_updateAudioResampler; | 
					
						
							| 
									
										
										
										
											2019-03-19 22:12:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-22 21:52:49 +00:00
										 |  |  |     uint8_t *m_pbytDecodedData[4]; | 
					
						
							|  |  |  |     int m_pintDecodedLineSize[4]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-19 23:07:05 +00:00
										 |  |  |     int m_frameCount; | 
					
						
							|  |  |  |     int m_videoStreamIndex; | 
					
						
							| 
									
										
										
										
											2019-03-19 22:12:54 +00:00
										 |  |  |     int m_audioStreamIndex; | 
					
						
							| 
									
										
										
										
											2018-02-22 21:52:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-20 00:14:38 +00:00
										 |  |  |     int m_currentRenderWidth; | 
					
						
							|  |  |  |     int m_currentRenderHeight; | 
					
						
							| 
									
										
										
										
											2018-02-22 21:52:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-23 08:38:29 +00:00
										 |  |  |     bool m_audioDecodeOK; | 
					
						
							|  |  |  |     bool m_videoDecodeOK; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-22 21:52:49 +00:00
										 |  |  |     bool InitializeFFMPEG(); | 
					
						
							|  |  |  |     bool PreprocessStream(); | 
					
						
							| 
									
										
										
										
											2018-02-26 00:04:45 +00:00
										 |  |  |     void ResetMetaData(); | 
					
						
							| 
									
										
										
										
											2018-02-22 21:52:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-12 22:20:51 +00:00
										 |  |  |     int new_decode(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *pkt); | 
					
						
							| 
									
										
										
										
											2019-03-22 07:05:01 +00:00
										 |  |  |     void setResampler(); | 
					
						
							| 
									
										
										
										
											2018-06-12 22:20:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-20 00:14:38 +00:00
										 |  |  |   protected: | 
					
						
							| 
									
										
										
										
											2018-02-22 21:52:49 +00:00
										 |  |  |     virtual bool eventFilter(QObject *obj, QEvent *event); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-20 00:14:38 +00:00
										 |  |  |   signals: | 
					
						
							|  |  |  |     void onMetaDataChanged(DataTSMetaData2 *metaData); | 
					
						
							| 
									
										
										
										
											2018-02-22 21:52:49 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-26 00:04:45 +00:00
										 |  |  | //To run Video Rendering with a dedicated thread
 | 
					
						
							| 
									
										
										
										
											2019-03-20 00:14:38 +00:00
										 |  |  | class DATVideoRenderThread : public QThread | 
					
						
							| 
									
										
										
										
											2018-02-22 21:52:49 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-03-20 00:14:38 +00:00
										 |  |  |   public: | 
					
						
							|  |  |  |     DATVideoRenderThread() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         m_renderer = nullptr; | 
					
						
							|  |  |  |         m_stream = nullptr; | 
					
						
							|  |  |  |         m_renderingVideo = false; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-02-22 21:52:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-20 00:14:38 +00:00
										 |  |  |     DATVideoRenderThread(DATVideoRender *renderer, DATVideostream *stream) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         m_renderer = renderer; | 
					
						
							|  |  |  |         m_stream = stream; | 
					
						
							|  |  |  |         m_renderingVideo = false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void setStreamAndRenderer(DATVideoRender *renderer, DATVideostream *stream) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         m_renderer = renderer; | 
					
						
							|  |  |  |         m_stream = stream; | 
					
						
							|  |  |  |         m_renderingVideo = false; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-02-22 21:52:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-20 00:14:38 +00:00
										 |  |  |     void run() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (m_renderingVideo) | 
					
						
							| 
									
										
										
										
											2018-02-22 21:52:49 +00:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2019-03-20 00:14:38 +00:00
										 |  |  |             return; | 
					
						
							| 
									
										
										
										
											2018-02-22 21:52:49 +00:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-20 00:14:38 +00:00
										 |  |  |         if ((m_renderer == nullptr) || (m_stream == nullptr)) | 
					
						
							| 
									
										
										
										
											2018-02-22 21:52:49 +00:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2019-03-20 00:14:38 +00:00
										 |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-02-22 21:52:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-20 00:14:38 +00:00
										 |  |  |         m_renderingVideo = m_renderer->OpenStream(m_stream); | 
					
						
							| 
									
										
										
										
											2018-02-22 21:52:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-20 00:14:38 +00:00
										 |  |  |         if (!m_renderingVideo) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             return; | 
					
						
							| 
									
										
										
										
											2018-02-22 21:52:49 +00:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-20 00:14:38 +00:00
										 |  |  |         while ((m_renderer->RenderStream()) && (m_renderingVideo == true)) | 
					
						
							| 
									
										
										
										
											2018-02-22 21:52:49 +00:00
										 |  |  |         { | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-20 00:14:38 +00:00
										 |  |  |         m_renderer->CloseStream(m_stream); | 
					
						
							|  |  |  |         m_renderingVideo = false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void stopRendering() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         m_renderingVideo = false; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-02-22 21:52:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-20 00:14:38 +00:00
										 |  |  |   private: | 
					
						
							|  |  |  |     DATVideoRender *m_renderer; | 
					
						
							|  |  |  |     DATVideostream *m_stream; | 
					
						
							|  |  |  |     bool m_renderingVideo; | 
					
						
							| 
									
										
										
										
											2018-02-22 21:52:49 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif // DATVIDEORENDER_H
 |