使用asio 接收ps流代码并显示
#include <iostream>
#include <asio.hpp>
#include <unordered_map>extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/error.h>
#include <libswscale/swscale.h>
}
#include <opencv2/opencv.hpp>
#ifdef _DEBUG
#pragma comment(lib,"opencv_world490d.lib")
#else
#pragma comment(lib,"opencv_world490.lib")
#endif
using namespace std;
using namespace asio;#define AV_ERROR_REPORT char buffer[64];\
av_strerror(ret, &buffer[0], 64);\
std::cerr << "Error sending packet to decoder: " << buffer << std::endl
static uint32_t b2l(uint32_t be)
{return ((be >> 24) & 0xff)| ((be >> 8) & 0xFF00)| ((be << 8) & 0xFF0000)| ((be << 24));
}struct RTPFrame {unsigned char* _frame;int _frameLen;RTPFrame(const unsigned char* frame, int frameLen) {_frame = (unsigned char*)frame;_frameLen = frameLen;};RTPFrame(unsigned char* frame, int frameLen, unsigned char payloadType) {_frame = frame;_frameLen = frameLen;if (_frameLen > 0)_frame[0] = 0x80;SetPayloadType(payloadType);}unsigned GetPayloadSize() const {return (_frameLen - GetHeaderSize());}void SetPayloadSize(int size) {_frameLen = size + GetHeaderSize();}int GetFrameLen() const {return (_frameLen);}unsigned char* GetPayloadPtr() const {return (_frame + GetHeaderSize());}int GetHeaderSize() const {int size;size = 12;if (_frameLen < 12)return 0;size += (_frame[0] & 0x0f) * 4;if (!(_frame[0] & 0x10))return size;if ((size + 4) < _frameLen)return (size + 4 + (_frame[size + 2] << 8) + _frame[size + 3]);return 0;}bool GetMarker() const {if (_frameLen < 2){return false;}return (_frame[1] & 0x80);}unsigned GetSequenceNumber() const {if (_frameLen < 4)return 0;return (_frame[2] << 8) + _frame[3];}unsigned int GetSSRC(){uint32_t s = *((uint32_t*)(&_frame[8]));return b2l(s);}void SetMarker(bool set) {if (_frameLen < 2)return;_frame[1] = _frame[1] & 0x7f;if (set) _frame[1] = _frame[1] | 0x80;}void SetPayloadType(unsigned char type) {if (_frameLen < 2)return;_frame[1] = _frame[1] & 0x80;_frame[1] = _frame[1] | (type & 0x7f);}unsigned char GetPayloadType() const{if (_frameLen < 1)return 0xff;return _frame[1] & 0x7f;}unsigned long GetTimestamp() const {if (_frameLen < 8)return 0;return ((_frame[4] << 24) + (_frame[5] << 16) + (_frame[6] << 8) + _frame[7]);}void SetTimestamp(unsigned long timestamp) {if (_frameLen < 8)return;_frame[4] = (unsigned char)((timestamp >> 24) & 0xff);_frame[5] = (unsigned char)((timestamp >> 16) & 0xff);_frame[6] = (unsigned char)((timestamp >> 8) & 0xff);_frame[7] = (unsigned char)(timestamp & 0xff);};
};struct s_context{AVFormatContext* fc_ = NULL;AVCodecContext* cc_ = NULL;int stream_index = -1;struct SwsContext* sws = NULL;uint8_t data_[4096];FILE* file_ = NULL;
};class PSStreamServer {s_context* get_scon(std::string name){auto iter = context_.find(name);if (iter != context_.end())return iter->second;else{s_context* con = new s_context();context_[name] = con;return con;}}public:PSStreamServer(io_context& io_context, unsigned short port): socket_(io_context, ip::udp::endpoint(ip::udp::v4(), port)) {}void start_receive() {socket_.async_receive_from(asio::buffer(buffer_), remote_endpoint_,[this](std::error_code ec, std::size_t length) {if (!ec && length > 0) {RTPFrame frame(buffer_, (int)length);uint8_t* payload = frame.GetPayloadPtr();int paylen = frame.GetPayloadSize();uint32_t timestamp = frame.GetTimestamp();uint32_t ssrc = frame.GetSSRC();std::cout << "recv " << length <<" sscr :"<<ssrc << std::endl;process_with_ffmpeg(payload, paylen);start_receive(); }else {std::cerr << "Error receiving data: " << ec.message() << std::endl;}});}private:void process_with_ffmpeg(uint8_t* data, std::size_t length) {AVPacket packet;packet.data = data;packet.size = (int)length;s_context* sc = get_scon(remote_endpoint_.address().to_string());static int i = 0;if (sc->file_ == NULL)sc->file_ = fopen("test1.h264", "ab");fwrite(data, length, 1, sc->file_);if (i++ > 1000){std::cout << "end write file" << std::endl;fclose(sc->file_);}if (!sc->fc_) {sc->fc_ = avformat_alloc_context();if (!sc->fc_) {std::cerr << "Failed to allocate PS format context" << std::endl;return;}const AVInputFormat* input_format = av_find_input_format("mpeg");if (!input_format) {std::cerr << "Failed to find input format" << std::endl;avformat_free_context(sc->fc_);sc->fc_ = nullptr;return;}sc->fc_->iformat = input_format;if (avformat_open_input(&sc->fc_, "", nullptr, nullptr) != 0) {std::cerr << "Failed to open input" << std::endl;avformat_free_context(sc->fc_);sc->fc_ = nullptr;return;}if (avformat_find_stream_info(sc->fc_, nullptr) < 0) {std::cerr << "Failed to find stream info" << std::endl;avformat_close_input(&sc->fc_);avformat_free_context(sc->fc_);sc->fc_ = nullptr;return;}av_dump_format(sc->fc_, 0, "", 0);}if (!sc->cc_) {AVStream* video_stream = nullptr;for (unsigned int i = 0; i < sc->fc_->nb_streams; ++i) {if (sc->fc_->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {video_stream = sc->fc_->streams[i];break;}}if (!video_stream) {std::cerr << "No video stream found" << std::endl;return;}sc->stream_index = video_stream->index;const AVCodec* codec = avcodec_find_decoder(video_stream->codecpar->codec_id);if (!codec) {std::cerr << "Failed to find decoder for video stream" << std::endl;return;}sc->cc_ = avcodec_alloc_context3(codec);if (!sc->cc_) {std::cerr << "Failed to allocate codec context" << std::endl;return;}if (avcodec_parameters_to_context(sc->cc_, video_stream->codecpar) < 0) {std::cerr << "Failed to copy codec parameters to codec context" << std::endl;avcodec_free_context(&sc->cc_);return;}if (avcodec_open2(sc->cc_, codec, nullptr) < 0) {std::cerr << "Failed to open codec" << std::endl;avcodec_free_context(&sc->cc_);return;}}AVFrame* frame = av_frame_alloc();if (!frame) {std::cerr << "Failed to allocate frame" << std::endl;avcodec_free_context(&sc->cc_);avformat_close_input(&sc->fc_);sc->fc_= nullptr;return ;}int w = sc->cc_->width;int h = sc->cc_->height;if (sc->sws == NULL){sc->sws = sws_getContext(w, h, sc->cc_->pix_fmt,w, h, AV_PIX_FMT_BGR24,SWS_BILINEAR, nullptr, nullptr, nullptr);if (!sc->sws) {std::cerr << "Failed to initialize SwsContext" << std::endl;av_frame_free(&frame);avcodec_free_context(&sc->cc_);avformat_close_input(&sc->fc_);return;}}AVPacket pkt;while (av_read_frame(sc->fc_, &pkt) >= 0) {if (pkt.stream_index == sc->stream_index) {int ret = avcodec_send_packet(sc->cc_, &packet);if (ret < 0) {AV_ERROR_REPORT;break;}while (ret >= 0) {ret = avcodec_receive_frame(sc->cc_, frame);if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)break;else if (ret < 0) {AV_ERROR_REPORT;break;}AVFrame* bgr_frame = av_frame_alloc();if (!bgr_frame) {std::cerr << "Failed to allocate BGR frame" << std::endl;break;}bgr_frame->width = sc->cc_->width;bgr_frame->height = sc->cc_->height;bgr_frame->format = AV_PIX_FMT_BGR24;av_frame_get_buffer(bgr_frame, 0);sws_scale(sc->sws, frame->data, frame->linesize, 0, sc->cc_->height,bgr_frame->data, bgr_frame->linesize);cv::Mat bgrMat(h, w, CV_8UC3, bgr_frame->data[0]);cv::imshow("Frame", bgrMat);cv::waitKey(1);av_frame_free(&bgr_frame);}}av_packet_unref(&pkt);}}ip::udp::socket socket_;ip::udp::endpoint remote_endpoint_;uint8_t buffer_[8192] = {0}; std::unordered_map < std::string, s_context*> context_;};int main() {try {io_context io_context;PSStreamServer server(io_context, 6000); server.start_receive(); std::cout << "server start at udp port:" << 6000 << std::endl;io_context.run();}catch (std::exception& e) {std::cerr << "Exception: " << e.what() << std::endl;}return 0;
}