uint8_t video_packet[1500 + 12];
void *raw_yuyv_data;
switch_image_t *img;
- switch_time_t last_video_ts;
switch_payload_t pt;
uint32_t seq;
int width;
static void vlc_video_unlock_callback(void *data, void *id, void *const *p_pixels)
{
- vlc_video_context_t *context = (vlc_video_context_t *)data;
+ vlc_video_context_t *context = (vlc_video_context_t *) data;
switch_frame_t *frame = context->vid_frame;
- uint32_t flag = 0;
- uint32_t encoded_data_len = 1500;
- switch_time_t now = (switch_time_t)(switch_micro_time_now() / 1000);
- switch_codec_t *codec = switch_core_session_get_video_write_codec(context->session);
- long delta;
switch_assert(id == NULL); /* picture identifier, not needed here */
- switch_assert(codec);
-
- if (now - context->last_video_ts < 60) goto end;
if (!context->img) context->img = switch_img_alloc(NULL, SWITCH_IMG_FMT_I420, context->width, context->height, 0);
- if (!context->img) goto end;
-
- yuyv_to_i420(*p_pixels, context->img->img_data, context->width, context->height);
-
- delta = now - context->last_video_ts;
-
- if (delta > 0) {
- frame->timestamp += delta * 90;
- context->last_video_ts = now;
- }
- //printf("WTF VLC d_w=%d d_h=%d w=%d h=%d\n", context->img->d_w, context->img->d_h, context->img->w, context->img->h);
-
- //context->img->d_w = context->img->w;
- //context->img->d_h = context->img->h;
-
- switch_core_codec_encode_video(codec, context->img, frame->data, &encoded_data_len, &flag);
-
- while(encoded_data_len) {
- //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "encoded: %s [%d] flag=%d ts=%ld\n", codec->implementation->iananame, encoded_data_len, flag, context->last_video_ts);
-
- frame->datalen = encoded_data_len;
- frame->packetlen = frame->datalen + 12;
- frame->m = flag & SFF_MARKER ? 1 : 0;
-
- if (1) {
- /* set correct mark and ts */
- switch_rtp_hdr_t *rtp = (switch_rtp_hdr_t *)frame->packet;
- memset(rtp, 0, 12);
- rtp->version = 2;
- rtp->m = frame->m;
- rtp->ts = htonl(frame->timestamp);
- rtp->ssrc = (uint32_t) ((intptr_t) rtp + (uint32_t) switch_epoch_time_now(NULL));
+ switch_assert(context->img);
- switch_set_flag(frame, SFF_RAW_RTP);
- }
-
- switch_set_flag(frame, SFF_RAW_RTP);
- // switch_set_flag(frame, SFF_PROXY_PACKET);
-
- switch_core_session_write_video_frame(context->session, frame, SWITCH_IO_FLAG_NONE, 0);
-
- encoded_data_len = 1500;
+ yuyv_to_i420(*p_pixels, context->img->img_data, context->width, context->height);
- switch_core_codec_encode_video(codec, NULL, frame->data, &encoded_data_len, &flag);
- }
+ switch_core_session_write_video_image(context->session, frame, context->img, SWITCH_DEFAULT_VIDEO_SIZE, NULL);
-end:
switch_mutex_unlock(context->video_mutex);
}
switch_mutex_unlock(context->video_mutex);
}
+
static void vlc_video_channel_unlock_callback(void *data, void *id, void *const *p_pixels)
{
vlc_video_context_t *context = (vlc_video_context_t *)data;
uint32_t flag = 0;
- uint32_t encoded_data_len = 1500;
- switch_codec_t *codec = switch_core_session_get_video_write_codec(context->session);
switch_frame_t *frame = context->vid_frame;
- switch_time_t now = (switch_time_t)(switch_micro_time_now() / 1000);
- long delta;
switch_assert(id == NULL); /* picture identifier, not needed here */
- switch_assert(codec);
if (!context->img) context->img = switch_img_alloc(NULL, SWITCH_IMG_FMT_I420, context->width, context->height, 0);
- if (!context->img) goto end;
+ switch_assert(context->img);
yuyv_to_i420(*p_pixels, context->img->img_data, context->width, context->height);
- encoded_data_len = 1500;
-
- frame->packet = context->video_packet;
- frame->data = context->video_packet + 12;
- delta = now - context->last_video_ts;
-
- if (delta > 0) {
- frame->timestamp += delta * 90;
- context->last_video_ts = now;
- }
if (context->video_refresh_req > 0) {
flag |= SFF_WAIT_KEY_FRAME;
context->video_refresh_req--;
}
- switch_core_codec_encode_video(codec, context->img, frame->data, &encoded_data_len, &flag);
-
- while(encoded_data_len) {
- // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "encoded: %s [%d] flag=%d ts=%u\n", codec->implementation->iananame, encoded_data_len, flag, context->ts);
-
- frame->datalen = encoded_data_len;
- frame->packetlen = frame->datalen + 12;
- frame->m = flag & SFF_MARKER ? 1 : 0;
-
- if (1) {
- /* set correct mark and ts */
- switch_rtp_hdr_t *rtp = (switch_rtp_hdr_t *)frame->packet;
+ switch_core_session_write_video_image(context->session, frame, context->img, SWITCH_DEFAULT_VIDEO_SIZE, &flag);
- memset(rtp, 0, 12);
- rtp->version = 2;
- rtp->m = frame->m;
- rtp->ts = htonl(frame->timestamp);
- rtp->ssrc = (uint32_t) ((intptr_t) rtp + (uint32_t) switch_epoch_time_now(NULL));
-
- switch_set_flag(frame, SFF_RAW_RTP);
- }
-
- switch_set_flag(frame, SFF_RAW_RTP);
- switch_set_flag(frame, SFF_PROXY_PACKET);
-
- do_buffer_frame(context);
-
- encoded_data_len = 1500;
- switch_core_codec_encode_video(codec, NULL, frame->data, &encoded_data_len, &flag);
- }
-
-end:
switch_mutex_unlock(context->video_mutex);
}
switch_size_t audio_datalen;
+
switch_channel_clear_flag(channel, CF_VIDEO_ECHO);
context = switch_core_session_alloc(session, sizeof(vlc_video_context_t));
static switch_status_t vlc_read_video_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id);
static switch_status_t vlc_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg);
static switch_status_t vlc_kill_channel(switch_core_session_t *session, int sig);
+static switch_status_t vlc_state_change(switch_core_session_t *session);
typedef struct {
switch_core_session_t *session;
/*send_dtmf*/ NULL,
/*receive_message*/ vlc_receive_message,
/*receive_event*/ NULL,
- /*state_change*/ NULL,
+ /*state_change*/ vlc_state_change,
/*read_video_frame*/ vlc_read_video_frame,
/*write_video_frame*/ NULL,
/*state_run*/ NULL
return status;
}
+static switch_status_t vlc_channel_img_callback(switch_core_session_t *session, switch_frame_t *frame, switch_image_t *img, void *user_data)
+{
+ vlc_video_context_t *context = (vlc_video_context_t *) user_data;
+
+ do_buffer_frame(context);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
static switch_status_t channel_on_init(switch_core_session_t *session)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
+ vlc_private_t *tech_pvt = switch_core_session_get_private(session);
switch_channel_set_state(channel, CS_CONSUME_MEDIA);
+ switch_core_session_set_image_write_callback(session, vlc_channel_img_callback, tech_pvt->context);
+
return SWITCH_STATUS_SUCCESS;
}
return SWITCH_STATUS_SUCCESS;
}
+static switch_status_t vlc_state_change(switch_core_session_t *session)
+{
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ switch_channel_state_t state = switch_channel_get_state(channel);
+
+ if (state == CS_HANGUP || state == CS_ROUTING) {
+ switch_core_session_video_reset(session);
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
static switch_status_t vlc_kill_channel(switch_core_session_t *session, int sig)
{
vlc_private_t *tech_pvt = switch_core_session_get_private(session);
#include <switch.h>
#include "private/switch_core_pvt.h"
+SWITCH_DECLARE(void) switch_core_session_set_image_write_callback(switch_core_session_t *session, switch_image_write_callback_t callback, void *user_data)
+{
+ session->image_write_callback = callback;
+ session->image_write_callback_user_data = user_data;
+}
+
+SWITCH_DECLARE(switch_status_t) switch_core_session_write_video_image(switch_core_session_t *session, switch_frame_t *frame,
+ switch_image_t *img, switch_size_t size, uint32_t *flag)
+{
+ uint32_t encoded_data_len = size, lflag = 0, *flagp = flag;
+ switch_codec_t *codec = switch_core_session_get_video_write_codec(session);
+ switch_timer_t *timer;
+
+ switch_assert(session);
+
+ if (!flag) {
+ flagp = &lflag;
+ }
+
+ timer = switch_core_media_get_timer(session, SWITCH_MEDIA_TYPE_VIDEO);
+ switch_assert(timer);
+
+ switch_core_codec_encode_video(codec, img, frame->data, &encoded_data_len, flagp);
+
+ while(encoded_data_len) {
+
+ frame->datalen = encoded_data_len;
+ frame->packetlen = frame->datalen + 12;
+ frame->m = (*flagp & SFF_MARKER) ? 1 : 0;
+ frame->timestamp = timer->samplecount;
+
+ switch_set_flag(frame, SFF_RAW_RTP_PARSE_FRAME);
+
+ switch_core_session_write_video_frame(session, frame, SWITCH_IO_FLAG_NONE, 0);
+
+ if (session->image_write_callback) {
+ session->image_write_callback(session, frame, img, session->image_write_callback_user_data);
+ }
+
+ encoded_data_len = size;
+ switch_core_codec_encode_video(codec, NULL, frame->data, &encoded_data_len, flagp);
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
SWITCH_DECLARE(switch_status_t) switch_core_session_write_video_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags,
int stream_id)
{
switch_rtp_clear_flag(rtp_session, SWITCH_RTP_FLAG_USE_TIMER);
}
} else {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG, "Not using a timer\n");
+ if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
+ if (switch_core_timer_init(&rtp_session->timer, "soft", 1, 90, pool) == SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG, "Starting video timer.\n");
+ }
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG, "Not using a timer\n");
+ }
+
switch_rtp_clear_flag(rtp_session, SWITCH_RTP_FLAG_USE_TIMER);
switch_rtp_clear_flag(rtp_session, SWITCH_RTP_FLAG_NOBLOCK);
}
}
+SWITCH_DECLARE(switch_timer_t *) switch_rtp_get_media_timer(switch_rtp_t *rtp_session)
+{
+ if (rtp_session->timer.timer_interface) {
+ if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
+ switch_core_timer_sync(&rtp_session->timer);
+ }
+ return &rtp_session->timer;
+ }
+
+ return NULL;
+}
+
+
SWITCH_DECLARE(stfu_instance_t *) switch_rtp_get_jitter_buffer(switch_rtp_t *rtp_session)
{
if (!switch_rtp_ready(rtp_session) || !rtp_session->jb) {
}
#endif
- fwd = (rtp_session->flags[SWITCH_RTP_FLAG_RAW_WRITE] && switch_test_flag(frame, SFF_RAW_RTP)) ? 1 : 0;
+ fwd = (rtp_session->flags[SWITCH_RTP_FLAG_RAW_WRITE] &&
+ (switch_test_flag(frame, SFF_RAW_RTP) || switch_test_flag(frame, SFF_RAW_RTP_PARSE_FRAME))) ? 1 : 0;
if (!fwd && !rtp_session->sending_dtmf && !rtp_session->queue_delay &&
rtp_session->flags[SWITCH_RTP_FLAG_RAW_WRITE] && (rtp_session->rtp_bugs & RTP_BUG_GEN_ONE_GEN_ALL)) {
send_msg = frame->packet;
len = frame->packetlen;
ts = 0;
- // Trying this based on http://jira.freeswitch.org/browse/MODSOFIA-90
- //if (frame->codec && frame->codec->agreed_pt == frame->payload) {
send_msg->header.pt = payload;
- //}
+
+ if (switch_test_flag(frame, SFF_RAW_RTP_PARSE_FRAME)) {
+ send_msg->header.version = 2;
+ send_msg->header.m = frame->m;
+ send_msg->header.ts = htonl(frame->timestamp);
+ send_msg->header.ssrc = htonl(rtp_session->ssrc);
+ }
+
} else {
data = frame->data;
len = frame->datalen;