/*! \brief read a frame from webcam or X11 through grabber_read(), * display it, then encode and split it. * Return a list of ast_frame representing the video fragments. * The head pointer is returned by the function, the tail pointer * is returned as an argument. */ static struct ast_frame *get_video_frames(struct video_desc *env, struct ast_frame **tail) { struct video_out_desc *v = &env->out; struct ast_frame *dummy; struct fbuf_t *loc_src = grabber_read(v); if (!loc_src) return NULL; /* can happen, e.g. we are reading too early */ if (tail == NULL) tail = &dummy; *tail = NULL; /* Scale the video for the encoder, then use it for local rendering * so we will see the same as the remote party. */ my_scale(loc_src, NULL, &env->enc_in, NULL); show_frame(env, WIN_LOCAL); if (!v->sendvideo) return NULL; if (v->enc_out.data == NULL) { static volatile int a = 0; if (a++ < 2) ast_log(LOG_WARNING, "fail, no encoder output buffer\n"); return NULL; } v->enc->enc_run(v); return v->enc->enc_encap(&v->enc_out, v->mtu, tail); }
/*! \brief refreshes the buffers of all the device by calling the * grabber_read on each device in the device table. * it encodes the primary source buffer, if the picture in picture mode is * enabled it encodes (in the buffer to split) the secondary source buffer too. * The encoded buffer is splitted to build the local and the remote view. * Return a list of ast_frame representing the video fragments. * The head pointer is returned by the function, the tail pointer * is returned as an argument. * * \param env = video environment descriptor * \param tail = tail ponter (pratically a return value) */ static struct ast_frame *get_video_frames(struct video_desc *env, struct ast_frame **tail) { struct video_out_desc *v = &env->out; struct ast_frame *dummy; struct fbuf_t *loc_src_primary = NULL, *p_read; int i; /* if no device was found in the config file */ if (!env->out.device_num) return NULL; /* every time this function is called we refresh the buffers of every device, updating the private device buffer in the device table */ for (i = 0; i < env->out.device_num; i++) { p_read = grabber_read(&env->out.devices[i], env->out.fps); /* it is used only if different from NULL, we mantain last good buffer otherwise */ if (p_read) env->out.devices[i].dev_buf = p_read; } /* select the primary device buffer as the one to encode */ loc_src_primary = env->out.devices[env->out.device_primary].dev_buf; /* loc_src_primary can be NULL if the device has been turned off during execution of it is read too early */ if (loc_src_primary) { /* Scale the video for the encoder, then use it for local rendering so we will see the same as the remote party */ my_scale(loc_src_primary, NULL, &env->enc_in, NULL); } if (env->out.picture_in_picture) { /* the picture in picture mode is enabled */ struct fbuf_t *loc_src_secondary; /* reads from the secondary source */ loc_src_secondary = env->out.devices[env->out.device_secondary].dev_buf; if (loc_src_secondary) { env->enc_in.win_x = env->out.pip_x; env->enc_in.win_y = env->out.pip_y; env->enc_in.win_w = env->enc_in.w/3; env->enc_in.win_h = env->enc_in.h/3; /* scales to the correct geometry and inserts in the enc_in buffer the picture in picture */ my_scale(loc_src_secondary, NULL, &env->enc_in, NULL); /* returns to normal parameters (not picture in picture) */ env->enc_in.win_x = 0; env->enc_in.win_y = 0; env->enc_in.win_w = 0; env->enc_in.win_h = 0; } else { /* loc_src_secondary can be NULL if the device has been turned off during execution of it is read too early */ env->out.picture_in_picture = 0; /* disable picture in picture */ } } show_frame(env, WIN_LOCAL); /* local rendering */ for (i = 0; i < env->out.device_num; i++) show_frame(env, i+WIN_SRC1); /* rendering of every source device in thumbnails */ if (tail == NULL) tail = &dummy; *tail = NULL; /* if no reason for encoding, do not encode */ if (!env->owner || !loc_src_primary || !v->sendvideo) return NULL; if (v->enc_out.data == NULL) { static volatile int a = 0; if (a++ < 2) ast_log(LOG_WARNING, "fail, no encoder output buffer\n"); return NULL; } v->enc->enc_run(v); return v->enc->enc_encap(&v->enc_out, v->mtu, tail); }