调整网络短视频实现
parent
d1298663f3
commit
6f56bf0fe3
@ -0,0 +1,159 @@
|
||||
//
|
||||
// Created by Matthew on 2025/3/11.
|
||||
//
|
||||
|
||||
#include "Streaming.h"
|
||||
|
||||
#include <android/api-level.h>
|
||||
#include <android/log.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#if 0
|
||||
StreamForwarder::~StreamForwarder() {
|
||||
stop();
|
||||
if (inputCtx) {
|
||||
avformat_close_input(&inputCtx);
|
||||
}
|
||||
if (outputCtx) {
|
||||
if (outputCtx->pb) {
|
||||
avio_closep(&outputCtx->pb);
|
||||
}
|
||||
avformat_free_context(outputCtx);
|
||||
}
|
||||
}
|
||||
|
||||
bool StreamForwarder::initialize(const std::string& inputUrl, const std::string& outputUrl) {
|
||||
if (!openInput(inputUrl)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!openOutput(outputUrl)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool StreamForwarder::openInput(const std::string& inputUrl) {
|
||||
inputCtx = avformat_alloc_context();
|
||||
if (!inputCtx) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (avformat_open_input(&inputCtx, inputUrl.c_str(), nullptr, nullptr) < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (avformat_find_stream_info(inputCtx, nullptr) < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool StreamForwarder::openOutput(const std::string& outputUrl) {
|
||||
int ret = avformat_alloc_output_context2(&outputCtx, nullptr, "flv", outputUrl.c_str());
|
||||
if (ret < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Copy streams from input to output
|
||||
for (unsigned int i = 0; i < inputCtx->nb_streams; i++) {
|
||||
AVStream* inStream = inputCtx->streams[i];
|
||||
AVStream* outStream = avformat_new_stream(outputCtx, inStream->codec->codec);
|
||||
if (!outStream) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = avcodec_copy_context(outStream->codec, inStream->codec);
|
||||
if (ret < 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Open output file
|
||||
if (!(outputCtx->oformat->flags & AVFMT_NOFILE)) {
|
||||
ret = avio_open(&outputCtx->pb, outputUrl.c_str(), AVIO_FLAG_WRITE);
|
||||
if (ret < 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Write header
|
||||
ret = avformat_write_header(outputCtx, nullptr);
|
||||
if (ret < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void StreamForwarder::setFrameCallback(std::function<void(uint8_t*, int, int, int)> callback) {
|
||||
frameCallback = callback;
|
||||
}
|
||||
|
||||
void StreamForwarder::start() {
|
||||
isRunning = true;
|
||||
forwardPackets();
|
||||
}
|
||||
|
||||
void StreamForwarder::stop() {
|
||||
isRunning = false;
|
||||
}
|
||||
|
||||
void StreamForwarder::forwardPackets() {
|
||||
AVPacket packet;
|
||||
AVFrame* frame = av_frame_alloc();
|
||||
|
||||
while (isRunning) {
|
||||
if (av_read_frame(inputCtx, &packet) < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Process video frames if callback is set
|
||||
if (frameCallback && packet.stream_index == 0) { // Assuming video is stream 0
|
||||
AVCodecContext* codecCtx = inputCtx->streams[packet.stream_index]->codec;
|
||||
int ret = avcodec_send_packet(codecCtx, &packet);
|
||||
if (ret < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
while (ret >= 0) {
|
||||
ret = avcodec_receive_frame(codecCtx, frame);
|
||||
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
|
||||
break;
|
||||
} else if (ret < 0) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
processFrame(frame);
|
||||
}
|
||||
}
|
||||
|
||||
// Forward packet
|
||||
av_packet_rescale_ts(&packet,
|
||||
inputCtx->streams[packet.stream_index]->time_base,
|
||||
outputCtx->streams[packet.stream_index]->time_base);
|
||||
|
||||
int ret = av_interleaved_write_frame(outputCtx, &packet);
|
||||
if (ret < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
av_packet_unref(&packet);
|
||||
}
|
||||
|
||||
end:
|
||||
av_frame_free(&frame);
|
||||
av_write_trailer(outputCtx);
|
||||
}
|
||||
|
||||
void StreamForwarder::processFrame(AVFrame* frame) {
|
||||
if (frameCallback) {
|
||||
frameCallback(frame->data[0], frame->linesize[0],
|
||||
frame->width, frame->height);
|
||||
}
|
||||
}
|
||||
#endif
|
@ -0,0 +1,50 @@
|
||||
//
|
||||
// Created by Matthew on 2025/3/11.
|
||||
//
|
||||
|
||||
#ifndef MICROPHOTO_STREAMING_H
|
||||
#define MICROPHOTO_STREAMING_H
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
#include <android/multinetwork.h>
|
||||
|
||||
extern "C" {
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavutil/avutil.h>
|
||||
#include <libswscale/swscale.h>
|
||||
}
|
||||
|
||||
class Streaming
|
||||
{
|
||||
public:
|
||||
virtual ~Streaming() {}
|
||||
virtual void start() {}
|
||||
virtual void stop() {}
|
||||
};
|
||||
#if 0
|
||||
class StreamForwarder : public Streaming
|
||||
{
|
||||
private:
|
||||
AVFormatContext* inputCtx = nullptr;
|
||||
AVFormatContext* outputCtx = nullptr;
|
||||
bool isRunning = false;
|
||||
|
||||
public:
|
||||
StreamForwarder() = default;
|
||||
virtual ~StreamForwarder();
|
||||
|
||||
bool initialize(const std::string& inputUrl, const std::string& outputUrl);
|
||||
virtual void start();
|
||||
virtual void stop();
|
||||
|
||||
private:
|
||||
bool openInput(const std::string& inputUrl);
|
||||
bool openOutput(const std::string& outputUrl);
|
||||
void forwardPackets();
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif //MICROPHOTO_STREAMING_H
|
Loading…
Reference in New Issue