Ich versuche tatsächlich, Echtzeitbilder über das Netzwerk effizient zu senden. Aus diesem Grund dachte ich, dass das RTP-Protokoll im Video-Streaming eine gute Möglichkeit ist, dies zu erreichen.Schreiben von Bildern in RTP mit ffmpeg
ich dies tatsächlich versucht:
extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavutil/opt.h>
#include <libavutil/channel_layout.h>
#include <libavutil/common.h>
#include <libavutil/imgutils.h>
#include <libavutil/mathematics.h>
#include <libavutil/samplefmt.h>
}
#include <iostream>
#include <unistd.h>
#include <stdio.h>
//Mainly based on https://stackoverflow.com/questions/40825300/ffmpeg-create-rtp-stream
int main()
{
//Init ffmpeg
avcodec_register_all();
av_register_all();
avformat_network_init();
//Init the codec used to encode our given image
AVCodecID codecID = AV_CODEC_ID_MPEG4;
AVCodec* codec;
AVCodecContext* codecCtx;
codec = avcodec_find_encoder(codecID);
codecCtx = avcodec_alloc_context3(codec);
//codecCtx->bit_rate = 400000;
codecCtx->width = 352;
codecCtx->height = 288;
codecCtx->time_base.num = 1;
codecCtx->time_base.den = 25;
codecCtx->gop_size = 25;
codecCtx->max_b_frames = 1;
codecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
codecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
if (codecID == AV_CODEC_ID_H264)
{
av_opt_set(codecCtx->priv_data, "preset", "ultrafast", 0);
av_opt_set(codecCtx->priv_data, "tune", "zerolatency", 0);
}
avcodec_open2(codecCtx, codec, NULL);
//Init the Frame containing our raw data
AVFrame* frame;
frame = av_frame_alloc();
frame->format = codecCtx->pix_fmt;
frame->width = codecCtx->width;
frame->height = codecCtx->height;
av_image_alloc(frame->data, frame->linesize, frame->width, frame->height, codecCtx->pix_fmt, 32);
//Init the format context
AVFormatContext* fmtCtx = avformat_alloc_context();
AVOutputFormat* format = av_guess_format("rtp", NULL, NULL);
avformat_alloc_output_context2(&fmtCtx, format, format->name, "rtp://127.0.0.1:49990");
avio_open(&fmtCtx->pb, fmtCtx->filename, AVIO_FLAG_WRITE);
//Configure the AVStream for the output format context
struct AVStream* stream = avformat_new_stream(fmtCtx, codec);
avcodec_parameters_from_context(stream->codecpar, codecCtx);
stream->time_base.num = 1;
stream->time_base.den = 25;
/* Rewrite the header */
avformat_write_header(fmtCtx, NULL);
/* Write a file for VLC */
char buf[200000];
AVFormatContext *ac[] = { fmtCtx };
av_sdp_create(ac, 1, buf, 20000);
printf("sdp:\n%s\n", buf);
FILE* fsdp = fopen("test.sdp", "w");
fprintf(fsdp, "%s", buf);
fclose(fsdp);
AVPacket pkt;
int j = 0;
for(int i = 0; i < 10000; i++)
{
fflush(stdout);
av_init_packet(&pkt);
pkt.data = NULL; // packet data will be allocated by the encoder
pkt.size = 0;
int R, G, B;
R = G = B = i % 255;
int Y = 0.257 * R + 0.504 * G + 0.098 * B + 16;
int U = -0.148 * R - 0.291 * G + 0.439 * B + 128;
int V = 0.439 * R - 0.368 * G - 0.071 * B + 128;
/* prepare a dummy image */
/* Y */
for (int y = 0; y < codecCtx->height; y++)
for (int x = 0; x < codecCtx->width; x++)
frame->data[0][y * codecCtx->width + x] = Y;
for (int y = 0; y < codecCtx->height/2; y++)
for (int x=0; x < codecCtx->width/2; x++)
{
frame->data[1][y * frame->linesize[1] + x] = U;
frame->data[2][y * frame->linesize[2] + x] = V;
}
/* Which frame is it ? */
frame->pts = i;
/* Send the frame to the codec */
avcodec_send_frame(codecCtx, frame);
/* Use the data in the codec to the AVPacket */
switch(avcodec_receive_packet(codecCtx, &pkt))
{
case AVERROR_EOF:
printf("Stream EOF\n");
break;
case AVERROR(EAGAIN):
printf("Stream EAGAIN\n");
break;
default:
printf("Write frame %3d (size=%5d)\n", j++, pkt.size);
/* Write the data on the packet to the output format */
av_interleaved_write_frame(fmtCtx, &pkt);
/* Reset the packet */
av_packet_unref(&pkt);
break;
}
usleep(1e6/25);
}
// end
avcodec_send_frame(codecCtx, NULL);
//Free everything
av_free(codecCtx);
av_free(fmtCtx);
return 0;
}
Und ich kann mit VLC ein Bild zu sehen, aber nicht ein Video (ich habe es reaload ein anderes Bild in Graustufen zu sehen).
Weiß jemand, warum vlc mein Video nicht gut spielen? Vielen Dank !