Commit e5235883 authored by Simon Morlat's avatar Simon Morlat
Browse files

allow to configure framerate, get captured and sent framerate

parent fa57d5e0
......@@ -572,6 +572,7 @@ struct _VideoStream
MSFilter *local_jpegwriter;
MSVideoSize sent_vsize;
MSVideoSize preview_vsize;
float fps;
int corner; /*for selfview*/
VideoStreamRenderCallback rendercb;
void *render_pointer;
......@@ -653,6 +654,20 @@ MS2_PUBLIC MSVideoSize video_stream_get_sent_video_size(const VideoStream *strea
*/
MS2_PUBLIC MSVideoSize video_stream_get_received_video_size(const VideoStream *stream);
/**
* Gets the framerate of the video that is sent.
* @param[in] stream The videostream.
* @return The actual framerate, 0 if not available..
*/
MS2_PUBLIC float video_stream_get_sent_framerate(const VideoStream *stream);
/**
* Gets the framerate of the video that is received.
* @param[in] stream The videostream.
* @return The received framerate or 0 if not available.
*/
MS2_PUBLIC float video_stream_get_received_framerate(const VideoStream *stream);
/**
* Returns the name of the video display filter on the current platform.
**/
......@@ -729,6 +744,13 @@ MS2_PUBLIC void video_stream_decoding_error_reported(VideoStream *stream);
**/
MS2_PUBLIC void video_stream_set_preview_size(VideoStream *stream, MSVideoSize vsize);
/**
* Force a resolution for the preview.
* @param[in] stream The VideoStream object.
* @param[in] fps the frame rate in frame/seconds. A value of zero means "use encoder default value".
**/
MS2_PUBLIC void video_stream_set_fps(VideoStream *stream, float fps);
/**
* Link the audio stream with an existing video stream.
* This is necessary to enable recording of audio & video into a multimedia file.
......@@ -748,10 +770,11 @@ MS2_PUBLIC void audio_stream_unlink_video(AudioStream *stream, VideoStream *vide
typedef VideoStream VideoPreview;
MS2_PUBLIC VideoPreview * video_preview_new();
#define video_preview_set_size(p,s) video_stream_set_sent_video_size(p,s)
#define video_preview_set_size(p,s) video_stream_set_sent_video_size(p,s)
#define video_preview_set_display_filter_name(p,dt) video_stream_set_display_filter_name(p,dt)
#define video_preview_set_native_window_id(p,id) video_stream_set_native_preview_window_id (p,id)
#define video_preview_get_native_window_id(p) video_stream_get_native_preview_window_id (p)
#define video_preview_set_native_window_id(p,id) video_stream_set_native_preview_window_id(p,id)
#define video_preview_get_native_window_id(p) video_stream_get_native_preview_window_id(p)
#define video_preview_set_fps(p,fps) video_stream_set_fps((VideoStream*)p,fps)
MS2_PUBLIC void video_preview_start(VideoPreview *stream, MSWebCam *device);
MS2_PUBLIC void video_preview_stop(VideoPreview *stream);
......
......@@ -356,9 +356,15 @@ struct _MSAverageFPS {
const char* context;
};
typedef struct _MSAverageFPS MSAverageFPS;
MS2_PUBLIC void ms_video_init_average_fps(MSAverageFPS* afps, const char* context);
MS2_PUBLIC void ms_average_fps_init(MSAverageFPS* afps, const char* context);
MS2_PUBLIC bool_t ms_average_fps_update(MSAverageFPS* afps, uint32_t current_time);
MS2_PUBLIC float ms_average_fps_get(const MSAverageFPS* afps);
/*deprecated: for compatibility with plugin*/
MS2_PUBLIC void ms_video_init_average_fps(MSAverageFPS* afps, const char* ctx);
MS2_PUBLIC bool_t ms_video_update_average_fps(MSAverageFPS* afps, uint32_t current_time);
/**
* Find the best video configuration from a list of configurations according to a given bitrate limit.
* @param[in] vconf_list The list of video configurations to choose from.
......
......@@ -84,8 +84,7 @@ typedef struct V4l2State{
int frame_max;
float fps;
unsigned int start_time;
unsigned int last_frame_time;
float mean_inter_frame;
MSAverageFPS avgfps;
int th_frame_count;
int queued;
bool_t configured;
......@@ -577,7 +576,7 @@ static void msv4l2_preprocess(MSFilter *f){
s->thread_run=TRUE;
ms_thread_create(&s->thread,NULL,msv4l2_thread,s);
s->th_frame_count=-1;
s->mean_inter_frame=0;
ms_average_fps_init(&s->avgfps,"V4L2 capture");
}
static void msv4l2_process(MSFilter *f){
......@@ -611,20 +610,9 @@ static void msv4l2_process(MSFilter *f){
mblk_set_timestamp_info(om,timestamp);
mblk_set_marker_info(om,TRUE);
ms_queue_put(f->outputs[0],om);
if (s->last_frame_time!=-1){
float frame_interval=(float)(curtime-s->last_frame_time)/1000.0;
if (s->mean_inter_frame==0){
s->mean_inter_frame=frame_interval;
}else{
s->mean_inter_frame=(0.8*s->mean_inter_frame)+(0.2*frame_interval);
}
}
s->last_frame_time=curtime;
ms_average_fps_update(&s->avgfps,f->ticker->time);
}
s->th_frame_count++;
if (s->th_frame_count%50==0 && s->mean_inter_frame!=0){
ms_message("Captured mean fps=%f, expected=%f",1/s->mean_inter_frame, s->fps);
}
}
}
......@@ -688,11 +676,20 @@ static int msv4l2_set_devfile(MSFilter *f, void *arg){
return 0;
}
static int msv4l2_get_fps(MSFilter *f, void *arg){
V4l2State *s=(V4l2State*)f->data;
if (f->ticker){
*(float*)arg=ms_average_fps_get(&s->avgfps);
}else *(float*)arg=s->fps;
return 0;
}
static MSFilterMethod msv4l2_methods[]={
{ MS_FILTER_SET_FPS , msv4l2_set_fps },
{ MS_FILTER_SET_VIDEO_SIZE, msv4l2_set_vsize },
{ MS_FILTER_GET_VIDEO_SIZE, msv4l2_get_vsize },
{ MS_FILTER_GET_PIX_FMT , msv4l2_get_pixfmt },
{ MS_FILTER_GET_FPS , msv4l2_get_fps },
{ 0 , NULL }
};
......
......@@ -43,9 +43,10 @@ typedef struct DecState{
enum PixelFormat output_pix_fmt;
uint8_t dci[512];
int dci_size;
MSAverageFPS fps;
AVFrame* orig;
bool_t snow_initialized;
bool_t first_image_decoded;
AVFrame* orig;
}DecState;
......@@ -140,6 +141,7 @@ static void dec_preprocess(MSFilter *f){
int error;
s->first_image_decoded = FALSE;
ms_average_fps_init(&s->fps, "Video decoder: FPS: %f");
if (s->av_context.codec==NULL){
/* we must know picture size before initializing snow decoder*/
#if HAVE_AVCODEC_SNOW
......@@ -700,6 +702,7 @@ static void dec_process_frame(MSFilter *f, mblk_t *inm){
}
if (got_picture) {
mblk_t *om = get_as_yuvmsg(f,s,s->orig);
ms_average_fps_update(&s->fps, f->ticker->time);
if (om!=NULL)
ms_queue_put(f->outputs[0],om);
......@@ -741,11 +744,18 @@ static int dec_get_vsize(MSFilter *f, void *data) {
return 0;
}
static int dec_get_fps(MSFilter *f, void *data){
DecState *s = (DecState *)f->data;
*(float*)data=ms_average_fps_get(&s->fps);
return 0;
}
static MSFilterMethod methods[]={
{ MS_FILTER_ADD_FMTP , dec_add_fmtp },
{ MS_VIDEO_DECODER_RESET_FIRST_IMAGE_NOTIFICATION, reset_first_image },
{ MS_FILTER_GET_VIDEO_SIZE, dec_get_vsize },
{ MS_FILTER_GET_FPS, dec_get_fps },
{ 0 , NULL }
};
......
......@@ -759,7 +759,7 @@ static void dec_init(MSFilter *f) {
s->avpf_enabled = FALSE;
s->freeze_on_error = TRUE;
f->data = s;
ms_video_init_average_fps(&s->fps, "VP8 decoder: FPS: %f");
ms_average_fps_init(&s->fps, "VP8 decoder: FPS: %f");
}
static void dec_preprocess(MSFilter* f) {
......@@ -850,7 +850,7 @@ static void dec_process(MSFilter *f) {
}
ms_queue_put(f->outputs[0], dupmsg(s->yuv_msg));
if (ms_video_update_average_fps(&s->fps, f->ticker->time)) {
if (ms_average_fps_update(&s->fps, f->ticker->time)) {
ms_message("VP8 decoder: Frame size: %dx%d", s->yuv_width, s->yuv_height);
}
if (!s->first_image_decoded) {
......@@ -898,11 +898,18 @@ static int dec_get_vsize(MSFilter *f, void *data) {
return 0;
}
static int dec_get_fps(MSFilter *f, void *data){
DecState *s = (DecState *)f->data;
*(float*)data= ms_average_fps_get(&s->fps);
return 0;
}
static MSFilterMethod dec_methods[] = {
{ MS_VIDEO_DECODER_RESET_FIRST_IMAGE_NOTIFICATION, dec_reset_first_image },
{ MS_VIDEO_DECODER_ENABLE_AVPF, dec_enable_avpf },
{ MS_VIDEO_DECODER_FREEZE_ON_ERROR, dec_freeze_on_error },
{ MS_FILTER_GET_VIDEO_SIZE, dec_get_vsize },
{ MS_FILTER_GET_FPS, dec_get_fps },
{ 0, NULL }
};
......
......@@ -781,7 +781,7 @@ bool_t ms_video_capture_new_frame(MSFrameRateController* ctrl, uint32_t current_
}
}
void ms_video_init_average_fps(MSAverageFPS* afps, const char* ctx) {
void ms_average_fps_init(MSAverageFPS* afps, const char* ctx) {
afps->last_frame_time = -1;
afps->last_print_time = -1;
afps->mean_inter_frame = 0;
......@@ -791,7 +791,12 @@ void ms_video_init_average_fps(MSAverageFPS* afps, const char* ctx) {
}
}
bool_t ms_video_update_average_fps(MSAverageFPS* afps, uint32_t current_time) {
/*compatibility, deprecated*/
void ms_video_init_average_fps(MSAverageFPS* afps, const char* ctx){
ms_average_fps_init(afps,ctx);
}
bool_t ms_average_fps_update(MSAverageFPS* afps, uint32_t current_time) {
if (afps->last_frame_time!=-1){
float frame_interval=(float)(current_time - afps->last_frame_time)/1000.0;
if (afps->mean_inter_frame==0){
......@@ -812,6 +817,15 @@ bool_t ms_video_update_average_fps(MSAverageFPS* afps, uint32_t current_time) {
return FALSE;
}
/*compatibility, deprecated*/
bool_t ms_video_update_average_fps(MSAverageFPS* afps, uint32_t current_time){
return ms_average_fps_update(afps,current_time);
}
float ms_average_fps_get(const MSAverageFPS* afps){
return afps->mean_inter_frame!=0 ? 1.0/afps->mean_inter_frame : 0;
}
MSVideoConfiguration ms_video_find_best_configuration_for_bitrate(const MSVideoConfiguration *vconf_list, int bitrate) {
const MSVideoConfiguration *current_vconf = vconf_list;
const MSVideoConfiguration *closer_to_best_vconf = NULL;
......
......@@ -212,6 +212,7 @@ VideoStream *video_stream_new_with_sessions(const MSMediaStreamSessions *session
stream->ms.ice_check_list=NULL;
rtp_session_register_event_queue(stream->ms.sessions.rtp_session,stream->ms.evq);
MS_VIDEO_SIZE_ASSIGN(stream->sent_vsize, CIF);
stream->fps=0;
stream->dir=VideoStreamSendRecv;
stream->display_filter_auto_rotate_enabled=0;
stream->freeze_on_error = FALSE;
......@@ -240,6 +241,10 @@ void video_stream_set_preview_size(VideoStream *stream, MSVideoSize vsize){
stream->preview_vsize=vsize;
}
void video_stream_set_fps(VideoStream *stream, float fps){
stream->fps=fps;
}
MSVideoSize video_stream_get_sent_video_size(const VideoStream *stream) {
MSVideoSize vsize;
MS_VIDEO_SIZE_ASSIGN(vsize, UNKNOWN);
......@@ -258,6 +263,23 @@ MSVideoSize video_stream_get_received_video_size(const VideoStream *stream) {
return vsize;
}
float video_stream_get_sent_framerate(const VideoStream *stream){
float fps=0;
if (stream->source){
if (ms_filter_has_method(stream->source, MS_FILTER_GET_FPS))
ms_filter_call_method(stream->source,MS_FILTER_GET_FPS,&fps);
}
return fps;
}
float video_stream_get_received_framerate(const VideoStream *stream){
float fps=0;
if (stream->ms.decoder != NULL && ms_filter_has_method(stream->ms.decoder, MS_FILTER_GET_FPS)) {
ms_filter_call_method(stream->ms.decoder, MS_FILTER_GET_FPS, &fps);
}
return fps;
}
void video_stream_set_relay_session_id(VideoStream *stream, const char *id){
ms_filter_call_method(stream->ms.rtpsend, MS_RTP_SEND_SET_RELAY_SESSION_ID,(void*)id);
}
......@@ -369,6 +391,8 @@ static void configure_video_source(VideoStream *stream){
}
ms_filter_call_method(stream->ms.encoder,MS_FILTER_SET_VIDEO_SIZE,&vsize);
ms_filter_call_method(stream->ms.encoder,MS_FILTER_GET_FPS,&fps);
if (stream->fps!=0)
fps=stream->fps;
ms_message("Setting sent vsize=%ix%i, fps=%f",vsize.width,vsize.height,fps);
/* configure the filters */
if (ms_filter_get_id(stream->source)!=MS_STATIC_IMAGE_ID) {
......@@ -968,13 +992,16 @@ VideoPreview * video_preview_new(void){
void video_preview_start(VideoPreview *stream, MSWebCam *device){
MSPixFmt format;
float fps=(float)29.97;
float fps;
int mirroring=1;
int corner=-1;
MSVideoSize disp_size=stream->sent_vsize;
MSVideoSize vsize=disp_size;
const char *displaytype=stream->display_name;
if (stream->fps!=0) fps=stream->fps;
else fps=(float)29.97;
stream->source = ms_web_cam_create_reader(device);
......
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