sdrangel/plugins/channelrx/demoddatv/datvideorender.h

248 lines
6.5 KiB
C
Raw Normal View History

2018-02-22 16:52:49 -05: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 00:39:30 -04:00
// (at your option) any later version. //
2018-02-22 16:52:49 -05: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>
#include <QWidget>
#include <QTextStream>
#include <QDebug>
2018-02-22 16:52:49 -05:00
#include "datvideostream.h"
#include "gui/tvscreen.h"
2018-02-22 16:52:49 -05: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>
#include <libavutil/opt.h>
2018-02-22 16:52:49 -05:00
#include <libavutil/samplefmt.h>
#include "libswscale/swscale.h"
}
2019-03-19 18:12:54 -04:00
class AudioFifo;
2018-02-22 16:52:49 -05:00
struct DataTSMetaData2
{
int PID;
int CodecID;
2018-02-25 19:04:45 -05:00
bool OK_Data;
bool OK_Decoding;
bool OK_TransportStream;
bool OK_VideoStream;
2018-02-22 16:52:49 -05:00
QString Program;
QString Stream;
int Width;
int Height;
int BitRate;
int Channels;
2018-02-25 19:04:45 -05:00
2018-02-22 16:52:49 -05:00
QString CodecDescription;
DataTSMetaData2()
{
reset();
}
void reset()
{
CodecID = -1;
PID = -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 16:52:49 -05:00
}
2021-03-28 12:40:43 -04:00
void formatString(QString &s)
{
QTextStream out(&s);
out << " CodecID:" << CodecID
<< " PID:" << PID
<< " Program:" << Program
<< " Stream:" << Stream
<< " Width:" << Width
<< " Height:" << Height
<< " BitRate:" << BitRate
<< " Channels:" << Channels
<< " CodecDescription:" << CodecDescription;
}
2018-02-22 16:52:49 -05:00
};
2018-03-11 11:39:02 -04:00
class DATVideoRender : public TVScreen
2018-02-22 16:52:49 -05:00
{
Q_OBJECT
2018-02-25 19:04:45 -05:00
public:
explicit DATVideoRender(QWidget *parent);
2019-03-22 03:05:01 -04:00
~DATVideoRender();
2021-04-05 07:13:57 -04:00
void setFullScreen(bool blnFullScreen);
2018-02-22 16:52:49 -05:00
2021-03-28 12:40:43 -04:00
void setAudioFIFO(AudioFifo *fifo) { m_audioFifo = fifo; }
2021-04-05 07:13:57 -04:00
bool openStream(DATVideostream *objDevice);
bool renderStream();
bool closeStream(QIODevice *objDevice);
2018-02-22 16:52:49 -05:00
2019-03-19 19:07:05 -04:00
int getVideoStreamIndex() const { return m_videoStreamIndex; }
2019-03-19 18:12:54 -04:00
int getAudioStreamIndex() const { return m_audioStreamIndex; }
2019-03-22 03:05:01 -04:00
void setAudioMute(bool audioMute) { m_audioMute = audioMute; }
void setVideoMute(bool videoMute) { m_videoMute = videoMute; }
2019-03-22 03:05:01 -04:00
void setAudioVolume(int audioVolume);
bool getAudioDecodeOK() const { return m_audioDecodeOK; }
bool getVideoDecodeOK() const { return m_videoDecodeOK; }
private:
struct DataTSMetaData2 m_metaData;
QWidget *m_parentWidget;
Qt::WindowFlags m_originalWindowFlags;
QSize m_originalSize;
bool m_isFullScreen;
bool m_isOpen;
SwsContext *m_swsCtx;
2019-03-19 19:07:05 -04:00
AVFormatContext *m_formatCtx;
AVCodecContext *m_videoDecoderCtx;
AVCodecContext *m_audioDecoderCtx;
AVFrame *m_frame;
2019-03-19 18:12:54 -04:00
AudioFifo *m_audioFifo;
struct SwrContext* m_audioSWR;
int m_audioSampleRate;
2019-03-21 03:35:29 -04:00
static const int m_audioFifoBufferSize = 16000;
int16_t m_audioFifoBuffer[m_audioFifoBufferSize*2]; // 2 channels
2019-03-21 03:35:29 -04:00
int m_audioFifoBufferIndex;
2019-03-22 03:05:01 -04:00
bool m_audioMute;
bool m_videoMute;
float m_audioVolume;
2019-03-19 18:12:54 -04:00
2021-04-05 07:13:57 -04:00
uint8_t *m_decodedData[4];
int m_decodedLineSize[4];
2018-02-22 16:52:49 -05:00
2019-03-19 19:07:05 -04:00
int m_frameCount;
int m_videoStreamIndex;
2019-03-19 18:12:54 -04:00
int m_audioStreamIndex;
2018-02-22 16:52:49 -05:00
int m_currentRenderWidth;
int m_currentRenderHeight;
2018-02-22 16:52:49 -05:00
bool m_audioDecodeOK;
bool m_videoDecodeOK;
2021-04-05 07:13:57 -04:00
static int ReadFunction(void *opaque, uint8_t *buf, int buf_size);
static int64_t SeekFunction(void *opaque, int64_t offset, int whence);
bool preprocessStream();
void resetMetaData();
2018-02-22 16:52:49 -05:00
2021-04-05 07:13:57 -04:00
int newDecode(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *pkt);
2019-03-22 03:05:01 -04:00
void setResampler();
protected:
2018-02-22 16:52:49 -05:00
virtual bool eventFilter(QObject *obj, QEvent *event);
signals:
void onMetaDataChanged(DataTSMetaData2 *metaData);
2018-02-22 16:52:49 -05:00
};
2018-02-25 19:04:45 -05:00
//To run Video Rendering with a dedicated thread
class DATVideoRenderThread : public QThread
2018-02-22 16:52:49 -05:00
{
public:
DATVideoRenderThread()
{
m_renderer = nullptr;
m_stream = nullptr;
m_renderingVideo = false;
}
2018-02-22 16:52:49 -05:00
DATVideoRenderThread(DATVideoRender *renderer, DATVideostream *stream)
{
m_renderer = renderer;
m_stream = stream;
m_renderingVideo = false;
}
void setStreamAndRenderer(DATVideoRender *renderer, DATVideostream *stream)
{
m_renderingVideo = false;
m_renderer = renderer;
m_stream = stream;
}
2018-02-22 16:52:49 -05:00
void run()
{
if (m_renderingVideo) {
return;
2018-02-22 16:52:49 -05:00
}
if ((m_renderer == nullptr) || (m_stream == nullptr)) {
return;
}
2018-02-22 16:52:49 -05:00
2021-04-05 07:13:57 -04:00
m_renderingVideo = m_renderer->openStream(m_stream);
2018-02-22 16:52:49 -05:00
if (!m_renderingVideo) {
return;
2018-02-22 16:52:49 -05:00
}
while ((m_renderingVideo == true) && (m_renderer))
2018-02-22 16:52:49 -05:00
{
2021-04-05 07:13:57 -04:00
if (!m_renderer->renderStream()) {
break;
}
2018-02-22 16:52:49 -05:00
}
2021-04-05 07:13:57 -04:00
m_renderer->closeStream(m_stream);
m_renderingVideo = false;
}
void stopRendering() {
m_renderingVideo = false;
}
2018-02-22 16:52:49 -05:00
static const int videoThreadTimeoutMs = 1000;
2021-03-28 12:40:43 -04:00
private:
DATVideoRender *m_renderer;
DATVideostream *m_stream;
bool m_renderingVideo;
2018-02-22 16:52:49 -05:00
};
#endif // DATVIDEORENDER_H