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

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#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