|
...
|
...
|
@@ -81,7 +81,7 @@ static T_ZiyanCameraFocusHandler s_focusHandler; |
|
|
|
static T_ZiyanCameraDigitalZoomHandler s_digitalZoomHandler;
|
|
|
|
static T_ZiyanCameraOpticalZoomHandler s_opticalZoomHandler;
|
|
|
|
static T_ZiyanCameraTapZoomHandler s_tapZoomHandler;
|
|
|
|
static T_ZiyanCameraExtendHandler s_extendHander;
|
|
|
|
static T_ZiyanCameraRangeFinderHandler s_rangeFinderHander;
|
|
|
|
|
|
|
|
static T_ZiyanTaskHandle s_userCameraThread;
|
|
|
|
|
|
...
|
...
|
@@ -181,1140 +181,12 @@ static void *UserCamera_Task(void *arg); |
|
|
|
|
|
|
|
/* Private functions definition-----------------------------------------------*/
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
|
|
|
/**************************************************************************************************/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <libavformat/avformat.h>
|
|
|
|
#include <libavcodec/avcodec.h>
|
|
|
|
|
|
|
|
|
|
|
|
#define VIDEO_STREAM_INDEX 0 // 视频流索引,假设为 0
|
|
|
|
#define BUFFER_SIZE 4096 // 每个帧的缓冲区大小
|
|
|
|
|
|
|
|
// void* push_video_stream(void* arg)
|
|
|
|
// {
|
|
|
|
// AVFormatContext *format_ctx = NULL;
|
|
|
|
// AVCodecContext *codec_ctx = NULL;
|
|
|
|
// AVCodec *codec = NULL;
|
|
|
|
// AVPacket packet;
|
|
|
|
// int video_stream_index = -1;
|
|
|
|
|
|
|
|
// const char* filename = "/home/levi/Videos/test.mp4";
|
|
|
|
// USER_UTIL_UNUSED(arg);
|
|
|
|
|
|
|
|
// // 初始化 FFmpeg 库
|
|
|
|
// av_register_all();
|
|
|
|
// avformat_network_init();
|
|
|
|
|
|
|
|
// // 打开输入文件
|
|
|
|
// if (avformat_open_input(&format_ctx, filename, NULL, NULL) < 0) {
|
|
|
|
// fprintf(stderr, "Could not open file: %s\n", filename);
|
|
|
|
// return;
|
|
|
|
// }
|
|
|
|
|
|
|
|
// // 获取文件信息
|
|
|
|
// if (avformat_find_stream_info(format_ctx, NULL) < 0) {
|
|
|
|
// fprintf(stderr, "Could not find stream information\n");
|
|
|
|
// return;
|
|
|
|
// }
|
|
|
|
|
|
|
|
// // 查找视频流
|
|
|
|
// for (int i = 0; i < format_ctx->nb_streams; i++) {
|
|
|
|
// if (format_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
|
|
|
// video_stream_index = i;
|
|
|
|
// break;
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
|
|
|
// if (video_stream_index == -1) {
|
|
|
|
// fprintf(stderr, "No video stream found in file\n");
|
|
|
|
// return;
|
|
|
|
// }
|
|
|
|
|
|
|
|
// // 获取视频流的解码器
|
|
|
|
// codec = avcodec_find_decoder(format_ctx->streams[video_stream_index]->codecpar->codec_id);
|
|
|
|
// if (!codec) {
|
|
|
|
// fprintf(stderr, "Codec not found\n");
|
|
|
|
// return;
|
|
|
|
// }
|
|
|
|
|
|
|
|
// // 创建解码器上下文
|
|
|
|
// codec_ctx = avcodec_alloc_context3(codec);
|
|
|
|
// if (!codec_ctx) {
|
|
|
|
// fprintf(stderr, "Could not allocate codec context\n");
|
|
|
|
// return;
|
|
|
|
// }
|
|
|
|
|
|
|
|
// // 初始化解码器上下文
|
|
|
|
// if (avcodec_parameters_to_context(codec_ctx, format_ctx->streams[video_stream_index]->codecpar) < 0) {
|
|
|
|
// fprintf(stderr, "Could not copy codec parameters to context\n");
|
|
|
|
// return;
|
|
|
|
// }
|
|
|
|
|
|
|
|
// // 打开解码器
|
|
|
|
// if (avcodec_open2(codec_ctx, codec, NULL) < 0) {
|
|
|
|
// fprintf(stderr, "Could not open codec\n");
|
|
|
|
// return;
|
|
|
|
// }
|
|
|
|
|
|
|
|
// // 读取视频数据包并推送每个视频帧
|
|
|
|
// av_init_packet(&packet);
|
|
|
|
// while (av_read_frame(format_ctx, &packet) >= 0) {
|
|
|
|
// if (packet.stream_index == video_stream_index) {
|
|
|
|
// // 发送每一帧数据到 ZiyanPayloadCamera_SendVideoStream
|
|
|
|
// T_ZiyanReturnCode ret = ZiyanPayloadCamera_SendVideoStream(packet.data, packet.size);
|
|
|
|
// usleep(1000 * 100);
|
|
|
|
// if (ret != 0) {
|
|
|
|
// printf("Failed to send video stream\n");
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
|
|
|
// // 释放数据包
|
|
|
|
// av_packet_unref(&packet);
|
|
|
|
// }
|
|
|
|
|
|
|
|
// // 释放资源
|
|
|
|
// avcodec_free_context(&codec_ctx);
|
|
|
|
// avformat_close_input(&format_ctx);
|
|
|
|
// }
|
|
|
|
|
|
|
|
#define UDP_STREAM_URL "udp://127.0.0.1:9600?pkt_size=1316"
|
|
|
|
// #define UDP_STREAM_URL "udp://192.168.3.74:9600"
|
|
|
|
// #define UDP_STREAM_URL "udp://127.0.0.1:9600"
|
|
|
|
|
|
|
|
void* push_video_stream(void* arg)
|
|
|
|
{
|
|
|
|
const char *input_file = "/home/levi/Videos/test.mp4";
|
|
|
|
AVFormatContext *ifmt_ctx = NULL, *ofmt_ctx = NULL;
|
|
|
|
AVOutputFormat *ofmt = NULL;
|
|
|
|
AVPacket pkt;
|
|
|
|
int ret, stream_index = 0;
|
|
|
|
int *stream_mapping = NULL;
|
|
|
|
int stream_mapping_size = 0;
|
|
|
|
|
|
|
|
// 初始化libavformat并注册所有的muxers, demuxers和protocols
|
|
|
|
av_register_all();
|
|
|
|
avformat_network_init();
|
|
|
|
|
|
|
|
// 打开输入文件
|
|
|
|
if ((ret = avformat_open_input(&ifmt_ctx, input_file, NULL, NULL)) < 0) {
|
|
|
|
fprintf(stderr, "Could not open input file '%s'\n", input_file);
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 获取流信息
|
|
|
|
if ((ret = avformat_find_stream_info(ifmt_ctx, NULL)) < 0) {
|
|
|
|
fprintf(stderr, "Failed to retrieve input stream information\n");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 打印输入文件信息
|
|
|
|
av_dump_format(ifmt_ctx, 0, input_file, 0);
|
|
|
|
|
|
|
|
// 分配输出上下文,并显式指定输出格式为mpegts
|
|
|
|
ofmt = av_guess_format("mpegts", NULL, NULL);
|
|
|
|
if (!ofmt) {
|
|
|
|
fprintf(stderr, "Could not find MPEG-TS output format\n");
|
|
|
|
ret = AVERROR_UNKNOWN;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
ofmt_ctx = avformat_alloc_context();
|
|
|
|
if (!ofmt_ctx) {
|
|
|
|
fprintf(stderr, "Could not create output context\n");
|
|
|
|
ret = AVERROR_UNKNOWN;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
ofmt_ctx->oformat = ofmt;
|
|
|
|
|
|
|
|
// 设置输出URL
|
|
|
|
snprintf(ofmt_ctx->filename, sizeof(ofmt_ctx->filename), "%s", UDP_STREAM_URL);
|
|
|
|
|
|
|
|
// 映射输入流到输出流
|
|
|
|
stream_mapping_size = ifmt_ctx->nb_streams;
|
|
|
|
stream_mapping = av_mallocz_array(stream_mapping_size, sizeof(*stream_mapping));
|
|
|
|
if (!stream_mapping) {
|
|
|
|
ret = AVERROR(ENOMEM);
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < ifmt_ctx->nb_streams; i++) {
|
|
|
|
AVStream *out_stream;
|
|
|
|
AVStream *in_stream = ifmt_ctx->streams[i];
|
|
|
|
AVCodecParameters *in_codecpar = in_stream->codecpar;
|
|
|
|
|
|
|
|
if (in_codecpar->codec_type != AVMEDIA_TYPE_VIDEO) {
|
|
|
|
stream_mapping[i] = -1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
stream_mapping[i] = stream_index++;
|
|
|
|
|
|
|
|
out_stream = avformat_new_stream(ofmt_ctx, NULL);
|
|
|
|
if (!out_stream) {
|
|
|
|
fprintf(stderr, "Failed allocating output stream\n");
|
|
|
|
ret = AVERROR_UNKNOWN;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = avcodec_parameters_copy(out_stream->codecpar, in_codecpar);
|
|
|
|
if (ret < 0) {
|
|
|
|
fprintf(stderr, "Failed to copy codec parameters\n");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
out_stream->codecpar->codec_tag = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 打印输出格式信息
|
|
|
|
av_dump_format(ofmt_ctx, 0, UDP_STREAM_URL, 1);
|
|
|
|
|
|
|
|
// 打开输出URL
|
|
|
|
if (!(ofmt->flags & AVFMT_NOFILE)) {
|
|
|
|
ret = avio_open(&ofmt_ctx->pb, UDP_STREAM_URL, AVIO_FLAG_WRITE);
|
|
|
|
if (ret < 0) {
|
|
|
|
fprintf(stderr, "Could not open output URL '%s'\n", UDP_STREAM_URL);
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 写文件头
|
|
|
|
ret = avformat_write_header(ofmt_ctx, NULL);
|
|
|
|
if (ret < 0) {
|
|
|
|
fprintf(stderr, "Error occurred when opening output URL\n");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 读取并写入数据包
|
|
|
|
while (1) {
|
|
|
|
AVStream *in_stream, *out_stream;
|
|
|
|
|
|
|
|
ret = av_read_frame(ifmt_ctx, &pkt);
|
|
|
|
if (ret < 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
in_stream = ifmt_ctx->streams[pkt.stream_index];
|
|
|
|
if (pkt.stream_index >= stream_mapping_size ||
|
|
|
|
stream_mapping[pkt.stream_index] < 0) {
|
|
|
|
av_packet_unref(&pkt);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
pkt.stream_index = stream_mapping[pkt.stream_index];
|
|
|
|
out_stream = ofmt_ctx->streams[pkt.stream_index];
|
|
|
|
|
|
|
|
// 复制packet
|
|
|
|
pkt.pts = av_rescale_q_rnd(pkt.pts, in_stream->time_base, out_stream->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
|
|
|
|
pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->time_base, out_stream->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
|
|
|
|
pkt.duration = av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base);
|
|
|
|
pkt.pos = -1;
|
|
|
|
|
|
|
|
|
|
|
|
// T_ZiyanReturnCode ret = ZiyanPayloadCamera_SendVideoStream(pkt.data, pkt.size);
|
|
|
|
|
|
|
|
// 写packet
|
|
|
|
ret = av_interleaved_write_frame(ofmt_ctx, &pkt);
|
|
|
|
if (ret < 0) {
|
|
|
|
fprintf(stderr, "Error muxing packet\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
av_packet_unref(&pkt);
|
|
|
|
usleep(1000*34);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 写文件尾
|
|
|
|
av_write_trailer(ofmt_ctx);
|
|
|
|
|
|
|
|
end:
|
|
|
|
avformat_close_input(&ifmt_ctx);
|
|
|
|
|
|
|
|
if (ofmt_ctx && !(ofmt->flags & AVFMT_NOFILE))
|
|
|
|
avio_closep(&ofmt_ctx->pb);
|
|
|
|
|
|
|
|
avformat_free_context(ofmt_ctx);
|
|
|
|
av_freep(&stream_mapping);
|
|
|
|
|
|
|
|
if (ret < 0 && ret != AVERROR_EOF) {
|
|
|
|
fprintf(stderr, "Error occurred: %s\n", av_err2str(ret));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void* push_video_stream1(void* arg)
|
|
|
|
{
|
|
|
|
const char *input_file = "/home/levi/Videos/test.mp4";
|
|
|
|
AVFormatContext *ifmt_ctx = NULL;
|
|
|
|
AVPacket pkt;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
// 初始化libavformat并注册所有的muxers, demuxers和protocols
|
|
|
|
av_register_all();
|
|
|
|
avformat_network_init();
|
|
|
|
|
|
|
|
// 打开输入文件
|
|
|
|
if ((ret = avformat_open_input(&ifmt_ctx, input_file, NULL, NULL)) < 0) {
|
|
|
|
fprintf(stderr, "Could not open input file '%s'\n", input_file);
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 获取流信息
|
|
|
|
if ((ret = avformat_find_stream_info(ifmt_ctx, NULL)) < 0) {
|
|
|
|
fprintf(stderr, "Failed to retrieve input stream information\n");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 打印输入文件信息
|
|
|
|
av_dump_format(ifmt_ctx, 0, input_file, 0);
|
|
|
|
|
|
|
|
// 查找视频流
|
|
|
|
int video_stream_index = -1;
|
|
|
|
for (int i = 0; i < ifmt_ctx->nb_streams; i++) {
|
|
|
|
if (ifmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
|
|
|
video_stream_index = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (video_stream_index == -1) {
|
|
|
|
fprintf(stderr, "No video stream found in input file\n");
|
|
|
|
ret = AVERROR_UNKNOWN;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 读取并发送H.264帧
|
|
|
|
while (1) {
|
|
|
|
ret = av_read_frame(ifmt_ctx, &pkt);
|
|
|
|
if (ret < 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
// 只处理视频流
|
|
|
|
if (pkt.stream_index == video_stream_index) {
|
|
|
|
// 调用发送函数发送H.264帧
|
|
|
|
ZiyanPayloadCamera_SendVideoStream(pkt.data, pkt.size);
|
|
|
|
}
|
|
|
|
usleep(1000*34);
|
|
|
|
av_packet_unref(&pkt);
|
|
|
|
}
|
|
|
|
|
|
|
|
end:
|
|
|
|
avformat_close_input(&ifmt_ctx);
|
|
|
|
|
|
|
|
if (ret < 0 && ret != AVERROR_EOF) {
|
|
|
|
fprintf(stderr, "Error occurred: %s\n", av_err2str(ret));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <libavformat/avformat.h>
|
|
|
|
#include <libavcodec/avcodec.h>
|
|
|
|
#include <libavutil/avutil.h>
|
|
|
|
#include <libavutil/opt.h>
|
|
|
|
|
|
|
|
// #define DEST_IP "127.0.0.1"
|
|
|
|
#define DEST_IP "127.0.0.1"
|
|
|
|
#define DEST_PORT 9600
|
|
|
|
|
|
|
|
void* push_video_stream2(void* arg)
|
|
|
|
{
|
|
|
|
const char *input_file = "/home/levi/Videos/test.mp4";
|
|
|
|
AVFormatContext *format_ctx = NULL;
|
|
|
|
AVCodecContext *codec_ctx = NULL;
|
|
|
|
AVStream *video_stream = NULL;
|
|
|
|
AVPacket packet;
|
|
|
|
int ret, video_stream_index;
|
|
|
|
|
|
|
|
// 初始化 FFmpeg 库
|
|
|
|
av_register_all();
|
|
|
|
avformat_network_init();
|
|
|
|
|
|
|
|
// 打开输入文件
|
|
|
|
ret = avformat_open_input(&format_ctx, input_file, NULL, NULL);
|
|
|
|
if (ret < 0) {
|
|
|
|
fprintf(stderr, "Could not open input file '%s'\n", input_file);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 获取文件信息
|
|
|
|
ret = avformat_find_stream_info(format_ctx, NULL);
|
|
|
|
if (ret < 0) {
|
|
|
|
fprintf(stderr, "Could not find stream information\n");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 查找视频流
|
|
|
|
video_stream_index = -1;
|
|
|
|
for (int i = 0; i < format_ctx->nb_streams; i++) {
|
|
|
|
if (format_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
|
|
|
video_stream_index = i;
|
|
|
|
video_stream = format_ctx->streams[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (video_stream_index == -1) {
|
|
|
|
fprintf(stderr, "No video stream found\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 获取视频流的解码器
|
|
|
|
AVCodec *codec = avcodec_find_decoder(video_stream->codecpar->codec_id);
|
|
|
|
if (!codec) {
|
|
|
|
fprintf(stderr, "Codec not found\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
codec_ctx = avcodec_alloc_context3(codec);
|
|
|
|
if (!codec_ctx) {
|
|
|
|
fprintf(stderr, "Could not allocate codec context\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = avcodec_parameters_to_context(codec_ctx, video_stream->codecpar);
|
|
|
|
if (ret < 0) {
|
|
|
|
fprintf(stderr, "Could not copy codec parameters\n");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = avcodec_open2(codec_ctx, codec, NULL);
|
|
|
|
if (ret < 0) {
|
|
|
|
fprintf(stderr, "Could not open codec\n");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 设置 UDP socket
|
|
|
|
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
|
|
|
|
if (sockfd < 0) {
|
|
|
|
perror("Socket creation failed");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct sockaddr_in dest_addr;
|
|
|
|
memset(&dest_addr, 0, sizeof(dest_addr));
|
|
|
|
dest_addr.sin_family = AF_INET;
|
|
|
|
dest_addr.sin_port = htons(DEST_PORT);
|
|
|
|
ret = inet_pton(AF_INET, DEST_IP, &dest_addr.sin_addr);
|
|
|
|
if (ret <= 0) {
|
|
|
|
fprintf(stderr, "Invalid destination IP address\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 解码并发送数据
|
|
|
|
av_init_packet(&packet);
|
|
|
|
while (1) {
|
|
|
|
ret = av_read_frame(format_ctx, &packet);
|
|
|
|
if (ret < 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (packet.stream_index == video_stream_index) {
|
|
|
|
// 这里发送的是解码后的裸流数据
|
|
|
|
ret = sendto(sockfd, packet.data, packet.size, 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
|
|
|
|
if (ret < 0) {
|
|
|
|
perror("Sendto failed");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
usleep(1000*34);
|
|
|
|
av_packet_unref(&packet);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 清理资源
|
|
|
|
close(sockfd);
|
|
|
|
avcodec_free_context(&codec_ctx);
|
|
|
|
avformat_close_input(&format_ctx);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <libavformat/avformat.h>
|
|
|
|
#include <libavcodec/avcodec.h>
|
|
|
|
#include <libavutil/avutil.h>
|
|
|
|
#include <libavutil/opt.h>
|
|
|
|
|
|
|
|
// #define DEST_IP "192.168.3.74"
|
|
|
|
// #define DEST_PORT 9600
|
|
|
|
|
|
|
|
void* push_video_stream3(void* arg)
|
|
|
|
{
|
|
|
|
const char *input_file = "/home/levi/Videos/test.mp4";
|
|
|
|
AVFormatContext *input_format_ctx = NULL, *output_format_ctx = NULL;
|
|
|
|
AVCodecContext *codec_ctx = NULL;
|
|
|
|
AVStream *video_stream = NULL;
|
|
|
|
AVPacket packet;
|
|
|
|
int ret, video_stream_index;
|
|
|
|
|
|
|
|
// 初始化 FFmpeg 库
|
|
|
|
av_register_all();
|
|
|
|
avformat_network_init();
|
|
|
|
|
|
|
|
// 打开输入 MP4 文件
|
|
|
|
ret = avformat_open_input(&input_format_ctx, input_file, NULL, NULL);
|
|
|
|
if (ret < 0) {
|
|
|
|
fprintf(stderr, "Could not open input file '%s'\n", input_file);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 获取文件流信息
|
|
|
|
ret = avformat_find_stream_info(input_format_ctx, NULL);
|
|
|
|
if (ret < 0) {
|
|
|
|
fprintf(stderr, "Could not find stream information\n");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 查找视频流
|
|
|
|
video_stream_index = -1;
|
|
|
|
for (int i = 0; i < input_format_ctx->nb_streams; i++) {
|
|
|
|
if (input_format_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
|
|
|
video_stream_index = i;
|
|
|
|
video_stream = input_format_ctx->streams[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (video_stream_index == -1) {
|
|
|
|
fprintf(stderr, "No video stream found\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 获取视频流的解码器
|
|
|
|
AVCodec *codec = avcodec_find_decoder(video_stream->codecpar->codec_id);
|
|
|
|
if (!codec) {
|
|
|
|
fprintf(stderr, "Codec not found\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
codec_ctx = avcodec_alloc_context3(codec);
|
|
|
|
if (!codec_ctx) {
|
|
|
|
fprintf(stderr, "Could not allocate codec context\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = avcodec_parameters_to_context(codec_ctx, video_stream->codecpar);
|
|
|
|
if (ret < 0) {
|
|
|
|
fprintf(stderr, "Could not copy codec parameters\n");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = avcodec_open2(codec_ctx, codec, NULL);
|
|
|
|
if (ret < 0) {
|
|
|
|
fprintf(stderr, "Could not open codec\n");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 创建输出格式上下文(MPEG-TS 格式)
|
|
|
|
ret = avformat_alloc_output_context2(&output_format_ctx, NULL, "mpegts", "udp://127.0.0.1:9600");
|
|
|
|
if (ret < 0 || !output_format_ctx) {
|
|
|
|
fprintf(stderr, "Could not create output context\n");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 创建输出流
|
|
|
|
AVStream *out_stream = avformat_new_stream(output_format_ctx, codec);
|
|
|
|
if (!out_stream) {
|
|
|
|
fprintf(stderr, "Could not create stream\n");
|
|
|
|
return AVERROR_UNKNOWN;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 复制输入流参数到输出流
|
|
|
|
ret = avcodec_parameters_copy(out_stream->codecpar, video_stream->codecpar);
|
|
|
|
if (ret < 0) {
|
|
|
|
fprintf(stderr, "Could not copy codec parameters\n");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 打开输出文件/流
|
|
|
|
if (!(output_format_ctx->oformat->flags & AVFMT_NOFILE)) {
|
|
|
|
ret = avio_open(&output_format_ctx->pb, "udp://127.0.0.1:9600", AVIO_FLAG_WRITE);
|
|
|
|
if (ret < 0) {
|
|
|
|
fprintf(stderr, "Could not open output stream\n");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 写入 MPEG-TS 文件头
|
|
|
|
ret = avformat_write_header(output_format_ctx, NULL);
|
|
|
|
if (ret < 0) {
|
|
|
|
fprintf(stderr, "Error writing header to output stream\n");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 创建 UDP socket
|
|
|
|
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
|
|
|
|
if (sockfd < 0) {
|
|
|
|
perror("Socket creation failed");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct sockaddr_in dest_addr;
|
|
|
|
memset(&dest_addr, 0, sizeof(dest_addr));
|
|
|
|
dest_addr.sin_family = AF_INET;
|
|
|
|
dest_addr.sin_port = htons(DEST_PORT);
|
|
|
|
ret = inet_pton(AF_INET, DEST_IP, &dest_addr.sin_addr);
|
|
|
|
if (ret <= 0) {
|
|
|
|
fprintf(stderr, "Invalid destination IP address\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 解码并发送视频流
|
|
|
|
av_init_packet(&packet);
|
|
|
|
while (1) {
|
|
|
|
ret = av_read_frame(input_format_ctx, &packet);
|
|
|
|
if (ret < 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (packet.stream_index == video_stream_index) {
|
|
|
|
// 将视频数据包发送到 UDP
|
|
|
|
// ret = sendto(sockfd, packet.data, packet.size, 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
|
|
|
|
ZiyanPayloadCamera_SendVideoStream(packet.data, packet.size);
|
|
|
|
if (ret < 0) {
|
|
|
|
perror("Sendto failed");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
usleep(1000 * 34);
|
|
|
|
av_packet_unref(&packet);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 写入文件尾部
|
|
|
|
av_write_trailer(output_format_ctx);
|
|
|
|
|
|
|
|
// 清理资源
|
|
|
|
close(sockfd);
|
|
|
|
avcodec_free_context(&codec_ctx);
|
|
|
|
avformat_close_input(&input_format_ctx);
|
|
|
|
avformat_free_context(output_format_ctx);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
|
|
|
|
#define TARGET_IP "127.0.0.1"
|
|
|
|
#define TARGET_PORT 9600
|
|
|
|
#define TS_PACKET_SIZE 1314
|
|
|
|
|
|
|
|
// 初始化Socket
|
|
|
|
int init_socket(const char *ip, int port) {
|
|
|
|
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
|
|
|
|
if (sockfd < 0) {
|
|
|
|
perror("Socket creation failed");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct sockaddr_in server_addr;
|
|
|
|
memset(&server_addr, 0, sizeof(server_addr));
|
|
|
|
server_addr.sin_family = AF_INET;
|
|
|
|
server_addr.sin_port = htons(port);
|
|
|
|
inet_pton(AF_INET, ip, &server_addr.sin_addr);
|
|
|
|
|
|
|
|
if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
|
|
|
|
perror("Socket connect failed");
|
|
|
|
close(sockfd);
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
return sockfd;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 推送TS包
|
|
|
|
void send_ts_packet(int sockfd, uint8_t *packet, int size) {
|
|
|
|
if (send(sockfd, packet, size, 0) < 0) {
|
|
|
|
perror("Send failed");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void* push_video_stream4(void* arg)
|
|
|
|
{
|
|
|
|
const char *input_file = "/home/levi/Videos/test.mp4";;
|
|
|
|
|
|
|
|
// 初始化FFmpeg
|
|
|
|
av_register_all();
|
|
|
|
avformat_network_init();
|
|
|
|
|
|
|
|
AVFormatContext *input_ctx = NULL;
|
|
|
|
if (avformat_open_input(&input_ctx, input_file, NULL, NULL) < 0) {
|
|
|
|
fprintf(stderr, "Could not open input file: %s\n", input_file);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (avformat_find_stream_info(input_ctx, NULL) < 0) {
|
|
|
|
fprintf(stderr, "Could not find stream information\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 查找视频流
|
|
|
|
int video_stream_index = -1;
|
|
|
|
for (int i = 0; i < input_ctx->nb_streams; i++) {
|
|
|
|
if (input_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
|
|
|
video_stream_index = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (video_stream_index == -1) {
|
|
|
|
fprintf(stderr, "No video stream found\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 初始化输出格式上下文(MPEG-TS)
|
|
|
|
AVFormatContext *output_ctx = NULL;
|
|
|
|
avformat_alloc_output_context2(&output_ctx, NULL, "mpegts", NULL);
|
|
|
|
if (!output_ctx) {
|
|
|
|
fprintf(stderr, "Could not create output context\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 添加视频流到输出上下文
|
|
|
|
AVStream *output_stream = avformat_new_stream(output_ctx, NULL);
|
|
|
|
if (!output_stream) {
|
|
|
|
fprintf(stderr, "Could not create output stream\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
avcodec_parameters_copy(output_stream->codecpar, input_ctx->streams[video_stream_index]->codecpar);
|
|
|
|
output_stream->codecpar->codec_tag = 0;
|
|
|
|
|
|
|
|
// 初始化Socket
|
|
|
|
int sockfd = init_socket(TARGET_IP, TARGET_PORT);
|
|
|
|
|
|
|
|
// 写入TS流到Socket
|
|
|
|
AVPacket pkt;
|
|
|
|
av_init_packet(&pkt);
|
|
|
|
pkt.data = NULL;
|
|
|
|
pkt.size = 0;
|
|
|
|
|
|
|
|
while (av_read_frame(input_ctx, &pkt) >= 0) {
|
|
|
|
if (pkt.stream_index == video_stream_index) {
|
|
|
|
// 发送TS包
|
|
|
|
uint8_t *ts_packet = pkt.data;
|
|
|
|
int ts_packet_size = pkt.size;
|
|
|
|
while (ts_packet_size > 0) {
|
|
|
|
int send_size = (ts_packet_size > TS_PACKET_SIZE) ? TS_PACKET_SIZE : ts_packet_size;
|
|
|
|
send_ts_packet(sockfd, ts_packet, send_size);
|
|
|
|
ts_packet += send_size;
|
|
|
|
ts_packet_size -= send_size;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
usleep(1000 * 34);
|
|
|
|
av_packet_unref(&pkt);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 清理资源
|
|
|
|
avformat_close_input(&input_ctx);
|
|
|
|
avformat_free_context(output_ctx);
|
|
|
|
close(sockfd);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <libavformat/avformat.h>
|
|
|
|
#include <libavcodec/avcodec.h>
|
|
|
|
#include <libavutil/opt.h>
|
|
|
|
|
|
|
|
#define OUTPUT_UDP "udp://127.0.0.1:9600"
|
|
|
|
#define INPUT_FILE "/home/levi/Videos/test.mp4"
|
|
|
|
|
|
|
|
void* push_video_stream5(void* arg)
|
|
|
|
{
|
|
|
|
avformat_network_init();
|
|
|
|
|
|
|
|
// 打开输入 MP4 文件
|
|
|
|
AVFormatContext *input_fmt_ctx = NULL;
|
|
|
|
if (avformat_open_input(&input_fmt_ctx, INPUT_FILE, NULL, NULL) < 0) {
|
|
|
|
fprintf(stderr, "Could not open input file '%s'\n", INPUT_FILE);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (avformat_find_stream_info(input_fmt_ctx, NULL) < 0) {
|
|
|
|
fprintf(stderr, "Could not find stream information\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 查找视频流
|
|
|
|
int video_stream_index = -1;
|
|
|
|
AVCodecContext *video_codec_ctx = NULL;
|
|
|
|
for (int i = 0; i < input_fmt_ctx->nb_streams; i++) {
|
|
|
|
if (input_fmt_ctx->streams[i]->codecpar->codec_id == AV_CODEC_ID_H264) {
|
|
|
|
video_stream_index = i;
|
|
|
|
video_codec_ctx = avcodec_alloc_context3(NULL);
|
|
|
|
avcodec_parameters_to_context(video_codec_ctx, input_fmt_ctx->streams[i]->codecpar);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (video_stream_index == -1) {
|
|
|
|
fprintf(stderr, "No H.264 video stream found\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 打开解码器
|
|
|
|
AVCodec *video_codec = avcodec_find_decoder(video_codec_ctx->codec_id);
|
|
|
|
if (avcodec_open2(video_codec_ctx, video_codec, NULL) < 0) {
|
|
|
|
fprintf(stderr, "Could not open codec\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 创建输出 UDP 流
|
|
|
|
AVFormatContext *output_fmt_ctx = NULL;
|
|
|
|
if (avformat_alloc_output_context2(&output_fmt_ctx, NULL, "mpegts", OUTPUT_UDP) < 0) {
|
|
|
|
fprintf(stderr, "Could not create output context\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 创建视频流
|
|
|
|
AVStream *out_stream = avformat_new_stream(output_fmt_ctx, video_codec);
|
|
|
|
if (!out_stream) {
|
|
|
|
fprintf(stderr, "Failed to create new stream\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 使用复制的参数配置输出流
|
|
|
|
if (avcodec_parameters_copy(out_stream->codecpar, input_fmt_ctx->streams[video_stream_index]->codecpar) < 0) {
|
|
|
|
fprintf(stderr, "Failed to copy codec parameters\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 打开输出流
|
|
|
|
if (!(output_fmt_ctx->oformat->flags & AVFMT_NOFILE)) {
|
|
|
|
if (avio_open(&output_fmt_ctx->pb, OUTPUT_UDP, AVIO_FLAG_WRITE) < 0) {
|
|
|
|
fprintf(stderr, "Could not open output file\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 写入文件头
|
|
|
|
if (avformat_write_header(output_fmt_ctx, NULL) < 0) {
|
|
|
|
fprintf(stderr, "Error occurred when opening output file\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 读取数据包并转发到 UDP
|
|
|
|
AVPacket packet;
|
|
|
|
while (1) {
|
|
|
|
if (av_read_frame(input_fmt_ctx, &packet) < 0) {
|
|
|
|
break; // 读取完毕
|
|
|
|
}
|
|
|
|
|
|
|
|
// 如果是视频流,直接转发
|
|
|
|
if (packet.stream_index == video_stream_index) {
|
|
|
|
// 复制数据包并推送到 UDP
|
|
|
|
if (av_interleaved_write_frame(output_fmt_ctx, &packet) < 0) {
|
|
|
|
fprintf(stderr, "Error while writing packet\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
usleep(1000 * 34);
|
|
|
|
}
|
|
|
|
//
|
|
|
|
// 释放包内存
|
|
|
|
av_packet_unref(&packet);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 写入文件尾并关闭
|
|
|
|
av_write_trailer(output_fmt_ctx);
|
|
|
|
avcodec_free_context(&video_codec_ctx);
|
|
|
|
avformat_close_input(&input_fmt_ctx);
|
|
|
|
avformat_free_context(output_fmt_ctx);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <libavformat/avformat.h>
|
|
|
|
#include <libavcodec/avcodec.h>
|
|
|
|
#include <libavutil/opt.h>
|
|
|
|
|
|
|
|
#define MAX_PACKET_SIZE 1316 // UDP 最大数据包大小(1500字节的MTU减去头部)
|
|
|
|
#define PAYLOAD_HEADER_SIZE 4 // 假设我们需要4字节来存储包的序号或其他信息
|
|
|
|
|
|
|
|
// 发送视频流数据到UDP
|
|
|
|
int SendVideoStream(const uint8_t *data, uint16_t len, int sockfd, struct sockaddr_in *dest_addr) {
|
|
|
|
// 将数据分片并发送
|
|
|
|
int remaining = len;
|
|
|
|
int offset = 0;
|
|
|
|
while (remaining > 0) {
|
|
|
|
int size_to_send = (remaining > (MAX_PACKET_SIZE - PAYLOAD_HEADER_SIZE)) ? (MAX_PACKET_SIZE - PAYLOAD_HEADER_SIZE) : remaining;
|
|
|
|
|
|
|
|
// 为每个数据包添加头部信息(例如,偏移量)
|
|
|
|
uint8_t *packet_data = malloc(PAYLOAD_HEADER_SIZE + size_to_send);
|
|
|
|
if (!packet_data) {
|
|
|
|
perror("Failed to allocate memory for packet fragment");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 在包头附加偏移量或序号(简单示例)
|
|
|
|
*(int*)packet_data = offset; // 偏移量作为示例
|
|
|
|
memcpy(packet_data + PAYLOAD_HEADER_SIZE, data + offset, size_to_send);
|
|
|
|
|
|
|
|
// 发送数据包
|
|
|
|
ssize_t sent_len = sendto(sockfd, packet_data, PAYLOAD_HEADER_SIZE + size_to_send, 0, (struct sockaddr*)dest_addr, sizeof(*dest_addr));
|
|
|
|
if (sent_len < 0) {
|
|
|
|
perror("Failed to send UDP packet");
|
|
|
|
free(packet_data);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("send len %d\n", sent_len);
|
|
|
|
|
|
|
|
// 更新状态
|
|
|
|
remaining -= size_to_send;
|
|
|
|
offset += size_to_send;
|
|
|
|
free(packet_data); // 释放已发送的数据包
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void* push_video_stream6(void* arg)
|
|
|
|
{
|
|
|
|
avformat_network_init();
|
|
|
|
|
|
|
|
// 打开输入 MP4 文件
|
|
|
|
AVFormatContext *input_fmt_ctx = NULL;
|
|
|
|
if (avformat_open_input(&input_fmt_ctx, INPUT_FILE, NULL, NULL) < 0) {
|
|
|
|
fprintf(stderr, "Could not open input file '%s'\n", INPUT_FILE);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (avformat_find_stream_info(input_fmt_ctx, NULL) < 0) {
|
|
|
|
fprintf(stderr, "Could not find stream information\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 查找视频流
|
|
|
|
int video_stream_index = -1;
|
|
|
|
AVCodecContext *video_codec_ctx = NULL;
|
|
|
|
for (int i = 0; i < input_fmt_ctx->nb_streams; i++) {
|
|
|
|
if (input_fmt_ctx->streams[i]->codecpar->codec_id == AV_CODEC_ID_H264) {
|
|
|
|
video_stream_index = i;
|
|
|
|
video_codec_ctx = avcodec_alloc_context3(NULL);
|
|
|
|
avcodec_parameters_to_context(video_codec_ctx, input_fmt_ctx->streams[i]->codecpar);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (video_stream_index == -1) {
|
|
|
|
fprintf(stderr, "No H.264 video stream found\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 打开解码器
|
|
|
|
AVCodec *video_codec = avcodec_find_decoder(video_codec_ctx->codec_id);
|
|
|
|
if (avcodec_open2(video_codec_ctx, video_codec, NULL) < 0) {
|
|
|
|
fprintf(stderr, "Could not open codec\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 创建 UDP 套接字
|
|
|
|
int sockfd;
|
|
|
|
struct sockaddr_in dest_addr;
|
|
|
|
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
|
|
|
|
if (sockfd < 0) {
|
|
|
|
perror("Socket creation failed");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(&dest_addr, 0, sizeof(dest_addr));
|
|
|
|
dest_addr.sin_family = AF_INET;
|
|
|
|
dest_addr.sin_port = htons(9600); // 目标端口
|
|
|
|
if (inet_pton(AF_INET, "127.0.0.1", &dest_addr.sin_addr) <= 0) {
|
|
|
|
perror("Invalid address");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 读取数据包并推送到 UDP
|
|
|
|
AVPacket packet;
|
|
|
|
while (1) {
|
|
|
|
if (av_read_frame(input_fmt_ctx, &packet) < 0) {
|
|
|
|
break; // 读取完毕
|
|
|
|
}
|
|
|
|
|
|
|
|
// 如果是视频流,推送到 UDP
|
|
|
|
if (packet.stream_index == video_stream_index) {
|
|
|
|
// 使用 ZiyanPayloadCamera_SendVideoStream 发送数据
|
|
|
|
if (SendVideoStream(packet.data, packet.size, sockfd, &dest_addr) < 0) {
|
|
|
|
fprintf(stderr, "Error sending packet\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
usleep(1000 * 33);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 释放包内存
|
|
|
|
av_packet_unref(&packet);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 清理
|
|
|
|
close(sockfd);
|
|
|
|
avcodec_free_context(&video_codec_ctx);
|
|
|
|
avformat_close_input(&input_fmt_ctx);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#include <libavformat/avformat.h>
|
|
|
|
#include <libavcodec/avcodec.h>
|
|
|
|
#include <libavutil/opt.h>
|
|
|
|
#include <libavdevice/avdevice.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <arpa/inet.h> // 引入该头文件
|
|
|
|
|
|
|
|
#define STREAM_PORT 9600
|
|
|
|
#define STREAM_ADDR "127.0.0.1"
|
|
|
|
|
|
|
|
void* push_video_stream7(void* arg)
|
|
|
|
{
|
|
|
|
av_register_all();
|
|
|
|
avformat_network_init();
|
|
|
|
|
|
|
|
// Input file path
|
|
|
|
char *input_file = "/home/levi/Videos/test.mp4"; // Replace with your input file
|
|
|
|
|
|
|
|
AVFormatContext *input_format_context = NULL;
|
|
|
|
AVCodecContext *codec_context = NULL;
|
|
|
|
AVCodec *codec = NULL;
|
|
|
|
AVPacket packet;
|
|
|
|
|
|
|
|
// Open the input MP4 file
|
|
|
|
if (avformat_open_input(&input_format_context, input_file, NULL, NULL) < 0) {
|
|
|
|
fprintf(stderr, "Error opening input file\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (avformat_find_stream_info(input_format_context, NULL) < 0) {
|
|
|
|
fprintf(stderr, "Error finding stream info\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find the video stream
|
|
|
|
int stream_index = -1;
|
|
|
|
for (int i = 0; i < input_format_context->nb_streams; i++) {
|
|
|
|
if (input_format_context->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
|
|
|
stream_index = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (stream_index == -1) {
|
|
|
|
fprintf(stderr, "No video stream found\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
AVStream *video_stream = input_format_context->streams[stream_index];
|
|
|
|
codec = avcodec_find_decoder(video_stream->codecpar->codec_id);
|
|
|
|
if (!codec) {
|
|
|
|
fprintf(stderr, "Codec not found\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
codec_context = avcodec_alloc_context3(codec);
|
|
|
|
if (!codec_context) {
|
|
|
|
fprintf(stderr, "Could not allocate codec context\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (avcodec_parameters_to_context(codec_context, video_stream->codecpar) < 0) {
|
|
|
|
fprintf(stderr, "Failed to copy codec parameters to context\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (avcodec_open2(codec_context, codec, NULL) < 0) {
|
|
|
|
fprintf(stderr, "Error opening codec\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// UDP socket setup for RTP
|
|
|
|
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
|
|
|
|
if (sockfd < 0) {
|
|
|
|
perror("Error opening UDP socket");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct sockaddr_in dest_addr;
|
|
|
|
memset(&dest_addr, 0, sizeof(dest_addr));
|
|
|
|
dest_addr.sin_family = AF_INET;
|
|
|
|
dest_addr.sin_port = htons(STREAM_PORT);
|
|
|
|
|
|
|
|
// 使用 inet_pton 替换 inet_addr
|
|
|
|
if (inet_pton(AF_INET, STREAM_ADDR, &dest_addr.sin_addr) <= 0) {
|
|
|
|
perror("Invalid address/Address not supported");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize packet structure
|
|
|
|
av_init_packet(&packet);
|
|
|
|
packet.data = NULL;
|
|
|
|
packet.size = 0;
|
|
|
|
|
|
|
|
// Start reading and sending packets
|
|
|
|
while (av_read_frame(input_format_context, &packet) >= 0) {
|
|
|
|
if (packet.stream_index == stream_index) {
|
|
|
|
// Send H.264 stream as RTP packet
|
|
|
|
if (sendto(sockfd, packet.data, packet.size, 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr)) < 0) {
|
|
|
|
perror("Error sending RTP packet");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
av_packet_unref(&packet);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Clean up and close the socket
|
|
|
|
close(sockfd);
|
|
|
|
avcodec_free_context(&codec_context);
|
|
|
|
avformat_close_input(&input_format_context);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef FFMPEG_INSTALLED
|
|
|
|
#include <libavformat/avformat.h>
|
|
|
|
#include <libavcodec/avcodec.h>
|
|
|
|
#include <libavutil/opt.h>
|
|
|
|
#include <libavutil/avutil.h>
|
|
|
|
#include <libavdevice/avdevice.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
...
|
...
|
@@ -1325,15 +197,17 @@ void* push_video_stream7(void* arg) |
|
|
|
#define STREAM_PORT 9600
|
|
|
|
#define STREAM_ADDR "127.0.0.1"
|
|
|
|
#define INPUT_FILE "/home/levi/Videos/test.h264" // Replace with your actual video file path
|
|
|
|
#define INPUT_FILE2 "test.h264"
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void* push_video_stream8(void* arg)
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(FFMPEG_INSTALLED) && (LIBAVFORMAT_VERSION_MAJOR >= 57)
|
|
|
|
while(1){
|
|
|
|
|
|
|
|
// Initialize FFmpeg libraries
|
|
|
|
av_register_all();
|
|
|
|
// av_register_all();
|
|
|
|
avformat_network_init();
|
|
|
|
|
|
|
|
AVFormatContext *input_format_context = NULL;
|
|
...
|
...
|
@@ -1341,121 +215,34 @@ void* push_video_stream8(void* arg) |
|
|
|
AVCodec *codec = NULL;
|
|
|
|
AVPacket packet;
|
|
|
|
|
|
|
|
printf("input file: %s\n", INPUT_FILE);
|
|
|
|
|
|
|
|
// Open the input MP4 file
|
|
|
|
if (avformat_open_input(&input_format_context, INPUT_FILE, NULL, NULL) < 0) {
|
|
|
|
fprintf(stderr, "Error opening input file\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Retrieve stream information
|
|
|
|
if (avformat_find_stream_info(input_format_context, NULL) < 0) {
|
|
|
|
fprintf(stderr, "Error finding stream info\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find the video stream
|
|
|
|
int video_stream_index = -1;
|
|
|
|
for (int i = 0; i < input_format_context->nb_streams; i++) {
|
|
|
|
if (input_format_context->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
|
|
|
video_stream_index = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (video_stream_index == -1) {
|
|
|
|
fprintf(stderr, "Video stream not found\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find the decoder for the video stream
|
|
|
|
AVStream *video_stream = input_format_context->streams[video_stream_index];
|
|
|
|
codec = avcodec_find_decoder(video_stream->codecpar->codec_id);
|
|
|
|
if (!codec) {
|
|
|
|
fprintf(stderr, "Codec not found\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
codec_context = avcodec_alloc_context3(codec);
|
|
|
|
if (!codec_context) {
|
|
|
|
fprintf(stderr, "Could not allocate codec context\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (avcodec_parameters_to_context(codec_context, video_stream->codecpar) < 0) {
|
|
|
|
fprintf(stderr, "Failed to copy codec parameters to context\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (avcodec_open2(codec_context, codec, NULL) < 0) {
|
|
|
|
fprintf(stderr, "Error opening codec\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize packet structure
|
|
|
|
av_init_packet(&packet);
|
|
|
|
packet.data = NULL;
|
|
|
|
packet.size = 0;
|
|
|
|
char cwd[256] = {0};
|
|
|
|
char file_path[256] = {0};
|
|
|
|
getcwd(cwd, sizeof(cwd));
|
|
|
|
sprintf(file_path, "%s/%s", cwd, INPUT_FILE2);
|
|
|
|
|
|
|
|
// Start reading frames and send packets
|
|
|
|
while (av_read_frame(input_format_context, &packet) >= 0) {
|
|
|
|
if (packet.stream_index == video_stream_index) {
|
|
|
|
// Send the H.264 encoded packet over UDP
|
|
|
|
ZiyanPayloadCamera_SendVideoStream(packet.data, packet.size);
|
|
|
|
// printf("Sent packet of size %d\n", packet.size);
|
|
|
|
usleep(1000 * 33);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Free the packet after sending
|
|
|
|
av_packet_unref(&packet);
|
|
|
|
}
|
|
|
|
char input_file[256] = {0};
|
|
|
|
|
|
|
|
// Clean up and close
|
|
|
|
avcodec_free_context(&codec_context);
|
|
|
|
avformat_close_input(&input_format_context);
|
|
|
|
if (access(file_path, F_OK) == 0) {
|
|
|
|
memcpy(input_file, file_path, strlen(file_path));
|
|
|
|
USER_LOG_INFO("select: %s", file_path);
|
|
|
|
} else {
|
|
|
|
memcpy(input_file, INPUT_FILE, strlen(INPUT_FILE));
|
|
|
|
USER_LOG_INFO("select: %s", INPUT_FILE);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#include <libavformat/avformat.h>
|
|
|
|
#include <libavcodec/avcodec.h>
|
|
|
|
#include <libavutil/opt.h>
|
|
|
|
#include <libavutil/avutil.h>
|
|
|
|
#include <libavdevice/avdevice.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
|
|
|
|
|
|
|
|
void* push_video_stream9(void* arg)
|
|
|
|
{
|
|
|
|
// Initialize FFmpeg libraries
|
|
|
|
av_register_all();
|
|
|
|
avformat_network_init();
|
|
|
|
|
|
|
|
AVFormatContext *input_format_context = NULL;
|
|
|
|
AVCodecContext *codec_context = NULL;
|
|
|
|
AVCodec *codec = NULL;
|
|
|
|
AVPacket packet;
|
|
|
|
|
|
|
|
printf("input file: %s\n", INPUT_FILE);
|
|
|
|
USER_LOG_INFO("input file: %s", input_file);
|
|
|
|
|
|
|
|
// Open the input H.264 file
|
|
|
|
if (avformat_open_input(&input_format_context, INPUT_FILE, NULL, NULL) < 0) {
|
|
|
|
// Open the input MP4 file
|
|
|
|
if (avformat_open_input(&input_format_context, input_file, NULL, NULL) < 0) {
|
|
|
|
fprintf(stderr, "Error opening input file\n");
|
|
|
|
return -1;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Retrieve stream information
|
|
|
|
if (avformat_find_stream_info(input_format_context, NULL) < 0) {
|
|
|
|
fprintf(stderr, "Error finding stream info\n");
|
|
|
|
return -1;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find the video stream
|
|
...
|
...
|
@@ -1469,7 +256,7 @@ void* push_video_stream9(void* arg) |
|
|
|
|
|
|
|
if (video_stream_index == -1) {
|
|
|
|
fprintf(stderr, "Video stream not found\n");
|
|
|
|
return -1;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find the decoder for the video stream
|
|
...
|
...
|
@@ -1477,61 +264,25 @@ void* push_video_stream9(void* arg) |
|
|
|
codec = avcodec_find_decoder(video_stream->codecpar->codec_id);
|
|
|
|
if (!codec) {
|
|
|
|
fprintf(stderr, "Codec not found\n");
|
|
|
|
return -1;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
codec_context = avcodec_alloc_context3(codec);
|
|
|
|
if (!codec_context) {
|
|
|
|
fprintf(stderr, "Could not allocate codec context\n");
|
|
|
|
return -1;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (avcodec_parameters_to_context(codec_context, video_stream->codecpar) < 0) {
|
|
|
|
fprintf(stderr, "Failed to copy codec parameters to context\n");
|
|
|
|
return -1;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (avcodec_open2(codec_context, codec, NULL) < 0) {
|
|
|
|
fprintf(stderr, "Error opening codec\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TCP socket setup
|
|
|
|
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
|
|
|
if (sockfd < 0) {
|
|
|
|
perror("Error opening TCP socket");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct sockaddr_in server_addr;
|
|
|
|
memset(&server_addr, 0, sizeof(server_addr));
|
|
|
|
server_addr.sin_family = AF_INET;
|
|
|
|
server_addr.sin_port = htons(STREAM_PORT);
|
|
|
|
server_addr.sin_addr.s_addr = INADDR_ANY;
|
|
|
|
|
|
|
|
// Bind the socket to the address and port
|
|
|
|
if (bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
|
|
|
|
perror("Error binding socket");
|
|
|
|
return -1;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Listen for incoming connections
|
|
|
|
if (listen(sockfd, 1) < 0) {
|
|
|
|
perror("Error listening for connections");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("Waiting for client connection...\n");
|
|
|
|
|
|
|
|
// Accept client connection
|
|
|
|
int client_sockfd = accept(sockfd, NULL, NULL);
|
|
|
|
if (client_sockfd < 0) {
|
|
|
|
perror("Error accepting client connection");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("Client connected, sending video stream...\n");
|
|
|
|
|
|
|
|
// Initialize packet structure
|
|
|
|
av_init_packet(&packet);
|
|
|
|
packet.data = NULL;
|
|
...
|
...
|
@@ -1540,13 +291,10 @@ void* push_video_stream9(void* arg) |
|
|
|
// Start reading frames and send packets
|
|
|
|
while (av_read_frame(input_format_context, &packet) >= 0) {
|
|
|
|
if (packet.stream_index == video_stream_index) {
|
|
|
|
// Send the H.264 encoded packet to the client over TCP
|
|
|
|
if (send(client_sockfd, packet.data, packet.size, 0) < 0) {
|
|
|
|
perror("Error sending TCP packet");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
printf("Sent packet of size %d\n", packet.size);
|
|
|
|
usleep(1000 * 30); // simulate 30fps
|
|
|
|
// Send the H.264 encoded packet over UDP
|
|
|
|
ZiyanPayloadCamera_SendVideoStream(packet.data, packet.size);
|
|
|
|
// printf("Sent packet of size %d\n", packet.size);
|
|
|
|
usleep(1000 * 33);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Free the packet after sending
|
|
...
|
...
|
@@ -1554,184 +302,17 @@ void* push_video_stream9(void* arg) |
|
|
|
}
|
|
|
|
|
|
|
|
// Clean up and close
|
|
|
|
close(client_sockfd);
|
|
|
|
close(sockfd);
|
|
|
|
avcodec_free_context(&codec_context);
|
|
|
|
avformat_close_input(&input_format_context);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void* push_video_stream10(void* arg)
|
|
|
|
{
|
|
|
|
// Initialize FFmpeg libraries
|
|
|
|
av_register_all();
|
|
|
|
avformat_network_init();
|
|
|
|
|
|
|
|
AVFormatContext *input_format_context = NULL;
|
|
|
|
AVCodecContext *codec_context = NULL;
|
|
|
|
AVCodec *codec = NULL;
|
|
|
|
AVPacket packet;
|
|
|
|
|
|
|
|
printf("input file: %s\n", INPUT_FILE);
|
|
|
|
|
|
|
|
// Open the input H.264 file
|
|
|
|
if (avformat_open_input(&input_format_context, INPUT_FILE, NULL, NULL) < 0) {
|
|
|
|
fprintf(stderr, "Error opening input file\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Retrieve stream information
|
|
|
|
if (avformat_find_stream_info(input_format_context, NULL) < 0) {
|
|
|
|
fprintf(stderr, "Error finding stream info\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find the video stream
|
|
|
|
int video_stream_index = -1;
|
|
|
|
for (int i = 0; i < input_format_context->nb_streams; i++) {
|
|
|
|
if (input_format_context->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
|
|
|
video_stream_index = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (video_stream_index == -1) {
|
|
|
|
fprintf(stderr, "Video stream not found\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find the decoder for the video stream
|
|
|
|
AVStream *video_stream = input_format_context->streams[video_stream_index];
|
|
|
|
codec = avcodec_find_decoder(video_stream->codecpar->codec_id);
|
|
|
|
if (!codec) {
|
|
|
|
fprintf(stderr, "Codec not found\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
codec_context = avcodec_alloc_context3(codec);
|
|
|
|
if (!codec_context) {
|
|
|
|
fprintf(stderr, "Could not allocate codec context\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (avcodec_parameters_to_context(codec_context, video_stream->codecpar) < 0) {
|
|
|
|
fprintf(stderr, "Failed to copy codec parameters to context\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (avcodec_open2(codec_context, codec, NULL) < 0) {
|
|
|
|
fprintf(stderr, "Error opening codec\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TCP socket setup
|
|
|
|
T_ZiyanSocketHandle socket_handle = NULL;
|
|
|
|
T_ZiyanReturnCode result = ZiyanPlatform_GetSocketHandler()->Socket(ZIYAN_SOCKET_MODE_TCP, &socket_handle);
|
|
|
|
printf("Socket result: %d\n", result);
|
|
|
|
if (result != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
|
|
|
perror("Error opening TCP socket");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Bind the socket to the address and port
|
|
|
|
if (ZiyanPlatform_GetSocketHandler()->Bind(socket_handle, "0.0.0.0", 9600) != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
|
|
|
perror("Error binding socket");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Listen for incoming connections
|
|
|
|
if (ZiyanPlatform_GetSocketHandler()->TcpListen(socket_handle) != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
|
|
|
perror("Error listening for connections");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("Waiting for client connection...\n");
|
|
|
|
|
|
|
|
// Accept client connection
|
|
|
|
char accept_ip[32] = "";
|
|
|
|
uint32_t accept_port = 0;
|
|
|
|
T_ZiyanSocketHandle accept_socket_handle = NULL;
|
|
|
|
if (ZiyanPlatform_GetSocketHandler()->TcpAccept(socket_handle, accept_ip, &accept_port, &accept_socket_handle) != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
|
|
|
perror("Error accepting client connection");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("Client connected %s:%d, sending video stream...\n", accept_ip, accept_port);
|
|
|
|
|
|
|
|
// Initialize packet structure
|
|
|
|
av_init_packet(&packet);
|
|
|
|
packet.data = NULL;
|
|
|
|
packet.size = 0;
|
|
|
|
|
|
|
|
// Start reading frames and send packets
|
|
|
|
while (av_read_frame(input_format_context, &packet) >= 0) {
|
|
|
|
if (packet.stream_index == video_stream_index) {
|
|
|
|
// Send the H.264 encoded packet to the client over TCP
|
|
|
|
uint32_t real_len = 0;
|
|
|
|
if (ZiyanPlatform_GetSocketHandler()->TcpSendData(accept_socket_handle, packet.data, packet.size, &real_len) != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
|
|
|
perror("Error sending TCP packet");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
printf("Sent packet of size %d : %d\n", packet.size, real_len);
|
|
|
|
usleep(1000 * 30); // simulate 30fps
|
|
|
|
}
|
|
|
|
|
|
|
|
// Free the packet after sending
|
|
|
|
av_packet_unref(&packet);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Clean up and close
|
|
|
|
avcodec_free_context(&codec_context);
|
|
|
|
avformat_close_input(&input_format_context);
|
|
|
|
|
|
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static T_ZiyanReturnCode GetSystemState(T_ZiyanCameraSystemState *systemState)
|
|
|
|
{
|
|
|
|
T_ZiyanReturnCode returnCode;
|
|
...
|
...
|
@@ -2900,23 +1481,20 @@ T_ZiyanReturnCode ZiyanTest_CameraEmuBaseStartService(void) |
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
s_extendHander.GetRangeFinderSwitch = GetRangeFinderSwitch;
|
|
|
|
s_extendHander.SetRangeFinderSwitch = SetRangeFinderSwitch;
|
|
|
|
s_extendHander.GetRangeFinderData = GetRangeFinderData;
|
|
|
|
s_extendHander.GetRangeFinderLocation = GetRangeFinderLocation;
|
|
|
|
s_rangeFinderHander.GetRangeFinderSwitch = GetRangeFinderSwitch;
|
|
|
|
s_rangeFinderHander.SetRangeFinderSwitch = SetRangeFinderSwitch;
|
|
|
|
s_rangeFinderHander.GetRangeFinderData = GetRangeFinderData;
|
|
|
|
s_rangeFinderHander.GetRangeFinderLocation = GetRangeFinderLocation;
|
|
|
|
|
|
|
|
returnCode = ZiyanPayloadCamera_RegExtendHandler(&s_extendHander);
|
|
|
|
returnCode = ZiyanPayloadCamera_RegRangeFinderHandler(&s_rangeFinderHander);
|
|
|
|
if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
|
|
|
USER_LOG_ERROR("camera register extend handler error:0x%08llX", returnCode);
|
|
|
|
USER_LOG_ERROR("camera register range finder handler error:0x%08llX", returnCode);
|
|
|
|
return returnCode;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//修改位
|
|
|
|
|
|
|
|
// T_ZiyanTaskHandle handle_test;
|
|
|
|
// osalHandler->TaskCreate("camera_vedio_task", push_video_stream8,
|
|
|
|
// PAYLOAD_CAMERA_EMU_TASK_STACK_SIZE, NULL, &handle_test);
|
|
|
|
T_ZiyanTaskHandle handle_test;
|
|
|
|
osalHandler->TaskCreate("camera_vedio_task", push_video_stream8,
|
|
|
|
PAYLOAD_CAMERA_EMU_TASK_STACK_SIZE, NULL, &handle_test);
|
|
|
|
|
|
|
|
/* Create the camera emu taskHandle */
|
|
|
|
if (osalHandler->TaskCreate("user_camera_task", UserCamera_Task,
|
...
|
...
|
|