Commit 798c5bea authored by Simon Morlat's avatar Simon Morlat

add test program "mkvstream" to demonstrate reading/recording from/to mkv files

parent 3e2218dc
......@@ -782,19 +782,25 @@ static void apply_video_preset(VideoStream *stream, PayloadType *pt) {
static void apply_bitrate_limit(VideoStream *stream, PayloadType *pt) {
MSVideoConfiguration *vconf_list = NULL;
ms_message("Limiting bitrate of video encoder to %i bits/s for stream [%p]",pt->normal_bitrate,stream);
if (stream->ms.target_bitrate<=0) {
stream->ms.target_bitrate=pt->normal_bitrate;
ms_message("target bitrate not set for stream [%p] using payload's bitrate is %i",stream,stream->ms.target_bitrate);
}
ms_message("Limiting bitrate of video encoder to %i bits/s for stream [%p]",stream->ms.target_bitrate,stream);
ms_filter_call_method(stream->ms.encoder, MS_VIDEO_ENCODER_GET_CONFIGURATION_LIST, &vconf_list);
if (vconf_list != NULL) {
MSVideoConfiguration vconf = ms_video_find_best_configuration_for_bitrate(vconf_list, pt->normal_bitrate, ms_get_cpu_count());
MSVideoConfiguration vconf = ms_video_find_best_configuration_for_bitrate(vconf_list, stream->ms.target_bitrate, ms_get_cpu_count());
/* Adjust configuration video size to use the user preferred video size if it is lower that the configuration one. */
if ((stream->sent_vsize.height * stream->sent_vsize.width) < (vconf.vsize.height * vconf.vsize.width)) {
vconf.vsize = stream->sent_vsize;
}
ms_filter_call_method(stream->ms.encoder, MS_VIDEO_ENCODER_SET_CONFIGURATION, &vconf);
} else {
ms_filter_call_method(stream->ms.encoder, MS_FILTER_SET_BITRATE, &pt->normal_bitrate);
ms_filter_call_method(stream->ms.encoder, MS_FILTER_SET_BITRATE, &stream->ms.target_bitrate);
}
rtp_session_set_target_upload_bandwidth(stream->ms.sessions.rtp_session, pt->normal_bitrate);
rtp_session_set_target_upload_bandwidth(stream->ms.sessions.rtp_session, stream->ms.target_bitrate);
}
static MSPixFmt mime_type_to_pix_format(const char *mime_type) {
......
......@@ -9,7 +9,7 @@ if MS2_FILTERS
noinst_PROGRAMS+=echo ring bench
if BUILD_VIDEO
noinst_PROGRAMS+=videodisplay test_x11window
noinst_PROGRAMS+=videodisplay test_x11window mkvstream
endif
endif MS2_FILTERS
......@@ -20,6 +20,7 @@ echo_SOURCES=echo.c
ring_SOURCES=ring.c
videodisplay_SOURCES=videodisplay.c
mtudiscover_SOURCES=mtudiscover.c
mkvstream_SOURCES=mkvstream.c
bench_SOURCES=bench.c
test_x11window_SOURCES=test_x11window.c
tones_SOURCES=tones.c
......
/*
mediastreamer2 library - modular sound and video processing and streaming
Copyright (C) 2015 Belledonne Communications SARL
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "mediastreamer2/mediastream.h"
#include "mediastreamer2/mseventqueue.h"
#include <signal.h>
static int active = 1;
/*handler called when pressing C-c*/
static void stop_handler(int signum){
active--;
if (active<0) {
ms_error("Brutal exit (%d)\n", active);
exit(-1);
}
}
static void usage(const char *prog){
fprintf(stderr, "Usage:\n%s play <mkv file> <dest_ip> <dest_port>\n"
"%s record <mkv file> local_port\n", prog, prog);
exit(-1);
}
typedef enum {
PLAY_MODE,
RECORD_MODE
}Mode;
/*the payload type number we're using here in the RTP packets sent and received*/
const int payload_type_number = 114;
/*callback function in which we are notified of end of file when playing an mkvfile to rtp*/
static void on_end_of_play(void *user_data, MSFilter *player, unsigned int event_id, void *event_arg){
switch(event_id){
case MS_PLAYER_EOF:
fprintf(stdout, "End of file reached.\n");
/*make the program exit*/
active = 0;
break;
}
}
/*
* This small program starts a video stream to either
* - read an H264 video track from mkv file and stream it out with RTP to specified destination
* - receive H264 RTP packets on a local port and record them into an mkv file
*/
int main(int argc, char *argv[]){
const char *command;
const char *file;
const char *ip;
int port;
VideoStream *stream;
RtpProfile *profile;
PayloadType *pt;
Mode mode;
int local_port = 7778;
MSMediaStreamIO io = MS_MEDIA_STREAM_IO_INITIALIZER;
int err;
/*parse command line arguments*/
if (argc<4) usage(argv[0]);
command = argv[1];
if (strcasecmp(command,"play")==0) mode = PLAY_MODE;
else if (strcasecmp(command, "record")==0) mode = RECORD_MODE;
else usage(argv[0]);
file = argv[2];
if (mode == PLAY_MODE){
ip = argv[3];
if (argc<5) usage(argv[0]);
port = atoi(argv[4]);
}else{
local_port = atoi(argv[3]);
ip = "127.0.0.1"; port = 9990; /*dummy destination address, we won't send anything here anyway*/
}
/*set a signal handler to interrupt the program cleanly*/
signal(SIGINT,stop_handler);
/*initialize mediastreamer2*/
ms_init();
/*create the video stream */
stream = video_stream_new(local_port, local_port+1, FALSE);
/*define its local input and outputs with the MSMediaStreamIO structure*/
if (mode == PLAY_MODE){
io.input.type = MSResourceFile;
io.input.file = file; /*the file we want to stream out via rtp*/
io.output.type = MSResourceFile;
io.output.file = NULL; /*we don't set a record file in PLAY_MODE, we just want the received video stream to be ignored, if something is received*/
}else{
io.input.type = MSResourceFile;
io.input.file = NULL; /*We don't want to send anything via RTP in RECORD_MODE*/
io.output.type = MSResourceFile;
io.output.file = file; /*The file to which we want to record the received video stream*/
}
/*define the RTP profile to use: in this case we just want to use H264 codec*/
profile = rtp_profile_new("My RTP profile");
pt = payload_type_clone(&payload_type_h264);
rtp_profile_set_payload(profile, payload_type_number, pt); /*we assign H264 to payload type number payload_type_number*/
media_stream_set_target_network_bitrate(&stream->ms, 500000); /*set a target IP bitrate in bits/second */
/*start the video stream, given the RtpProfile and "io" definition */
err = video_stream_start_from_io(stream, profile, ip, port, ip, port+1, payload_type_number, &io);
if (err !=0 ){
fprintf(stderr,"Could not start video stream.");
goto end;
}
/*Register an event handler on the player to be notified of end of file*/
ms_filter_add_notify_callback(stream->source, on_end_of_play, NULL, FALSE);
/*program's main loop*/
while (active){
/*handle video stream background activity. This is non blocking*/
video_stream_iterate(stream);
/*process event callbacks*/
ms_event_queue_pump(ms_factory_get_event_queue(ms_factory_get_fallback()));
ms_usleep(50000); /*pause 50ms to avoid busy loop*/
}
end:
/*stop and destroy the video stream object*/
if (stream) video_stream_stop(stream);
/*free the RTP profile and payload type inside*/
if (profile) rtp_profile_destroy(profile);
return err;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment