问题
My test_ffmpeg.c can push the local H.264 video to the RTMP server,and received_video.c can receive h.264 format data from socket, but now I want to push the H264 format data received from the socket to the RTMP server. Excuse me, can it be implemented? and How can I modify my code?
note 1:Three methods I found on the Internet.I want to use the third one, but I don't know how to modify it.
Method 1: set up RTMP server locally, change the port number of local RTMP
server to the same as socket monitoring, and then the local RTMP server
will listen to the data and forward it to the remote RTMP server;
Method 2: cache the H264 monitored by socket, implement RTMP protocol by
myself, and then push it to the remote RTMP server;
Method 3: I need to modify ffmpeg API and set callback, that is in my
test_ffmpeg.c can be modified.
note 2:
test_ffmpeg.c : push the local h.264 video to the rtmp server.
received_video.c : received h.264 format data from the socket.
test_ffmpeg.c
#include <stdio.h>
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libavfilter/avfilter.h"
#include "libavutil/mathematics.h"
#include "libavutil/time.h"
typedef long long int64;
int main(void)
{
AVOutputFormat *ofmt = NULL;
AVFormatContext *ifmt_ctx = NULL, *ofmt_ctx = NULL;
AVPacket pkt;
const char *in_filename, *out_filename;
int ret, i;
int videoindex = -1;
int frame_index = 0;
int64 start_time = 0;
in_filename = "./test.h264";
out_filename = "rtmp://192.168.1.108/mytv/01";
#if 0
av_register_all();
#endif
avformat_network_init();
if ((ret == avformat_open_input(&ifmt_ctx, in_filename, 0, 0)) < 0)
{
printf("Could not open input file.\n");
goto end;
}
if ((ret == avformat_find_stream_info(ifmt_ctx, 0)) < 0)
{
printf("Failed to retrieve input stream information!\n");
goto end;
}
for (i = 0; i < ifmt_ctx->nb_streams; i++)
{
if (ifmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
{
videoindex = i;
break;
}
}
av_dump_format(ifmt_ctx, 0, in_filename, 0);
avformat_alloc_output_context2(&ofmt_ctx, NULL, "flv", out_filename);
if (!ofmt_ctx)
{
printf("Could not create output context!\n");
ret = AVERROR_UNKNOWN;
goto end;
}
ofmt = ofmt_ctx->oformat;
for (i = 0;i < ifmt_ctx->nb_streams; i++)
{
AVStream *in_stream = ifmt_ctx->streams[i];
AVStream *out_stream = avformat_new_stream(ofmt_ctx, in_stream->codec->codec);
// AVStream *out_stream = avformat_new_stream(ofmt_ctx, NULL);
if (!out_stream)
{
printf("Failed allocating output stream!\n");
ret = AVERROR_UNKNOWN;
goto end;
}
#if 0
ret = avcodec_copy_context(out_stream->codecpar, in_stream->codecpar);
#endif
ret = avcodec_parameters_copy(out_stream->codecpar, in_stream->codecpar);
if (ret < 0)
{
printf("Failed to copy context from input to output stream codec context!\n");
goto end;
}
out_stream->codecpar->codec_tag = 0;
#if 0
if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
{
out_stream->codec->flags | AV_CODEC_FLAG_GLOBAL_HEADER;
}
#endif
}
av_dump_format(ofmt_ctx, 0, out_filename, 1);
#if 0
if (!(ofmt->flags & AVFMT_NOFILE))
#endif
{
ret = avio_open(&ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE);
if (ret < 0)
{
printf("Could not open output URL '%s'", out_filename);
goto end;
}
}
ret = avformat_write_header(ofmt_ctx, NULL);
if (ret < 0)
{
printf("Error occurred when opening output URL!\n");
}
start_time = av_gettime();
while (1)
{
AVStream *in_stream, *out_stream;
ret = av_read_frame(ifmt_ctx, &pkt);
if (ret < 0)
{
break;
}
if (pkt.pts == AV_NOPTS_VALUE)
{
AVRational time_base1 = ifmt_ctx->streams[videoindex]->time_base;
int64 calc_duration = (double)AV_TIME_BASE/av_q2d(ifmt_ctx->streams[videoindex]-
>r_frame_rate);
pkt.pts = (double)(frame_index*calc_duration)/(double)
(av_q2d(time_base1)*AV_TIME_BASE);
pkt.dts = pkt.pts;
pkt.duration = (double)calc_duration/(double)(av_q2d(time_base1)*AV_TIME_BASE);
}
if (pkt.stream_index == videoindex)
{
AVRational time_base = ifmt_ctx->streams[videoindex]->time_base;
AVRational time_base_q = {1, AV_TIME_BASE};
int64 pts_time = av_rescale_q(pkt.dts, time_base, time_base_q);
int64 now_time = av_gettime() - start_time;
if (pts_time > now_time)
{
av_usleep(pts_time - now_time);
}
}
in_stream = ifmt_ctx->streams[pkt.stream_index];
out_stream = ofmt_ctx->streams[pkt.stream_index];
pkt.pts = av_rescale_q_rnd(pkt.pts, in_stream->time_base, out_stream->time_base, (enum
AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));
pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->time_base, out_stream->time_base, (enum
AVRounding)(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;
if(pkt.stream_index == videoindex)
{
printf("Send %8d video frames to output URL\n",frame_index);
frame_index++;
}
ret = av_interleaved_write_frame(ofmt_ctx, &pkt);
// ret = av_write_frame(ofmt_ctx, &pkt);
if (ret < 0)
{
printf( "Error muxing packet\n");
break;
}
// av_free_packet(&pkt);
#if 0
av_packet_unref(&pkt);
av_write_trailer(ofmt_ctx);
#endif
}
end:
avformat_close_input(&ifmt_ctx);
if (ofmt_ctx && !(ofmt->flags & AVFMT_NOFILE))
{
avio_close(ofmt_ctx->pb);
}
avformat_free_context(ofmt_ctx);
if (ret < 0 && ret != AVERROR_EOF)
{
printf( "Error occurred.\n");
return -1;
}
return 0;
}
received_video.c
VOID *ReceivedVideoFunction(VOID *arg)
{
INT32 receivedVideoSocket = -1;
struct sockaddr_in6 receivedVideoAddr;
INT32 ret = 0;
UCHAR recvBuf[RCV_BUFF_LEN];
struct sockaddr_in6 clientAddr;
socklen_t clientAddrLen;
INT32 recvCount = -1;
INT32 tmpLN = 0;
INT32 tmpSD = 0;
INT32 i = 0;
unsigned int ii = 0;
unsigned short lastSN = 0, dropNum = 0, currentSN = 0, lastPrintSN = 0, dorpNumfromlastprint
= 0;
struct timeval lastPrintTime, currentTime;
memset(&lastPrintTime, 0, sizeof(struct timeval));
memset(¤tTime, 0, sizeof(struct timeval));
receivedVideoSocket = socket(AF_INET6, SOCK_DGRAM, 0);
if(receivedVideoSocket < 0)
{
printf("error : failed to create a received video socket !\n");
exit(-1);
}
ForwardVideoSocket = socket(AF_INET, SOCK_DGRAM, 0);
if(ForwardVideoSocket < 0)
{
printf("error : failed to create a forward video socket !\n");
exit(-1);
}
memset(&receivedVideoAddr, 0, sizeof(receivedVideoAddr));
receivedVideoAddr.sin6_family = AF_INET6;
receivedVideoAddr.sin6_port = htons(RCV_VIDEO_PORT);
inet_pton(AF_INET6, EC_CONTAINER_IPV6, &receivedVideoAddr.sin6_addr);
ret = bind(receivedVideoSocket, (struct sockaddr*)&receivedVideoAddr,
sizeof(receivedVideoAddr));
if(ret < 0)
{
printf("(%s error) failed to bind the received video socket !\n", __FUNCTION__);
exit(-1);
}
while(1)
{
memset(recvBuf, 0, RCV_BUFF_LEN);
clientAddrLen = sizeof(clientAddr);
recvCount = recvfrom(receivedVideoSocket, recvBuf, RCV_BUFF_LEN, 0, (struct
sockaddr*)&clientAddr, (socklen_t*)&clientAddrLen);
if(recvCount <= 0)
{
//printf("test\n");
usleep(100);
continue;
}
else
{
//--------------------------------------------------------------
//Here I want to push data to rtmp server, how to modify my code?
//--------------------------------------------------------------
}
}
}
来源:https://stackoverflow.com/questions/65355580/how-to-push-the-h-264-format-data-received-from-socket-to-rtmp-server