|
|
|
|
|
#ifndef _TS_DECODER_H_
|
|
|
|
|
|
#define _TS_DECODER_H_
|
|
|
|
|
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
|
|
#include <string>
|
|
|
|
|
|
#include <thread>
|
|
|
|
|
|
#include <QThread>
|
|
|
|
|
|
#include <QString>
|
|
|
|
|
|
#include "opencv2/opencv.hpp"
|
|
|
|
|
|
extern "C"
|
|
|
|
|
|
{
|
|
|
|
|
|
#include "libavcodec/avcodec.h"
|
|
|
|
|
|
#include "libavformat/avformat.h"
|
|
|
|
|
|
#include "libavdevice/avdevice.h"
|
|
|
|
|
|
#include "libswscale/swscale.h"
|
|
|
|
|
|
#include "libavutil/imgutils.h"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#include "commondefine.h"
|
|
|
|
|
|
#include "TsPacker.hpp"
|
|
|
|
|
|
|
|
|
|
|
|
#include <QFile>
|
|
|
|
|
|
|
|
|
|
|
|
class TsDecoder
|
|
|
|
|
|
{
|
|
|
|
|
|
public:
|
|
|
|
|
|
void decoder(){
|
|
|
|
|
|
std::cout<<"decode loop"<<std::endl;
|
|
|
|
|
|
// decode loop
|
|
|
|
|
|
AVPacket aPacket;
|
|
|
|
|
|
int nTelemSize = sizeof(telemetryData);
|
|
|
|
|
|
int index = 0;
|
|
|
|
|
|
int raw_index = 0;
|
|
|
|
|
|
while (true)
|
|
|
|
|
|
{
|
|
|
|
|
|
// packet init
|
|
|
|
|
|
av_init_packet(&aPacket);
|
|
|
|
|
|
|
|
|
|
|
|
// read a packet
|
|
|
|
|
|
if (av_read_frame(pFormatCtx, &aPacket) == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
// check id
|
|
|
|
|
|
if (aPacket.stream_index == videoStreamID)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (avcodec_send_packet(pVideoCtx, &aPacket) == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (avcodec_receive_frame(pVideoCtx, pFrame) == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
// QFile file(QString("./img_%1.yuv").arg(aPacket.pts));
|
|
|
|
|
|
// if(file.open(QIODevice::WriteOnly)){
|
|
|
|
|
|
// file.write((char *)pFrame->data[0], pFrame->linesize[0]);
|
|
|
|
|
|
// file.write((char *)pFrame->data[1], pFrame->linesize[1]);
|
|
|
|
|
|
// }
|
|
|
|
|
|
// file.close();
|
|
|
|
|
|
cv::Mat src(1024, 1280, CV_8UC3, (char*)pFrame->data[0]);
|
|
|
|
|
|
cv::imshow("", src);
|
|
|
|
|
|
cv::waitKey(1);
|
|
|
|
|
|
|
|
|
|
|
|
qDebug() << "get image";
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
// if packet is video pkt
|
|
|
|
|
|
//_packer->demuxer(aPacket.buf->data, aPacket.buf->size, aPacket.pts, TsPacker::VIDEO);
|
|
|
|
|
|
printf("");
|
|
|
|
|
|
index ++;
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (aPacket.stream_index == telemStreamID)
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
// QFile file(QString("./img_raw_%1.yuv").arg(raw_index));
|
|
|
|
|
|
// if(file.open(QIODevice::WriteOnly)){
|
|
|
|
|
|
// file.write((char *)aPacket.buf->data, aPacket.buf->size);
|
|
|
|
|
|
// }
|
|
|
|
|
|
// file.close();
|
|
|
|
|
|
// if it is a telem pkt
|
|
|
|
|
|
// _packer->demuxer(&aPacket, TsPacker::BINDATA);
|
|
|
|
|
|
// _packer->demuxer(aPacket.buf->data, aPacket.buf->size, aPacket.pts, TsPacker::BINDATA);
|
|
|
|
|
|
|
|
|
|
|
|
telemetryData aTelem;
|
|
|
|
|
|
memset(&aTelem, 0, sizeof(telemetryData));
|
|
|
|
|
|
telemCodec::telemDecode(aPacket.buf->data, aPacket.buf->size, aTelem);
|
|
|
|
|
|
char buff[1024] = {0};
|
|
|
|
|
|
int times = raw_index / 25;
|
|
|
|
|
|
int minute = times / 60;
|
|
|
|
|
|
int misc = times % 60;
|
|
|
|
|
|
sprintf(buff, "[%02d:%02d:%02d:%04d] Lon: %.06f, %.06f, %.03f, Drone: yaw:%.06f, %.06f, %.06f, IMU: yaw:%.06f, %.06f, %.06f, Comp: yaw:%.06f, %.06f, %.06f, SF: %.06f, %.06f, Target: %.06f, %.06f, %.03f, Dis: %.03f, speed: %.06f, %.06f, %.06f\n",
|
|
|
|
|
|
aTelem.mHour, aTelem.mMinute, aTelem.mSecond, aTelem.mMillSecond,
|
|
|
|
|
|
aTelem.mDroneLongtitude, aTelem.mDroneLatitude, aTelem.mDroneAltitude,
|
|
|
|
|
|
aTelem.mDroneYaw, aTelem.mDronePitch, aTelem.mDroneRoll,
|
|
|
|
|
|
aTelem.mSensorYaw, aTelem.mSensorPitch, aTelem.mSensorRoll,
|
|
|
|
|
|
aTelem.mComposedYaw, aTelem.mComposedPitch, aTelem.mComposedRoll,
|
|
|
|
|
|
aTelem.mFrameYaw, aTelem.mFramePitch,
|
|
|
|
|
|
aTelem.mMarkLongtitude, aTelem.mMarkLatitude, aTelem.mMarkAltitude, aTelem.mLaserDistance,
|
|
|
|
|
|
aTelem.mDroneSpeedEast * 100 * 32767 / 1024,
|
|
|
|
|
|
aTelem.mDroneSpeedNorth * 100 * 32767 / 1024,
|
|
|
|
|
|
aTelem.mDroneSpeedSky * 100 * 32767 / 1024);
|
|
|
|
|
|
|
|
|
|
|
|
// file->write(buff, strlen(buff));
|
|
|
|
|
|
qDebug("[%s] \n", buff);
|
|
|
|
|
|
raw_index++;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
av_packet_unref(&aPacket);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
std::cout<<"end of file"<<std::endl;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
av_packet_unref(&aPacket);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
exit(0);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TsDecoder(const std::string &str){
|
|
|
|
|
|
int dataStreamID = 0;
|
|
|
|
|
|
int mImgWidth = 0;
|
|
|
|
|
|
int mImgHeight = 0;
|
|
|
|
|
|
int mBytesPerPixel = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// init ffmpeg
|
|
|
|
|
|
//avcodec_register_all();
|
|
|
|
|
|
avdevice_register_all();
|
|
|
|
|
|
|
|
|
|
|
|
//std::thread *dumxer = new std::thread(&this::decoder, std::ref(*this));
|
|
|
|
|
|
|
|
|
|
|
|
QStringList list = QString::fromStdString(str).split("/");
|
|
|
|
|
|
QStringList namelist = list.at(list.size() - 1).split(".");
|
|
|
|
|
|
std::string filename = QString(namelist[0] + "_out." + namelist[1]).toStdString();
|
|
|
|
|
|
_packer = new TsPacker(filename);
|
|
|
|
|
|
// create ffmpeg context
|
|
|
|
|
|
int nRet = 0;
|
|
|
|
|
|
pFormatCtx = avformat_alloc_context();
|
|
|
|
|
|
if (pFormatCtx == nullptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
std::cout << "Can not create format context for udp video stream." << std::endl;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
AVDictionary *opts = nullptr;
|
|
|
|
|
|
av_dict_set(&opts, "buffer_size", "81944000", 0);
|
|
|
|
|
|
av_dict_set(&opts, "bufsize", "81944000", 0); // "131072" 默认大小是65536
|
|
|
|
|
|
av_dict_set(&opts, "probesize", "10240000", 0); // "131072" 默认大小是5M
|
|
|
|
|
|
av_dict_set(&opts, "reorder_queue_size", "10", 0); // "131072" 默认大小是5M
|
|
|
|
|
|
|
|
|
|
|
|
av_dict_set(&opts, "rtsp_transport", "udp", 0); //以udp方式打开,如果以tcp方式打开将udp替换为tcp
|
|
|
|
|
|
av_dict_set(&opts, "max_delay", "200000", 0); //设置最大时延
|
|
|
|
|
|
|
|
|
|
|
|
nRet = avformat_open_input(&pFormatCtx, str.c_str(), nullptr, nullptr);
|
|
|
|
|
|
if (nRet != 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
std::cout << "Can not open udp video stream at: " << str.c_str()<< std::endl;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
nRet = avformat_find_stream_info(pFormatCtx, nullptr);
|
|
|
|
|
|
if (nRet < 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
std::cout << "Can not find udp video stream infomation. " << std::endl;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// find video stream id
|
|
|
|
|
|
videoStreamID = av_find_best_stream(pFormatCtx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
|
|
|
|
|
|
// find telem stream id
|
|
|
|
|
|
for (unsigned int j = 0; j < pFormatCtx->nb_streams; j++)
|
|
|
|
|
|
{
|
|
|
|
|
|
qDebug("nb[%d] type :%d,%d", j, pFormatCtx->streams[j]->codecpar->codec_id, pFormatCtx->streams[j]->codecpar->codec_type);
|
|
|
|
|
|
if (pFormatCtx->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_DATA &&
|
|
|
|
|
|
pFormatCtx->streams[j]->codecpar->codec_id == AV_CODEC_ID_BIN_DATA)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (dataStreamID < pFormatCtx->streams[j]->id)
|
|
|
|
|
|
{
|
|
|
|
|
|
telemStreamID = j;
|
|
|
|
|
|
dataStreamID = pFormatCtx->streams[j]->id;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
// set stream
|
|
|
|
|
|
if (videoStreamID > -1)
|
|
|
|
|
|
pVideoStream = pFormatCtx->streams[videoStreamID];
|
|
|
|
|
|
if (telemStreamID > -1)
|
|
|
|
|
|
pTelemStream = pFormatCtx->streams[telemStreamID];
|
|
|
|
|
|
|
|
|
|
|
|
printf("aPacket.stream_index --- %d:%d\n", videoStreamID, telemStreamID);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if video stream is validate, open codec and context
|
|
|
|
|
|
if (pVideoStream)
|
|
|
|
|
|
{
|
|
|
|
|
|
pVideoCodec = avcodec_find_decoder(pVideoStream->codecpar->codec_id);
|
|
|
|
|
|
pVideoCtx = pVideoCodec ? avcodec_alloc_context3(pVideoCodec) : nullptr;
|
|
|
|
|
|
if (pVideoCtx)
|
|
|
|
|
|
{
|
|
|
|
|
|
avcodec_parameters_to_context(pVideoCtx, pVideoStream->codecpar);
|
|
|
|
|
|
avcodec_open2(pVideoCtx, pVideoCodec, nullptr);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (pVideoCtx->width > 0 && pVideoCtx->height > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
mImgHeight = pVideoCtx->height;
|
|
|
|
|
|
mImgWidth = pVideoCtx->width;
|
|
|
|
|
|
mBytesPerPixel = 3;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
pFrame = av_frame_alloc();
|
|
|
|
|
|
qDebug("codec id:%d, %d", videoStreamID, telemStreamID);
|
|
|
|
|
|
|
|
|
|
|
|
//file = new QFile(namelist[0] + "_param.txt");
|
|
|
|
|
|
//file->open(QIODevice::WriteOnly);
|
|
|
|
|
|
//std::thread d1(&TsDecoder::decoder, std::ref(*this));
|
|
|
|
|
|
//d1.detach();
|
|
|
|
|
|
}
|
|
|
|
|
|
~TsDecoder(){
|
|
|
|
|
|
if (pFormatCtx != nullptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
avformat_free_context(pFormatCtx);
|
|
|
|
|
|
pFormatCtx = nullptr;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (pVideoCtx != nullptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
avcodec_free_context(&pVideoCtx);
|
|
|
|
|
|
pVideoCodec = nullptr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// release
|
|
|
|
|
|
avformat_network_deinit();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
// define ffmpeg format contex
|
|
|
|
|
|
AVFormatContext *pFormatCtx = nullptr;
|
|
|
|
|
|
AVStream *pVideoStream = nullptr;
|
|
|
|
|
|
AVStream *pTelemStream = nullptr;
|
|
|
|
|
|
AVCodecContext *pVideoCtx = nullptr;
|
|
|
|
|
|
AVCodec *pVideoCodec = nullptr;
|
|
|
|
|
|
AVFrame* pFrame = nullptr;
|
|
|
|
|
|
int videoStreamID = 0;
|
|
|
|
|
|
int telemStreamID = 0;
|
|
|
|
|
|
|
|
|
|
|
|
float _change_angle = 0.0;
|
|
|
|
|
|
TsPacker *_packer = nullptr;
|
|
|
|
|
|
|
|
|
|
|
|
QFile *file = nullptr;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|