You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

251 lines
9.2 KiB

#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