Add multithreaded FFmpeg benchmark receive code
This commit is contained in:
parent
e8d44bf7d6
commit
4050ef0bcb
|
|
@ -16,8 +16,12 @@ ffmpeg_sender:
|
||||||
$(CXX) $(CXXFLAGS) -o ffmpeg/sender ffmpeg/sender.cc util/util.cc -lkvazaar `pkg-config --libs libavformat` \
|
$(CXX) $(CXXFLAGS) -o ffmpeg/sender ffmpeg/sender.cc util/util.cc -lkvazaar `pkg-config --libs libavformat` \
|
||||||
-Wno-unused -Wno-deprecated-declarations -Wno-unused-result
|
-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:
|
clean:
|
||||||
rm -f kvzrtp/receiver kvzrtp/sender ffmpeg/sender
|
rm -f kvzrtp/receiver kvzrtp/sender ffmpeg/sender ffmpeg/receiver
|
||||||
|
|
||||||
# jrtp:
|
# jrtp:
|
||||||
# $(CXX) $(CXXFLAGS) -o main_jrtp jrtp.cc ../util/util.cc -lkvazaar -ljrtp -lpthread
|
# $(CXX) $(CXXFLAGS) -o main_jrtp jrtp.cc ../util/util.cc -lkvazaar -ljrtp -lpthread
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,3 @@
|
||||||
#include <stdio.h>
|
|
||||||
#include <chrono>
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <libavcodec/avcodec.h>
|
#include <libavcodec/avcodec.h>
|
||||||
#include <libavformat/avformat.h>
|
#include <libavformat/avformat.h>
|
||||||
|
|
@ -8,11 +5,24 @@ extern "C" {
|
||||||
#include <libswscale/swscale.h>
|
#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();
|
AVFormatContext *format_ctx = avformat_alloc_context();
|
||||||
AVCodecContext* codec_ctx = NULL;
|
AVCodecContext *codec_ctx = NULL;
|
||||||
int video_stream_index;
|
int video_stream_index = 0;
|
||||||
|
|
||||||
/* register everything */
|
/* register everything */
|
||||||
av_register_all();
|
av_register_all();
|
||||||
|
|
@ -23,38 +33,108 @@ int main(int argc, char **argv)
|
||||||
av_dict_set(&d, "protocol_whitelist", "file,udp,rtp", 0);
|
av_dict_set(&d, "protocol_whitelist", "file,udp,rtp", 0);
|
||||||
|
|
||||||
char buf[256];
|
char buf[256];
|
||||||
|
|
||||||
|
/* input buffer size */
|
||||||
snprintf(buf, sizeof(buf), "%d", 40 * 1024 * 1024);
|
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))
|
/* avioflags flags (input/output)
|
||||||
return EXIT_FAILURE;
|
*
|
||||||
|
* 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)
|
/* Reduce the latency introduced by buffering during initial input streams analysis. */
|
||||||
return EXIT_FAILURE;
|
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++) {
|
for (size_t i = 0; i < format_ctx->nb_streams; i++) {
|
||||||
if (format_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
|
if (format_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
|
||||||
video_stream_index = i;
|
video_stream_index = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t cnt = 0;
|
size_t pkts = 0;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
AVPacket packet;
|
AVPacket packet;
|
||||||
av_init_packet(&packet);
|
av_init_packet(&packet);
|
||||||
|
|
||||||
|
auto start = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
/* start reading packets from stream */
|
/* start reading packets from stream */
|
||||||
av_read_play(format_ctx);
|
av_read_play(format_ctx);
|
||||||
|
|
||||||
while (av_read_frame(format_ctx, &packet) >= 0) {
|
while (av_read_frame(format_ctx, &packet) >= 0) {
|
||||||
if (packet.stream_index == video_stream_index) {
|
if (packet.stream_index == video_stream_index) {
|
||||||
size += packet.size;
|
size += packet.size;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "unknown format!\n");
|
||||||
}
|
}
|
||||||
|
pkts++;
|
||||||
|
|
||||||
av_free_packet(&packet);
|
av_free_packet(&packet);
|
||||||
av_init_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);
|
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));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
Loading…
Reference in New Issue