Add multithreaded FFmpeg benchmark receive code

This commit is contained in:
Aaro Altonen 2020-04-14 11:14:01 +03:00
parent e8d44bf7d6
commit 4050ef0bcb
10 changed files with 164 additions and 16 deletions

View File

@ -16,8 +16,12 @@ ffmpeg_sender:
$(CXX) $(CXXFLAGS) -o ffmpeg/sender ffmpeg/sender.cc util/util.cc -lkvazaar `pkg-config --libs libavformat` \
-Wno-unused -Wno-deprecated-declarations -Wno-unused-result
ffmpeg_receiver:
$(CXX) $(CXXFLAGS) -o ffmpeg/receiver ffmpeg/receiver.cc util/util.cc -lkvazaar `pkg-config --libs libavformat` \
-Wno-unused -Wno-deprecated-declarations -Wno-unused-result
clean:
rm -f kvzrtp/receiver kvzrtp/sender ffmpeg/sender
rm -f kvzrtp/receiver kvzrtp/sender ffmpeg/sender ffmpeg/receiver
# jrtp:
# $(CXX) $(CXXFLAGS) -o main_jrtp jrtp.cc ../util/util.cc -lkvazaar -ljrtp -lpthread

View File

@ -1,6 +1,3 @@
#include <stdio.h>
#include <chrono>
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
@ -8,11 +5,24 @@ extern "C" {
#include <libswscale/swscale.h>
}
int main(int argc, char **argv)
#include <atomic>
#include <cstdio>
#include <chrono>
#include <thread>
struct thread_info {
size_t pkts;
size_t bytes;
std::chrono::high_resolution_clock::time_point start;
} *thread_info;
std::atomic<int> nready(0);
void thread_func(int thread_num)
{
AVFormatContext* format_ctx = avformat_alloc_context();
AVCodecContext* codec_ctx = NULL;
int video_stream_index;
AVFormatContext *format_ctx = avformat_alloc_context();
AVCodecContext *codec_ctx = NULL;
int video_stream_index = 0;
/* register everything */
av_register_all();
@ -23,38 +33,108 @@ int main(int argc, char **argv)
av_dict_set(&d, "protocol_whitelist", "file,udp,rtp", 0);
char buf[256];
/* input buffer size */
snprintf(buf, sizeof(buf), "%d", 40 * 1024 * 1024);
av_dict_set(&d, "buffer_size", buf, 0);
av_dict_set(&d, "buffer_size", buf, 32);
if (avformat_open_input(&format_ctx, "../../examples/full/sdp/hevc.sdp", NULL, &d))
return EXIT_FAILURE;
/* avioflags flags (input/output)
*
* Possible values:
* direct
* Reduce buffering. */
snprintf(buf, sizeof(buf), "direct");
av_dict_set(&d, "avioflags", buf, 32);
if (avformat_find_stream_info(format_ctx, NULL) < 0)
return EXIT_FAILURE;
/* Reduce the latency introduced by buffering during initial input streams analysis. */
av_dict_set(&d, "nobuffer", NULL, 32);
/* Set probing size in bytes, i.e. the size of the data to analyze to get stream information.
*
* A higher value will enable detecting more information in case it is dispersed into the stream,
* but will increase latency. Must be an integer not lesser than 32. It is 5000000 by default. */
snprintf(buf, sizeof(buf), "%d", 256);
av_dict_set(&d, "probesize", buf, 32);
/* Set number of frames used to probe fps. */
snprintf(buf, sizeof(buf), "%d", 2);
av_dict_set(&d, "fpsprobesize", buf, 32);
snprintf(buf, sizeof(buf), "ffmpeg/sdp/hevc_%d.sdp", thread_num / 2);
if (avformat_open_input(&format_ctx, buf, NULL, &d)) {
fprintf(stderr, "failed to open input file\n");
nready++;
return;
}
if (avformat_find_stream_info(format_ctx, NULL) < 0) {
fprintf(stderr, "failed to find stream info!\n");
nready++;
return;
}
//search video stream
for (size_t i = 0; i < format_ctx->nb_streams; i++) {
if (format_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
video_stream_index = i;
}
size_t cnt = 0;
size_t pkts = 0;
size_t size = 0;
AVPacket packet;
av_init_packet(&packet);
auto start = std::chrono::high_resolution_clock::now();
/* start reading packets from stream */
av_read_play(format_ctx);
while (av_read_frame(format_ctx, &packet) >= 0) {
if (packet.stream_index == video_stream_index) {
size += packet.size;
} else {
fprintf(stderr, "unknown format!\n");
}
pkts++;
av_free_packet(&packet);
av_init_packet(&packet);
if (++pkts == 597)
break;
}
if (pkts == 597) {
fprintf(stderr, "%zu %zu\n", size,
std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::high_resolution_clock::now() - start
).count()
);
} else {
fprintf(stderr, "discard %zu %zu\n", size,
std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::high_resolution_clock::now() - start
).count()
);
}
av_read_pause(format_ctx);
return 0;
nready++;
}
int main(int argc, char **argv)
{
if (argc != 2) {
fprintf(stderr, "usage: ./%s <number of threads>\n", __FILE__);
return -1;
}
int nthreads = atoi(argv[1]);
thread_info = (struct thread_info *)calloc(nthreads, sizeof(*thread_info));
for (int i = 0; i < nthreads; ++i)
new std::thread(thread_func, i * 2);
while (nready.load() != nthreads)
std::this_thread::sleep_for(std::chrono::milliseconds(20));
}

View File

@ -0,0 +1,8 @@
v=0
o=user 0 0 IN IP4 10.21.25.200
s=No Name
c=IN IP4 10.21.25.200
t=0 0
m=video 8888 RTP/AVP 96
a=rtpmap:96 H265/90000
a=recvonly

View File

@ -0,0 +1,8 @@
v=0
o=user 0 0 IN IP4 10.21.25.200
s=No Name
c=IN IP4 10.21.25.200
t=0 0
m=video 8890 RTP/AVP 96
a=rtpmap:96 H265/90000
a=recvonly

View File

@ -0,0 +1,8 @@
v=0
o=user 0 0 IN IP4 10.21.25.200
s=No Name
c=IN IP4 10.21.25.200
t=0 0
m=video 8892 RTP/AVP 96
a=rtpmap:96 H265/90000
a=recvonly

View File

@ -0,0 +1,8 @@
v=0
o=user 0 0 IN IP4 10.21.25.200
s=No Name
c=IN IP4 10.21.25.200
t=0 0
m=video 8894 RTP/AVP 96
a=rtpmap:96 H265/90000
a=recvonly

View File

@ -0,0 +1,8 @@
v=0
o=user 0 0 IN IP4 10.21.25.200
s=No Name
c=IN IP4 10.21.25.200
t=0 0
m=video 8896 RTP/AVP 96
a=rtpmap:96 H265/90000
a=recvonly

View File

@ -0,0 +1,8 @@
v=0
o=user 0 0 IN IP4 10.21.25.200
s=No Name
c=IN IP4 10.21.25.200
t=0 0
m=video 8898 RTP/AVP 96
a=rtpmap:96 H265/90000
a=recvonly

View File

@ -0,0 +1,8 @@
v=0
o=user 0 0 IN IP4 10.21.25.200
s=No Name
c=IN IP4 10.21.25.200
t=0 0
m=video 8900 RTP/AVP 96
a=rtpmap:96 H265/90000
a=recvonly

View File

@ -0,0 +1,8 @@
v=0
o=user 0 0 IN IP4 10.21.25.200
s=No Name
c=IN IP4 10.21.25.200
t=0 0
m=video 8902 RTP/AVP 96
a=rtpmap:96 H265/90000
a=recvonly