FS-7500: another refactoring pass, temp code still in place, WORK IN PROGRESS
This commit is contained in:
parent
258dacc742
commit
0cd5658caa
|
@ -169,10 +169,6 @@ typedef enum {
|
|||
DS_INVALID,
|
||||
} dtls_state_t;
|
||||
|
||||
typedef switch_status_t (switch_core_video_thread_callback_func_t) (switch_core_session_t *session, switch_frame_t *frame, void *user_data);
|
||||
|
||||
|
||||
|
||||
#define MESSAGE_STAMP_FFL(_m) _m->_file = __FILE__; _m->_func = __SWITCH_FUNC__; _m->_line = __LINE__
|
||||
|
||||
#define MESSAGE_STRING_ARG_MAX 10
|
||||
|
@ -1274,18 +1270,6 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(_In_ switch_core_
|
|||
*/
|
||||
SWITCH_DECLARE(switch_status_t) switch_core_session_read_video_frame(_In_ switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags,
|
||||
int stream_id);
|
||||
|
||||
/*!
|
||||
\brief Write a video image to a session using a video frame
|
||||
\param session the session to write to
|
||||
\param frame a pointer to a frame to use for write with proper codec
|
||||
\param img the image structure with the image data
|
||||
\param the size for packetization
|
||||
\param flag pointer to frame flags to pass in / out
|
||||
\return SWITCH_STATUS_SUCCESS a if the image was written
|
||||
*/
|
||||
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);
|
||||
/*!
|
||||
\brief set a callback to be called after each frame of an image is written
|
||||
\param session the session to write to
|
||||
|
@ -1643,16 +1627,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_codec_decode(switch_codec_t *codec,
|
|||
/*!
|
||||
\brief Encode video data using a codec handle
|
||||
\param codec the codec handle to use
|
||||
\param img the img in I420 format
|
||||
\param encoded_data the buffer to write the encoded data to
|
||||
\param encoded_data_len the size of the encoded_data buffer
|
||||
\param flag flags to exchange
|
||||
\return SWITCH_STATUS_SUCCESS if the data was encoded
|
||||
\note encoded_data_len will be rewritten to the in-use size of encoded_data
|
||||
\param frame the frame to encode
|
||||
*/
|
||||
SWITCH_DECLARE(switch_status_t) switch_core_codec_encode_video(switch_codec_t *codec,
|
||||
switch_image_t *img,
|
||||
void *encoded_data, uint32_t *encoded_data_len, unsigned int *flag);
|
||||
SWITCH_DECLARE(switch_status_t) switch_core_codec_encode_video(switch_codec_t *codec, switch_frame_t *frame);
|
||||
|
||||
|
||||
/*!
|
||||
\brief send control data using a codec handle
|
||||
|
@ -1679,10 +1657,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_codec_control(switch_codec_t *codec,
|
|||
\param flag flags to exchange
|
||||
\return SWITCH_STATUS_SUCCESS if the data was decoded, and a non-NULL img
|
||||
*/
|
||||
SWITCH_DECLARE(switch_status_t) switch_core_codec_decode_video(switch_codec_t *codec,
|
||||
switch_frame_t *frame,
|
||||
switch_image_t **img, unsigned int *flag);
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_core_codec_decode_video(switch_codec_t *codec, switch_frame_t *frame);
|
||||
|
||||
/*!
|
||||
\brief Destroy an initalized codec handle
|
||||
|
@ -2340,34 +2315,6 @@ SWITCH_DECLARE(uint8_t) switch_core_session_compare(switch_core_session_t *a, sw
|
|||
*/
|
||||
SWITCH_DECLARE(uint8_t) switch_core_session_check_interface(switch_core_session_t *session, const switch_endpoint_interface_t *endpoint_interface);
|
||||
|
||||
/*!
|
||||
\brief Set a callback to let the core video thread call us
|
||||
\param session the session
|
||||
\param func to callback
|
||||
\param private user data
|
||||
\return SWITCH_STATUS_CONTINUE | SWITCH_STATUS_SUCCESS | SWITCH_STATUS_BREAK | SWITCH_STATUS_*
|
||||
|
||||
If returns SWITCH_STATUS_CONTINUE, it will continues to run furthur code (read/write) in the core video thread,
|
||||
that is to say, if the callback func to nothing and just returns SWITCH_STATUS_CONTINUE, it remains the default behaviour,
|
||||
Return SWITCH_STATUS_SUCCESS to skip the default behaviour
|
||||
Return SWITCH_STATUS_BREAK will break the loop and end the video thread
|
||||
*/
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_core_session_set_video_thread_callback(switch_core_session_t *session, switch_core_video_thread_callback_func_t *func, void *user_data);
|
||||
|
||||
/*!
|
||||
\brief Set a callback to let the core video thread call us
|
||||
\param session the session
|
||||
\param the current video frame
|
||||
\param private user data
|
||||
\return SWITCH_STATUS_CONTINUE or SWITCH_STATUS_SUCCESS
|
||||
|
||||
If returns SWITCH_STATUS_CONTINUE, it will continues to run furthur code (read/write) in the core video thread,
|
||||
that is to say, if the callback func to nothing and just returns SWITCH_STATUS_CONTINUE, it remains the default behaviour,
|
||||
Return SWITCH_STATUS_SUCCESS to skip the default behaviour
|
||||
*/
|
||||
SWITCH_DECLARE(switch_status_t) switch_core_session_video_thread_callback(switch_core_session_t *session, switch_frame_t *frame);
|
||||
|
||||
SWITCH_DECLARE(switch_hash_index_t *) switch_core_mime_index(void);
|
||||
SWITCH_DECLARE(const char *) switch_core_mime_ext2type(const char *ext);
|
||||
SWITCH_DECLARE(const char *) switch_core_mime_type2ext(const char *type);
|
||||
|
|
|
@ -150,7 +150,7 @@ typedef struct switch_core_media_params_s {
|
|||
/* a core_video_thread will be started automatically
|
||||
when uses rtp based media,
|
||||
external_video_source should be set to SWITCH_TRUE and
|
||||
switch_core_media_start_video_thread()
|
||||
switch_core_session_start_video_thread()
|
||||
should be explicitly called to start the video thread
|
||||
if uses the media handle for non-rtp based media
|
||||
*/
|
||||
|
@ -266,11 +266,6 @@ SWITCH_DECLARE(void) switch_core_media_deinit(void);
|
|||
SWITCH_DECLARE(void) switch_core_media_set_stats(switch_core_session_t *session);
|
||||
SWITCH_DECLARE(void) switch_core_session_wake_video_thread(switch_core_session_t *session);
|
||||
SWITCH_DECLARE(void) switch_core_session_clear_crypto(switch_core_session_t *session);
|
||||
<<<<<<< HEAD
|
||||
SWITCH_DECLARE(switch_status_t) switch_core_media_start_video_thread(switch_core_session_t *session);
|
||||
=======
|
||||
SWITCH_DECLARE(switch_status_t) start_core_video_thread(switch_core_session_t *session);
|
||||
>>>>>>> allow using the video thread externally - e.g. non rtp based video
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_core_session_get_payload_code(switch_core_session_t *session,
|
||||
switch_media_type_t type,
|
||||
|
@ -314,7 +309,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_codec_control(switch_core_sess
|
|||
|
||||
|
||||
SWITCH_DECLARE(switch_timer_t *) switch_core_media_get_timer(switch_core_session_t *session, switch_media_type_t mtype);
|
||||
|
||||
SWITCH_DECLARE(void) switch_core_media_start_video_function(switch_core_session_t *session, switch_video_function_t video_function, void *user_data);
|
||||
SWITCH_DECLARE(void) switch_core_media_end_video_function(switch_core_session_t *session);
|
||||
SWITCH_DECLARE(switch_status_t) switch_core_session_start_video_thread(switch_core_session_t *session);
|
||||
SWITCH_DECLARE(int) switch_core_media_check_video_function(switch_core_session_t *session);
|
||||
SWITCH_END_EXTERN_C
|
||||
#endif
|
||||
/* For Emacs:
|
||||
|
|
|
@ -74,6 +74,7 @@ SWITCH_BEGIN_EXTERN_C
|
|||
switch_frame_flag_t flags;
|
||||
void *user_data;
|
||||
payload_map_t *pmap;
|
||||
switch_image_t *img;
|
||||
};
|
||||
|
||||
SWITCH_END_EXTERN_C
|
||||
|
|
|
@ -1450,6 +1450,7 @@ typedef enum {
|
|||
CF_BYPASS_MEDIA_AFTER_HOLD,
|
||||
CF_HANGUP_HELD,
|
||||
CF_CONFERENCE_RESET_MEDIA,
|
||||
CF_VIDEO_DECODED_READ,
|
||||
/* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */
|
||||
/* IF YOU ADD NEW ONES CHECK IF THEY SHOULD PERSIST OR ZERO THEM IN switch_core_session.c switch_core_session_request_xml() */
|
||||
CF_FLAG_MAX
|
||||
|
@ -1496,7 +1497,8 @@ typedef enum {
|
|||
SFF_MARKER = (1 << 11),
|
||||
SFF_WAIT_KEY_FRAME = (1 << 12),
|
||||
SFF_RAW_RTP_PARSE_FRAME = (1 << 13),
|
||||
SFF_PICTURE_RESET = (1 << 14)
|
||||
SFF_PICTURE_RESET = (1 << 14),
|
||||
SFF_SAME_IMAGE = (1 << 15)
|
||||
} switch_frame_flag_enum_t;
|
||||
typedef uint32_t switch_frame_flag_t;
|
||||
|
||||
|
@ -2154,6 +2156,8 @@ typedef switch_bool_t (*switch_media_bug_callback_t) (switch_media_bug_t *, void
|
|||
typedef switch_bool_t (*switch_tone_detect_callback_t) (switch_core_session_t *, const char *, const char *);
|
||||
typedef struct switch_xml_binding switch_xml_binding_t;
|
||||
|
||||
typedef void (*switch_video_function_t) (switch_core_session_t *session, void *user_data);
|
||||
|
||||
typedef switch_status_t (*switch_core_codec_encode_func_t) (switch_codec_t *codec,
|
||||
switch_codec_t *other_codec,
|
||||
void *decoded_data,
|
||||
|
@ -2169,13 +2173,9 @@ typedef switch_status_t (*switch_core_codec_decode_func_t) (switch_codec_t *code
|
|||
uint32_t encoded_rate,
|
||||
void *decoded_data, uint32_t *decoded_data_len, uint32_t *decoded_rate, unsigned int *flag);
|
||||
|
||||
typedef switch_status_t (*switch_core_codec_video_encode_func_t) (switch_codec_t *codec,
|
||||
switch_image_t *img,
|
||||
void *encoded_data, uint32_t *encoded_data_len, unsigned int *flag);
|
||||
typedef switch_status_t (*switch_core_codec_video_encode_func_t) (switch_codec_t *codec, switch_frame_t *frame);
|
||||
|
||||
typedef switch_status_t (*switch_core_codec_video_decode_func_t) (switch_codec_t *codec,
|
||||
switch_frame_t *frame,
|
||||
switch_image_t **img, unsigned int *flag);
|
||||
typedef switch_status_t (*switch_core_codec_video_decode_func_t) (switch_codec_t *codec, switch_frame_t *frame);
|
||||
|
||||
typedef enum {
|
||||
SCC_VIDEO_REFRESH = 0
|
||||
|
|
|
@ -198,8 +198,7 @@ typedef enum {
|
|||
MFLAG_JOIN_ONLY = (1 << 25),
|
||||
MFLAG_POSITIONAL = (1 << 26),
|
||||
MFLAG_NO_POSITIONAL = (1 << 27),
|
||||
MFLAG_JOIN_VID_FLOOR = (1 << 28),
|
||||
MFLAG_RECEIVING_VIDEO = (1 << 29)
|
||||
MFLAG_JOIN_VID_FLOOR = (1 << 28)
|
||||
} member_flag_t;
|
||||
|
||||
typedef enum {
|
||||
|
@ -231,8 +230,7 @@ typedef enum {
|
|||
|
||||
typedef enum {
|
||||
RFLAG_CAN_SPEAK = (1 << 0),
|
||||
RFLAG_CAN_HEAR = (1 << 1),
|
||||
RFLAG_CAN_SEND_VIDEO = (1 << 2)
|
||||
RFLAG_CAN_HEAR = (1 << 1)
|
||||
} relation_flag_t;
|
||||
|
||||
typedef enum {
|
||||
|
@ -2394,11 +2392,6 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe
|
|||
|
||||
}
|
||||
|
||||
if (member->conference->video_floor_holder && member->conference->video_floor_holder != member && member->channel) {
|
||||
// there's already someone hold the floor, tell the core thread start to read video
|
||||
switch_channel_clear_flag(member->channel, CF_VIDEO_PASSIVE);
|
||||
}
|
||||
|
||||
unlock_member(member);
|
||||
switch_mutex_unlock(member->audio_out_mutex);
|
||||
switch_mutex_unlock(member->audio_in_mutex);
|
||||
|
@ -2917,29 +2910,6 @@ static void *SWITCH_THREAD_FUNC conference_video_bridge_thread_run(switch_thread
|
|||
return NULL;
|
||||
}
|
||||
|
||||
switch_status_t video_thread_callback(switch_core_session_t *session, switch_frame_t *frame, void *user_data)
|
||||
{
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
char *name = switch_channel_get_name(channel);
|
||||
conference_member_t *member = (conference_member_t *)user_data;
|
||||
conference_relationship_t *rel = NULL;
|
||||
|
||||
if (!member || member->relationships == NULL) return SWITCH_STATUS_SUCCESS;
|
||||
|
||||
lock_member(member);
|
||||
|
||||
for (rel = member->relationships; rel; rel = rel->next) {
|
||||
conference_member_t *imember = conference_member_get(member->conference, rel->id);
|
||||
if (imember && switch_test_flag(imember, MFLAG_RECEIVING_VIDEO)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s %d->%d %d\n", name, member->id, imember->id, frame->datalen);
|
||||
switch_core_session_write_video_frame(imember->session, frame, SWITCH_IO_FLAG_NONE, 0);
|
||||
switch_thread_rwlock_unlock(imember->rwlock);
|
||||
}
|
||||
}
|
||||
|
||||
unlock_member(member);
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Main video monitor thread (1 per distinct conference room) */
|
||||
static void *SWITCH_THREAD_FUNC conference_video_thread_run(switch_thread_t *thread, void *obj)
|
||||
|
@ -3031,11 +3001,9 @@ static void *SWITCH_THREAD_FUNC conference_video_thread_run(switch_thread_t *thr
|
|||
}
|
||||
|
||||
if (isession && switch_channel_test_flag(ichannel, CF_VIDEO)) {
|
||||
if (!switch_test_flag(imember, MFLAG_RECEIVING_VIDEO)) {
|
||||
memcpy(vid_frame->packet, buf, vid_frame->packetlen);
|
||||
switch_core_session_write_video_frame(imember->session, vid_frame, SWITCH_IO_FLAG_NONE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
switch_core_session_rwunlock(isession);
|
||||
}
|
||||
|
@ -7559,7 +7527,7 @@ static switch_status_t conf_api_sub_stop(conference_obj_t *conference, switch_st
|
|||
|
||||
static switch_status_t conf_api_sub_relate(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv)
|
||||
{
|
||||
uint8_t nospeak = 0, nohear = 0, sendvideo = 0, clear = 0;
|
||||
uint8_t nospeak = 0, nohear = 0, clear = 0;
|
||||
|
||||
switch_assert(conference != NULL);
|
||||
switch_assert(stream != NULL);
|
||||
|
@ -7580,10 +7548,9 @@ static switch_status_t conf_api_sub_relate(conference_obj_t *conference, switch_
|
|||
if (member_id > 0 && member->id != member_id) continue;
|
||||
|
||||
for (rel = member->relationships; rel; rel = rel->next) {
|
||||
stream->write_function(stream, "%d -> %d %s%s%s\n", member->id, rel->id,
|
||||
stream->write_function(stream, "%d -> %d %s%s\n", member->id, rel->id,
|
||||
(rel->flags & RFLAG_CAN_SPEAK) ? "SPEAK " : "NOSPEAK ",
|
||||
(rel->flags & RFLAG_CAN_HEAR) ? "HEAR " : "NOHEAR ",
|
||||
(rel->flags & RFLAG_CAN_SEND_VIDEO) ? "SENDVIDEO " : "NOSENDVIDEO ");
|
||||
(rel->flags & RFLAG_CAN_HEAR) ? "HEAR" : "NOHEAR");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -7598,35 +7565,22 @@ static switch_status_t conf_api_sub_relate(conference_obj_t *conference, switch_
|
|||
|
||||
nospeak = strstr(argv[4], "nospeak") ? 1 : 0;
|
||||
nohear = strstr(argv[4], "nohear") ? 1 : 0;
|
||||
sendvideo = strstr(argv[4], "sendvideo") ? 1 : 0;
|
||||
|
||||
if (!strcasecmp(argv[4], "clear")) {
|
||||
clear = 1;
|
||||
}
|
||||
|
||||
if (!(clear || nospeak || nohear || sendvideo)) {
|
||||
if (!(clear || nospeak || nohear)) {
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
|
||||
if (clear) {
|
||||
conference_member_t *member = NULL, *other_member = NULL;
|
||||
conference_member_t *member = NULL;
|
||||
uint32_t id = atoi(argv[2]);
|
||||
uint32_t oid = atoi(argv[3]);
|
||||
|
||||
if ((member = conference_member_get(conference, id))) {
|
||||
member_del_relationship(member, oid);
|
||||
other_member = conference_member_get(conference, oid);
|
||||
|
||||
if (other_member) {
|
||||
if (switch_test_flag(other_member, MFLAG_RECEIVING_VIDEO)) {
|
||||
switch_clear_flag(other_member, MFLAG_RECEIVING_VIDEO);
|
||||
if (conference->floor_holder) {
|
||||
switch_core_session_refresh_video(conference->floor_holder->session);
|
||||
}
|
||||
}
|
||||
switch_thread_rwlock_unlock(other_member->rwlock);
|
||||
}
|
||||
|
||||
stream->write_function(stream, "relationship %u->%u cleared.\n", id, oid);
|
||||
switch_thread_rwlock_unlock(member->rwlock);
|
||||
} else {
|
||||
|
@ -7635,7 +7589,7 @@ static switch_status_t conf_api_sub_relate(conference_obj_t *conference, switch_
|
|||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (nospeak || nohear || sendvideo) {
|
||||
if (nospeak || nohear) {
|
||||
conference_member_t *member = NULL, *other_member = NULL;
|
||||
uint32_t id = atoi(argv[2]);
|
||||
uint32_t oid = atoi(argv[3]);
|
||||
|
@ -7647,11 +7601,6 @@ static switch_status_t conf_api_sub_relate(conference_obj_t *conference, switch_
|
|||
if (member && other_member) {
|
||||
conference_relationship_t *rel = NULL;
|
||||
|
||||
if (sendvideo && switch_test_flag(other_member, MFLAG_RECEIVING_VIDEO) && (! (nospeak || nohear))) {
|
||||
stream->write_function(stream, "member %d already receiving video", oid);
|
||||
goto skip;
|
||||
}
|
||||
|
||||
if ((rel = member_get_relationship(member, other_member))) {
|
||||
rel->flags = 0;
|
||||
} else {
|
||||
|
@ -7667,13 +7616,7 @@ static switch_status_t conf_api_sub_relate(conference_obj_t *conference, switch_
|
|||
if (nohear) {
|
||||
switch_clear_flag(rel, RFLAG_CAN_HEAR);
|
||||
}
|
||||
if (sendvideo) {
|
||||
switch_set_flag(rel, RFLAG_CAN_SEND_VIDEO);
|
||||
switch_set_flag(other_member, MFLAG_RECEIVING_VIDEO);
|
||||
switch_core_session_refresh_video(member->session);
|
||||
}
|
||||
|
||||
stream->write_function(stream, "ok %u->%u %s set\n", id, oid, argv[4]);
|
||||
stream->write_function(stream, "ok %u->%u set\n", id, oid);
|
||||
} else {
|
||||
stream->write_function(stream, "error!\n");
|
||||
}
|
||||
|
@ -7681,7 +7624,6 @@ static switch_status_t conf_api_sub_relate(conference_obj_t *conference, switch_
|
|||
stream->write_function(stream, "relationship %u->%u not found.\n", id, oid);
|
||||
}
|
||||
|
||||
skip:
|
||||
if (member) {
|
||||
switch_thread_rwlock_unlock(member->rwlock);
|
||||
}
|
||||
|
@ -9785,16 +9727,11 @@ SWITCH_STANDARD_APP(conference_function)
|
|||
msg.message_id = SWITCH_MESSAGE_INDICATE_BRIDGE;
|
||||
switch_core_session_receive_message(session, &msg);
|
||||
|
||||
/* Chime in the core video thread */
|
||||
switch_core_session_set_video_thread_callback(session, video_thread_callback, (void *)&member);
|
||||
|
||||
/* Run the conference loop */
|
||||
do {
|
||||
conference_loop_output(&member);
|
||||
} while (member.loop_loop);
|
||||
|
||||
switch_core_session_set_video_thread_callback(session, NULL, NULL);
|
||||
|
||||
switch_channel_set_private(channel, "_conference_autocall_list_", NULL);
|
||||
|
||||
/* Tell the channel we are no longer going to be in a bridge */
|
||||
|
|
|
@ -673,7 +673,6 @@ SWITCH_STANDARD_APP(play_yuv_function)
|
|||
if (read_frame) switch_core_session_write_frame(session, read_frame, SWITCH_IO_FLAG_NONE, 0);
|
||||
|
||||
{ /* video part */
|
||||
uint32_t flag = 0;
|
||||
uint32_t encoded_data_len = 1500;
|
||||
switch_frame_t *frame = &vid_frame;
|
||||
switch_time_t now = switch_micro_time_now() / 1000;
|
||||
|
@ -691,14 +690,12 @@ SWITCH_STANDARD_APP(play_yuv_function)
|
|||
|
||||
sprintf(ts_str, "%u", timestamp);
|
||||
text(img->planes[SWITCH_PLANE_PACKED], width, 20, 20, ts_str);
|
||||
switch_core_codec_encode_video(codec, img, vid_frame.data, &encoded_data_len, &flag);
|
||||
vid_frame.img = img;
|
||||
switch_core_codec_encode_video(codec, &vid_frame);
|
||||
|
||||
while(encoded_data_len) {
|
||||
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "encoded: %s [%d] flag=%d ts=%lld\n", codec->implementation->iananame, encoded_data_len, flag, last_video_ts);
|
||||
|
||||
frame->datalen = encoded_data_len;
|
||||
frame->packetlen = frame->datalen + 12;
|
||||
frame->m = flag & SFF_MARKER ? 1 : 0;
|
||||
frame->timestamp = timestamp;
|
||||
|
||||
if (1) { // we can remove this when ts and marker full passed in core
|
||||
|
@ -715,8 +712,8 @@ SWITCH_STANDARD_APP(play_yuv_function)
|
|||
|
||||
switch_core_session_write_video_frame(session, frame, SWITCH_IO_FLAG_NONE, 0);
|
||||
|
||||
encoded_data_len = 1500;
|
||||
switch_core_codec_encode_video(codec, NULL, vid_frame.data, &encoded_data_len, &flag);
|
||||
vid_frame.datalen = 1500;
|
||||
switch_core_codec_encode_video(codec, &vid_frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -817,10 +814,7 @@ SWITCH_STANDARD_APP(decode_video_function)
|
|||
}
|
||||
|
||||
if ( 1 ) { /* video part */
|
||||
uint32_t flag = 0;
|
||||
switch_image_t *img = NULL;
|
||||
|
||||
switch_core_codec_decode_video(codec, frame, &img, &flag);
|
||||
switch_core_codec_decode_video(codec, frame);
|
||||
|
||||
if ((switch_test_flag(frame, SFF_WAIT_KEY_FRAME))) {
|
||||
switch_time_t now = switch_micro_time_now();
|
||||
|
@ -831,19 +825,19 @@ SWITCH_STANDARD_APP(decode_video_function)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (img) {
|
||||
if (img->d_w > 0 && !width) {
|
||||
width = img->d_w;
|
||||
if (frame->img) {
|
||||
if (frame->img->d_w > 0 && !width) {
|
||||
width = frame->img->d_w;
|
||||
switch_channel_set_variable_printf(channel, "video_width", "%d", width);
|
||||
}
|
||||
|
||||
if (img->d_h > 0 && !height) {
|
||||
height = img->d_h;
|
||||
if (frame->img->d_h > 0 && !height) {
|
||||
height = frame->img->d_h;
|
||||
switch_channel_set_variable_printf(channel, "video_height", "%d", height);
|
||||
}
|
||||
|
||||
decoded_pictures++;
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "picture#%d %dx%d\n", decoded_pictures, img->d_w, img->d_h);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "picture#%d %dx%d\n", decoded_pictures, frame->img->d_w, frame->img->d_h);
|
||||
|
||||
if (max_pictures && (decoded_pictures >= max_pictures)) {
|
||||
break;
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
#include "codec_api.h"
|
||||
//#include "inc/logging.h" // for debug
|
||||
|
||||
#define FPS 15.0f // frame rate
|
||||
#define FPS 20.0f // frame rate
|
||||
#define H264_NALU_BUFFER_SIZE 65536
|
||||
#define MAX_NALUS 100
|
||||
#define SLICE_SIZE 1200 //NALU Slice Size
|
||||
|
@ -66,15 +66,16 @@ typedef struct h264_codec_context_s {
|
|||
switch_image_t *img;
|
||||
int got_sps;
|
||||
int64_t pts;
|
||||
int need_key_frame;
|
||||
switch_size_t last_received_timestamp;
|
||||
switch_bool_t last_received_complete_picture;
|
||||
} h264_codec_context_t;
|
||||
|
||||
int FillSpecificParameters(SEncParamExt& param) {
|
||||
/* Test for temporal, spatial, SNR scalability */
|
||||
param.iPicWidth = 352; // width of picture in samples
|
||||
param.iPicHeight = 288; // height of picture in samples
|
||||
param.iTargetBitrate = 384000; // target bitrate desired
|
||||
param.iPicWidth = 1280; // width of picture in samples
|
||||
param.iPicHeight = 720; // height of picture in samples
|
||||
param.iTargetBitrate = 1280 * 720 * 8; // target bitrate desired
|
||||
param.iRCMode = RC_QUALITY_MODE; // rc mode control
|
||||
param.uiMaxNalSize = SLICE_SIZE * 20;
|
||||
param.iTemporalLayerNum = 1; // layer number at temporal level
|
||||
|
@ -91,11 +92,11 @@ int FillSpecificParameters(SEncParamExt& param) {
|
|||
param.bPrefixNalAddingCtrl = 0;
|
||||
|
||||
int iIndexLayer = 0;
|
||||
param.sSpatialLayers[iIndexLayer].iVideoWidth = 352;
|
||||
param.sSpatialLayers[iIndexLayer].iVideoHeight = 288;
|
||||
param.sSpatialLayers[iIndexLayer].fFrameRate = 15.0f;
|
||||
param.sSpatialLayers[iIndexLayer].iVideoWidth = 1280;
|
||||
param.sSpatialLayers[iIndexLayer].iVideoHeight = 720;
|
||||
param.sSpatialLayers[iIndexLayer].fFrameRate = (double) (FPS * 1.0f);
|
||||
// param.sSpatialLayers[iIndexLayer].iQualityLayerNum = 1;
|
||||
param.sSpatialLayers[iIndexLayer].iSpatialBitrate = 384000;
|
||||
param.sSpatialLayers[iIndexLayer].iSpatialBitrate = 1280 * 720 * 8;
|
||||
|
||||
#ifdef MT_ENABLED
|
||||
param.sSpatialLayers[iIndexLayer].sSliceCfg.uiSliceMode = SM_DYN_SLICE;
|
||||
|
@ -137,27 +138,21 @@ static switch_size_t buffer_h264_nalu(h264_codec_context_t *context, switch_fram
|
|||
switch_buffer_t *buffer = context->nalu_buffer;
|
||||
switch_size_t size = 0;
|
||||
|
||||
if (!frame) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No frame in codec!!\n");
|
||||
return size;
|
||||
}
|
||||
switch_assert(frame);
|
||||
|
||||
nalu_idc = (nalu_hdr & 0x60) >> 5;
|
||||
nalu_type = nalu_hdr & 0x1f;
|
||||
|
||||
if (!context->got_sps && nalu_type != 7) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Waiting SPS/PPS\n");
|
||||
switch_set_flag(frame, SFF_WAIT_KEY_FRAME);
|
||||
return size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!context->got_sps) context->got_sps = 1;
|
||||
|
||||
size = switch_buffer_write(buffer, sync_bytes, sizeof(sync_bytes));
|
||||
if (size == 0 ) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Buffer Memory Error!\n");
|
||||
|
||||
size = switch_buffer_write(buffer, frame->data, frame->datalen);
|
||||
if (size == 0 ) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Buffer Memory Error!\n");
|
||||
|
||||
|
||||
#ifdef DEBUG_H264
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ts: %ld len: %4d %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x mark=%d size=%d\n",
|
||||
|
@ -173,13 +168,13 @@ static switch_size_t buffer_h264_nalu(h264_codec_context_t *context, switch_fram
|
|||
return size;
|
||||
}
|
||||
|
||||
static switch_status_t nalu_slice(h264_codec_context_t *context, void *data, uint32_t *len, uint32_t *flag)
|
||||
static switch_status_t nalu_slice(h264_codec_context_t *context, switch_frame_t *frame)
|
||||
{
|
||||
int nalu_len;
|
||||
uint8_t *buffer;
|
||||
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
||||
|
||||
*flag &= ~SFF_MARKER;
|
||||
frame->m = SWITCH_FALSE;
|
||||
|
||||
if (context->cur_nalu_index >= context->bit_stream_info.sLayerInfo[context->cur_layer].iNalCount) {
|
||||
context->cur_nalu_index = 0;
|
||||
|
@ -198,8 +193,8 @@ static switch_status_t nalu_slice(h264_codec_context_t *context, void *data, uin
|
|||
|
||||
if (context->last_frame_type == videoFrameTypeSkip ||
|
||||
context->cur_layer >= context->bit_stream_info.iLayerNum) {
|
||||
*len = 0;
|
||||
*flag |= SFF_MARKER;
|
||||
frame->datalen = 0;
|
||||
frame->m = SWITCH_TRUE;
|
||||
context->cur_layer = 0;
|
||||
context->cur_nalu_index = 0;
|
||||
return status;
|
||||
|
@ -225,12 +220,12 @@ static switch_status_t nalu_slice(h264_codec_context_t *context, void *data, uin
|
|||
|
||||
// if (nalu_type == 7) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Got SPS\n");
|
||||
|
||||
memcpy(data, (buffer + context->last_nalu_data_pos), nalu_len);
|
||||
*len = nalu_len;
|
||||
memcpy(frame->data, (buffer + context->last_nalu_data_pos), nalu_len);
|
||||
frame->datalen = nalu_len;
|
||||
// *flag |= (nalu_type == 6 || nalu_type == 7 || nalu_type == 8 || (nalu_type == 0xe && context->last_nalu_type == 8)) ? 0 : SFF_MARKER;
|
||||
if ((context->cur_nalu_index == context->bit_stream_info.sLayerInfo[context->cur_layer].iNalCount - 1) &&
|
||||
(context->cur_layer == context->bit_stream_info.iLayerNum - 1)) {
|
||||
*flag |= SFF_MARKER;
|
||||
frame->m = SWITCH_TRUE;
|
||||
} else {
|
||||
status = SWITCH_STATUS_MORE_DATA;
|
||||
}
|
||||
|
@ -240,7 +235,7 @@ static switch_status_t nalu_slice(h264_codec_context_t *context, void *data, uin
|
|||
goto end;
|
||||
} else {
|
||||
int left = nalu_len;
|
||||
uint8_t *p = (uint8_t *)data;
|
||||
uint8_t *p = (uint8_t *) frame->data;
|
||||
|
||||
if (context->nalu_eat) {
|
||||
left = nalu_len + 4 - context->nalu_eat;
|
||||
|
@ -267,7 +262,7 @@ static switch_status_t nalu_slice(h264_codec_context_t *context, void *data, uin
|
|||
memcpy(p + 2, buffer + context->last_nalu_data_pos, SLICE_SIZE - 2);
|
||||
context->last_nalu_data_pos += (SLICE_SIZE - 2);
|
||||
context->nalu_eat += (SLICE_SIZE - 2);
|
||||
*len = SLICE_SIZE;
|
||||
frame->datalen = SLICE_SIZE;
|
||||
status = SWITCH_STATUS_MORE_DATA;
|
||||
goto end;
|
||||
} else {
|
||||
|
@ -275,8 +270,8 @@ static switch_status_t nalu_slice(h264_codec_context_t *context, void *data, uin
|
|||
p[1] = 0x40 | context->last_nalu_type;
|
||||
memcpy(p + 2, buffer + context->last_nalu_data_pos, left);
|
||||
context->last_nalu_data_pos += left;
|
||||
*len = left + 2;
|
||||
*flag |= SFF_MARKER;
|
||||
frame->datalen = left + 2;
|
||||
frame->m = SWITCH_TRUE;
|
||||
context->nalu_eat = 0;
|
||||
context->cur_nalu_index++;
|
||||
status = SWITCH_STATUS_MORE_DATA;
|
||||
|
@ -361,6 +356,7 @@ static switch_status_t init_encoder(h264_codec_context_t *context, uint32_t widt
|
|||
|
||||
context->encoder_params.iPicWidth = width;
|
||||
context->encoder_params.iPicHeight = height;
|
||||
|
||||
for (int i=0; i<context->encoder_params.iSpatialLayerNum; i++) {
|
||||
context->encoder_params.sSpatialLayers[i].iVideoWidth = width;
|
||||
context->encoder_params.sSpatialLayers[i].iVideoHeight = height;
|
||||
|
@ -371,14 +367,12 @@ static switch_status_t init_encoder(h264_codec_context_t *context, uint32_t widt
|
|||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Encoder Init Error\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
context->encoder_initialized = SWITCH_TRUE;
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t switch_h264_encode(switch_codec_t *codec,
|
||||
switch_image_t *img,
|
||||
void *encoded_data, uint32_t *encoded_data_len,
|
||||
unsigned int *flag)
|
||||
static switch_status_t switch_h264_encode(switch_codec_t *codec, switch_frame_t *frame)
|
||||
{
|
||||
h264_codec_context_t *context = (h264_codec_context_t *)codec->private_info;
|
||||
int width = 0;
|
||||
|
@ -387,17 +381,24 @@ static switch_status_t switch_h264_encode(switch_codec_t *codec,
|
|||
SSourcePicture* pic = NULL;
|
||||
long result;
|
||||
|
||||
if (*flag & SFF_WAIT_KEY_FRAME) {
|
||||
if (context->need_key_frame) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "H264 KEYFRAME GENERATED\n");
|
||||
context->encoder->ForceIntraFrame(1);
|
||||
context->need_key_frame = 0;
|
||||
}
|
||||
|
||||
if (img == NULL) {
|
||||
return nalu_slice(context, encoded_data, encoded_data_len, flag);
|
||||
if (frame->flags & SFF_SAME_IMAGE) {
|
||||
return nalu_slice(context, frame);
|
||||
}
|
||||
|
||||
//d_w and d_h are corrupt
|
||||
width = img->w;
|
||||
height = img->h;
|
||||
|
||||
if (frame->img->d_h > 1) {
|
||||
width = frame->img->d_w;
|
||||
height = frame->img->d_h;
|
||||
} else {
|
||||
width = frame->img->w;
|
||||
height = frame->img->h;
|
||||
}
|
||||
|
||||
//switch_assert(width > 0 && (width % 2 == 0));
|
||||
//switch_assert(height > 0 && (height % 2 == 0));
|
||||
|
@ -419,12 +420,12 @@ static switch_status_t switch_h264_encode(switch_codec_t *codec,
|
|||
pic->iColorFormat = videoFormatI420;
|
||||
pic->iPicHeight = height;
|
||||
pic->iPicWidth = width;
|
||||
pic->iStride[0] = img->stride[0];
|
||||
pic->iStride[1] = img->stride[1]; // = img->stride[2];
|
||||
pic->iStride[0] = frame->img->stride[0];
|
||||
pic->iStride[1] = frame->img->stride[1]; // = frame->img->stride[2];
|
||||
|
||||
pic->pData[0] = img->planes[0];
|
||||
pic->pData[1] = img->planes[1];
|
||||
pic->pData[2] = img->planes[2];
|
||||
pic->pData[0] = frame->img->planes[0];
|
||||
pic->pData[1] = frame->img->planes[1];
|
||||
pic->pData[2] = frame->img->planes[2];
|
||||
|
||||
result = (EVideoFrameType)context->encoder->EncodeFrame(pic, &context->bit_stream_info);
|
||||
if (result != cmResultSuccess ) {
|
||||
|
@ -436,45 +437,48 @@ static switch_status_t switch_h264_encode(switch_codec_t *codec,
|
|||
context->cur_nalu_index = 0;
|
||||
context->last_nalu_data_pos = 0;
|
||||
|
||||
if(pic){
|
||||
if (pic){
|
||||
delete pic;
|
||||
pic = NULL;
|
||||
}
|
||||
return nalu_slice(context, encoded_data, encoded_data_len, flag);
|
||||
|
||||
return nalu_slice(context, frame);
|
||||
|
||||
error:
|
||||
|
||||
if(pic){
|
||||
delete pic;
|
||||
pic = NULL;
|
||||
}
|
||||
|
||||
*encoded_data_len = 0;
|
||||
*flag |= SFF_MARKER;
|
||||
frame->datalen = 0;
|
||||
frame->m = SWITCH_TRUE;
|
||||
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
static switch_status_t switch_h264_decode(switch_codec_t *codec,
|
||||
switch_frame_t *frame,
|
||||
switch_image_t **img,
|
||||
unsigned int *flag)
|
||||
static switch_status_t switch_h264_decode(switch_codec_t *codec, switch_frame_t *frame)
|
||||
{
|
||||
h264_codec_context_t *context = (h264_codec_context_t *)codec->private_info;
|
||||
switch_size_t size = 0;
|
||||
uint32_t error_code;
|
||||
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
||||
|
||||
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "len: %d ts: %u mark:%d\n", frame->datalen, ntohl(frame->timestamp), frame->m);
|
||||
|
||||
if (context->last_received_timestamp && context->last_received_timestamp != frame->timestamp &&
|
||||
if (0 && context->last_received_timestamp && context->last_received_timestamp != frame->timestamp &&
|
||||
(!frame->m) && (!context->last_received_complete_picture)) {
|
||||
// possible packet loss
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Packet Loss, skip privousely received packets\n");
|
||||
switch_buffer_zero(context->nalu_buffer);
|
||||
switch_goto_status(SWITCH_STATUS_RESTART, end);
|
||||
}
|
||||
|
||||
context->last_received_timestamp = frame->timestamp;
|
||||
context->last_received_complete_picture = frame->m ? SWITCH_TRUE : SWITCH_FALSE;
|
||||
|
||||
size = buffer_h264_nalu(context, frame);
|
||||
printf("READ buf:%ld got_key:%d st:%d m:%d\n", size, context->got_sps, status, frame->m);
|
||||
|
||||
|
||||
if (frame->m && size) {
|
||||
int got_picture = 0;
|
||||
|
@ -486,6 +490,11 @@ static switch_status_t switch_h264_decode(switch_codec_t *codec,
|
|||
switch_buffer_peek_zerocopy(context->nalu_buffer, &nalu);
|
||||
uint8_t* pData[3] = { 0 };
|
||||
|
||||
|
||||
frame->m = SWITCH_FALSE;
|
||||
frame->flags = 0;
|
||||
|
||||
|
||||
pData[0] = NULL;
|
||||
pData[1] = NULL;
|
||||
pData[2] = NULL;
|
||||
|
@ -515,22 +524,40 @@ static switch_status_t switch_h264_decode(switch_codec_t *codec,
|
|||
context->img->stride[1] = dest_buffer_info.UsrData.sSystemBuffer.iStride[1];
|
||||
context->img->stride[2] = dest_buffer_info.UsrData.sSystemBuffer.iStride[1];
|
||||
|
||||
*img = context->img;
|
||||
frame->img = context->img;
|
||||
// TODO: keep going and see if more picture available
|
||||
// pDecoder->DecodeFrame (NULL, 0, pData, &sDstBufInfo);
|
||||
} else {
|
||||
if (error_code) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Decode error: 0x%x\n", error_code);
|
||||
context->got_sps = 0;
|
||||
switch_goto_status(SWITCH_STATUS_RESTART, end);
|
||||
}
|
||||
}
|
||||
|
||||
switch_buffer_zero(context->nalu_buffer);
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
status = SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
end:
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
||||
if (size == 0) {
|
||||
status == SWITCH_STATUS_MORE_DATA;
|
||||
}
|
||||
|
||||
if (status == SWITCH_STATUS_RESTART) {
|
||||
context->got_sps = 0;
|
||||
switch_buffer_zero(context->nalu_buffer);
|
||||
}
|
||||
|
||||
if (!context->got_sps) {
|
||||
switch_set_flag(frame, SFF_WAIT_KEY_FRAME);
|
||||
}
|
||||
|
||||
if (!frame->img) {
|
||||
status = SWITCH_STATUS_MORE_DATA;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static switch_status_t switch_h264_control(switch_codec_t *codec,
|
||||
|
@ -540,6 +567,18 @@ static switch_status_t switch_h264_control(switch_codec_t *codec,
|
|||
switch_codec_control_type_t *rtype,
|
||||
void **ret_data) {
|
||||
|
||||
|
||||
|
||||
h264_codec_context_t *context = (h264_codec_context_t *)codec->private_info;
|
||||
|
||||
switch(cmd) {
|
||||
case SCC_VIDEO_REFRESH:
|
||||
context->need_key_frame = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
#include <vpx/vp8dx.h>
|
||||
#include <vpx/vp8.h>
|
||||
|
||||
#define FPS 15
|
||||
#define FPS 20
|
||||
#define SLICE_SIZE 1200
|
||||
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_vpx_load);
|
||||
|
@ -84,6 +84,24 @@ static switch_status_t init_codec(switch_codec_t *codec)
|
|||
vpx_context_t *context = (vpx_context_t *)codec->private_info;
|
||||
vpx_codec_enc_cfg_t *config = &context->config;
|
||||
|
||||
if (!context->codec_settings.video.width) {
|
||||
context->codec_settings.video.width = 1280;
|
||||
}
|
||||
|
||||
if (!context->codec_settings.video.height) {
|
||||
context->codec_settings.video.height = 720;
|
||||
}
|
||||
|
||||
if (context->codec_settings.video.bandwidth) {
|
||||
context->bandwidth = context->codec_settings.video.bandwidth;
|
||||
} else {
|
||||
context->bandwidth = context->codec_settings.video.width * context->codec_settings.video.height * 8;
|
||||
}
|
||||
|
||||
if (context->bandwidth > 1250000) {
|
||||
context->bandwidth = 1250000;
|
||||
}
|
||||
|
||||
// settings
|
||||
config->g_profile = 1;
|
||||
config->g_w = context->codec_settings.video.width;
|
||||
|
@ -93,7 +111,8 @@ static switch_status_t init_codec(switch_codec_t *codec)
|
|||
config->g_timebase.den = 1000;
|
||||
config->g_error_resilient = VPX_ERROR_RESILIENT_PARTITIONS;
|
||||
config->g_lag_in_frames = 0; // 0- no frame lagging
|
||||
config->g_threads = 1;
|
||||
config->g_threads = (switch_core_cpu_count() > 1) ? 2 : 1;
|
||||
|
||||
// rate control settings
|
||||
config->rc_dropframe_thresh = 0;
|
||||
config->rc_end_usage = VPX_CBR;
|
||||
|
@ -198,6 +217,8 @@ static switch_status_t init_codec(switch_codec_t *codec)
|
|||
vpx_codec_control(&context->decoder, VP8_SET_POSTPROC, &ppcfg);
|
||||
|
||||
switch_buffer_create_dynamic(&context->vpx_packet_buffer, 512, 512, 1024000);
|
||||
|
||||
printf("WTF CREATE ??? %p\n", (void *)context->vpx_packet_buffer);
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
@ -274,11 +295,11 @@ static switch_status_t switch_vpx_init(switch_codec_t *codec, switch_codec_flag_
|
|||
+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
|
||||
static switch_status_t consume_partition(vpx_context_t *context, void *data, uint32_t *len, uint32_t *flag)
|
||||
static switch_status_t consume_partition(vpx_context_t *context, switch_frame_t *frame)
|
||||
{
|
||||
if (!context->pkt) context->pkt = vpx_codec_get_cx_data(&context->encoder, &context->iter);
|
||||
|
||||
*flag &= ~SFF_MARKER;
|
||||
frame->m = 0;
|
||||
|
||||
if (context->pkt) {
|
||||
// if (context->pkt->kind == VPX_CODEC_CX_FRAME_PKT && (context->pkt->data.frame.flags & VPX_FRAME_IS_KEY) && context->pkt_pos == 0) {
|
||||
|
@ -290,8 +311,8 @@ static switch_status_t consume_partition(vpx_context_t *context, void *data, uin
|
|||
}
|
||||
|
||||
if (!context->pkt || context->pkt_pos >= context->pkt->data.frame.sz - 1 || context->pkt->kind != VPX_CODEC_CX_FRAME_PKT) {
|
||||
*len = 0;
|
||||
*flag |= SFF_MARKER;
|
||||
frame->datalen = 0;
|
||||
frame->m = 1;
|
||||
context->pkt_pos = 0;
|
||||
context->pkt = NULL;
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
@ -300,24 +321,24 @@ static switch_status_t consume_partition(vpx_context_t *context, void *data, uin
|
|||
if (context->pkt->data.frame.sz < SLICE_SIZE) {
|
||||
uint8_t hdr = 0x10;
|
||||
|
||||
memcpy(data, &hdr, 1);
|
||||
memcpy((uint8_t *)data + 1, context->pkt->data.frame.buf, context->pkt->data.frame.sz);
|
||||
*len = context->pkt->data.frame.sz + 1;
|
||||
*flag |= SFF_MARKER;
|
||||
memcpy(frame->data, &hdr, 1);
|
||||
memcpy((uint8_t *)frame->data + 1, context->pkt->data.frame.buf, context->pkt->data.frame.sz);
|
||||
frame->datalen = context->pkt->data.frame.sz + 1;
|
||||
frame->m = 1;
|
||||
context->pkt = NULL;
|
||||
context->pkt_pos = 0;
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
} else {
|
||||
int left = context->pkt->data.frame.sz - context->pkt_pos;
|
||||
uint8_t *p = data;
|
||||
uint8_t *p = frame->data;
|
||||
|
||||
if (left < SLICE_SIZE) {
|
||||
p[0] = 0;
|
||||
memcpy(p+1, (uint8_t *)context->pkt->data.frame.buf + context->pkt_pos, left);
|
||||
context->pkt_pos = 0;
|
||||
context->pkt = NULL;
|
||||
*len = left + 1;
|
||||
*flag |= SFF_MARKER;
|
||||
frame->datalen = left + 1;
|
||||
frame->m = 1;
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
} else {
|
||||
uint8_t hdr = context->pkt_pos == 0 ? 0x10 : 0;
|
||||
|
@ -325,15 +346,13 @@ static switch_status_t consume_partition(vpx_context_t *context, void *data, uin
|
|||
p[0] = hdr;
|
||||
memcpy(p+1, (uint8_t *)context->pkt->data.frame.buf + context->pkt_pos, SLICE_SIZE - 1);
|
||||
context->pkt_pos += (SLICE_SIZE - 1);
|
||||
*len = SLICE_SIZE;
|
||||
frame->datalen = SLICE_SIZE;
|
||||
return SWITCH_STATUS_MORE_DATA;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static switch_status_t switch_vpx_encode(switch_codec_t *codec, switch_image_t *img,
|
||||
void *encoded_data, uint32_t *encoded_data_len,
|
||||
unsigned int *flag)
|
||||
static switch_status_t switch_vpx_encode(switch_codec_t *codec, switch_frame_t *frame)
|
||||
{
|
||||
vpx_context_t *context = (vpx_context_t *)codec->private_info;
|
||||
uint32_t duration = 90000 / FPS;
|
||||
|
@ -341,20 +360,21 @@ static switch_status_t switch_vpx_encode(switch_codec_t *codec, switch_image_t *
|
|||
int height = 0;
|
||||
vpx_enc_frame_flags_t vpx_flags = 0;
|
||||
|
||||
if (*flag & SFF_WAIT_KEY_FRAME) {
|
||||
context->need_key_frame = 1;
|
||||
}
|
||||
|
||||
if (img == NULL) {
|
||||
return consume_partition(context, encoded_data, encoded_data_len, flag);
|
||||
if (frame->flags & SFF_SAME_IMAGE) {
|
||||
return consume_partition(context, frame);
|
||||
}
|
||||
|
||||
//d_w and d_h are messed up
|
||||
//printf("WTF %d %d\n", frame->img->d_w, frame->img->d_h);
|
||||
|
||||
//printf("WTF %d %d\n", img->d_w, img->d_h);
|
||||
|
||||
width = img->w;
|
||||
height = img->h;
|
||||
if (frame->img->d_h > 1) {
|
||||
width = frame->img->d_w;
|
||||
height = frame->img->d_h;
|
||||
} else {
|
||||
width = frame->img->w;
|
||||
height = frame->img->h;
|
||||
}
|
||||
|
||||
//switch_assert(width > 0 && (width % 4 == 0));
|
||||
//switch_assert(height > 0 && (height % 4 == 0));
|
||||
|
@ -362,45 +382,43 @@ static switch_status_t switch_vpx_encode(switch_codec_t *codec, switch_image_t *
|
|||
if (context->config.g_w != width || context->config.g_h != height) {
|
||||
context->codec_settings.video.width = width;
|
||||
context->codec_settings.video.height = height;
|
||||
if (context->codec_settings.video.bandwidth) {
|
||||
context->bandwidth = context->codec_settings.video.bandwidth;
|
||||
} else {
|
||||
context->bandwidth = width * height * 8;
|
||||
}
|
||||
|
||||
if (context->bandwidth > 1250000) {
|
||||
context->bandwidth = 1250000;
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(codec->session), SWITCH_LOG_NOTICE,
|
||||
"VPX reset encoder picture from %dx%d to %dx%d %u BW\n",
|
||||
context->config.g_w, context->config.g_h, width, height, context->bandwidth);
|
||||
|
||||
init_codec(codec);
|
||||
*flag |= SFF_PICTURE_RESET;
|
||||
frame->flags |= SFF_PICTURE_RESET;
|
||||
context->need_key_frame = 1;
|
||||
}
|
||||
|
||||
if (context->need_key_frame > 0) {
|
||||
// force generate a key frame
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "VPX KEYFRAME REQ\n");
|
||||
vpx_flags |= VPX_EFLAG_FORCE_KF;
|
||||
context->need_key_frame--;
|
||||
|
||||
if (!context->encoder_init) {
|
||||
init_codec(codec);
|
||||
}
|
||||
|
||||
if (vpx_codec_encode(&context->encoder, (vpx_image_t *)img, context->pts, duration, vpx_flags, VPX_DL_REALTIME) != VPX_CODEC_OK) {
|
||||
if (context->need_key_frame != 0) {
|
||||
// force generate a key frame
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "VPX KEYFRAME GENERATED\n");
|
||||
vpx_flags |= VPX_EFLAG_FORCE_KF;
|
||||
context->need_key_frame = 0;
|
||||
}
|
||||
|
||||
if (vpx_codec_encode(&context->encoder, (vpx_image_t *) frame->img, context->pts, duration, vpx_flags, VPX_DL_REALTIME) != VPX_CODEC_OK) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "VP8 encode error %d:%s\n",
|
||||
context->encoder.err, context->encoder.err_detail);
|
||||
|
||||
frame->datalen = 0;
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
context->pts += duration;
|
||||
context->iter = NULL;
|
||||
|
||||
return consume_partition(context, encoded_data, encoded_data_len, flag);
|
||||
return consume_partition(context, frame);
|
||||
}
|
||||
|
||||
static void buffer_vpx_packets(vpx_context_t *context, switch_frame_t *frame)
|
||||
static switch_status_t buffer_vpx_packets(vpx_context_t *context, switch_frame_t *frame)
|
||||
{
|
||||
uint8_t *data = frame->data;
|
||||
uint8_t S;
|
||||
|
@ -410,7 +428,7 @@ static void buffer_vpx_packets(vpx_context_t *context, switch_frame_t *frame)
|
|||
|
||||
if (!frame) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "no frame in codec!!\n");
|
||||
return;
|
||||
return SWITCH_STATUS_RESTART;
|
||||
}
|
||||
|
||||
DES = *data;
|
||||
|
@ -431,106 +449,119 @@ static void buffer_vpx_packets(vpx_context_t *context, switch_frame_t *frame)
|
|||
}
|
||||
|
||||
len = frame->datalen - (data - (uint8_t *)frame->data);
|
||||
|
||||
if (len <= 0) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid packet %d\n", len);
|
||||
switch_buffer_zero(context->vpx_packet_buffer);
|
||||
return;
|
||||
return SWITCH_STATUS_RESTART;
|
||||
}
|
||||
|
||||
if (S && (PID == 0)) {
|
||||
uint8_t keyframe;
|
||||
int is_keyframe = ((*data) & 0x01) ? 0 : 1;
|
||||
|
||||
keyframe = ((*data) & 0x01) ? 0 : 1;
|
||||
|
||||
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "[%d] PID: %d K:%d P:%d Inv:%d len: %d size:%d\n", frame->datalen, PID, keyframe, profile, invisible, len, size);
|
||||
|
||||
if (keyframe) {
|
||||
if (!context->got_key_frame) context->got_key_frame = 1;
|
||||
if (is_keyframe && !context->got_key_frame) {
|
||||
context->got_key_frame = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!context->got_key_frame) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Waiting for key frame\n");
|
||||
switch_set_flag(frame, SFF_WAIT_KEY_FRAME);
|
||||
return;
|
||||
return SWITCH_STATUS_RESTART;
|
||||
}
|
||||
|
||||
switch_buffer_write(context->vpx_packet_buffer, data, len);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
static switch_status_t switch_vpx_decode(switch_codec_t *codec, switch_frame_t *frame, switch_image_t **img, unsigned int *flag)
|
||||
static switch_status_t switch_vpx_decode(switch_codec_t *codec, switch_frame_t *frame)
|
||||
{
|
||||
vpx_context_t *context = (vpx_context_t *)codec->private_info;
|
||||
vpx_codec_ctx_t *decoder = &context->decoder;
|
||||
switch_size_t len;
|
||||
vpx_codec_ctx_t *decoder = NULL;
|
||||
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
||||
|
||||
if (!decoder) {
|
||||
if (!context->decoder_init) {
|
||||
init_codec(codec);
|
||||
}
|
||||
|
||||
if (!context->decoder_init) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "VPX decoder is not initialized!\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
decoder = &context->decoder;
|
||||
|
||||
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "len: %d ts: %" SWITCH_SIZE_T_FMT " mark:%d\n", frame->datalen, frame->timestamp, frame->m);
|
||||
|
||||
if (context->last_received_timestamp && context->last_received_timestamp != frame->timestamp &&
|
||||
(!frame->m) && (!context->last_received_complete_picture)) {
|
||||
// possible packet loss
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Packet Loss, skip previouse received frame (to avoid crash?)\n");
|
||||
switch_buffer_zero(context->vpx_packet_buffer);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Packet Loss, skip previous received frame (to avoid crash?)\n");
|
||||
switch_goto_status(SWITCH_STATUS_RESTART, end);
|
||||
}
|
||||
|
||||
context->last_received_timestamp = frame->timestamp;
|
||||
context->last_received_complete_picture = frame->m ? SWITCH_TRUE : SWITCH_FALSE;
|
||||
|
||||
buffer_vpx_packets(context, frame);
|
||||
status = buffer_vpx_packets(context, frame);
|
||||
|
||||
len = switch_buffer_inuse(context->vpx_packet_buffer);
|
||||
printf("READ buf:%ld got_key:%d st:%d m:%d\n", switch_buffer_inuse(context->vpx_packet_buffer), context->got_key_frame, status, frame->m);
|
||||
|
||||
if (frame->m && len) {
|
||||
if (status == SWITCH_STATUS_SUCCESS && frame->m && (len = switch_buffer_inuse(context->vpx_packet_buffer))) {
|
||||
uint8_t *data;
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
int corrupted = 0;
|
||||
int err;
|
||||
// int keyframe = 0;
|
||||
//int keyframe = 0;
|
||||
|
||||
printf("WTF %d %ld\n", frame->m, len);
|
||||
|
||||
switch_buffer_peek_zerocopy(context->vpx_packet_buffer, (void *)&data);
|
||||
// keyframe = (*data & 0x01) ? 0 : 1;
|
||||
//keyframe = (*data & 0x01) ? 0 : 1;
|
||||
|
||||
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "buffered: %" SWITCH_SIZE_T_FMT ", key: %d\n", len, keyframe);
|
||||
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "buffered: %" SWITCH_SIZE_T_FMT ", key: %d\n", len, keyframe);
|
||||
|
||||
err = vpx_codec_decode(decoder, data, (unsigned int)len, NULL, 0);
|
||||
|
||||
if (err != VPX_CODEC_OK) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error decoding %" SWITCH_SIZE_T_FMT " bytes, [%d:%d:%s]\n", len, err, decoder->err, decoder->err_detail);
|
||||
switch_set_flag(frame, SFF_WAIT_KEY_FRAME);
|
||||
context->got_key_frame = 0;
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "require key frame %d\n", context->got_key_frame);
|
||||
goto error;
|
||||
switch_goto_status(SWITCH_STATUS_RESTART, end);
|
||||
}
|
||||
|
||||
if (vpx_codec_control(decoder, VP8D_GET_FRAME_CORRUPTED, &corrupted) != VPX_CODEC_OK) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "VPX control error!\n");
|
||||
goto error;
|
||||
switch_goto_status(SWITCH_STATUS_RESTART, end);
|
||||
}
|
||||
|
||||
*img = (switch_image_t *)vpx_codec_get_frame(decoder, &iter);
|
||||
frame->img = (switch_image_t *) vpx_codec_get_frame(decoder, &iter);
|
||||
|
||||
if (!(*img) || corrupted) {
|
||||
if (!(frame->img) || corrupted) {
|
||||
switch_buffer_zero(context->vpx_packet_buffer);
|
||||
goto ok;
|
||||
switch_goto_status(SWITCH_STATUS_SUCCESS, end);
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%dx%d %dx%d\n", (*img)->w,(*img)->h, (*img)->d_w, (*img)->d_h);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%dx%d %dx%d\n", frame->img->w,frame->img->h, frame->img->d_w, frame->img->d_h);
|
||||
|
||||
switch_buffer_zero(context->vpx_packet_buffer);
|
||||
}
|
||||
|
||||
ok:
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
end:
|
||||
|
||||
error:
|
||||
if (status == SWITCH_STATUS_RESTART) {
|
||||
context->got_key_frame = 0;
|
||||
switch_buffer_zero(context->vpx_packet_buffer);
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_FALSE;
|
||||
if (!frame->img) {
|
||||
status = SWITCH_STATUS_MORE_DATA;
|
||||
}
|
||||
|
||||
if (!context->got_key_frame) {
|
||||
switch_set_flag(frame, SFF_WAIT_KEY_FRAME);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -50,25 +50,19 @@ static switch_status_t switch_yuv_init(switch_codec_t *codec, switch_codec_flag_
|
|||
}
|
||||
}
|
||||
|
||||
static switch_status_t switch_yuv_encode(switch_codec_t *codec,
|
||||
switch_image_t *img,
|
||||
void *encoded_data, uint32_t *encoded_data_len,
|
||||
unsigned int *flag)
|
||||
static switch_status_t switch_yuv_encode(switch_codec_t *codec, switch_frame_t *frame)
|
||||
{
|
||||
/* yuv encode is unclear, so return 0 for now */
|
||||
*encoded_data_len = 0;
|
||||
*flag |= SFF_MARKER;
|
||||
frame->datalen = 0;
|
||||
frame->m = 1;
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t switch_yuv_decode(switch_codec_t *codec,
|
||||
switch_frame_t *frame,
|
||||
switch_image_t **img,
|
||||
unsigned int *flag)
|
||||
static switch_status_t switch_yuv_decode(switch_codec_t *codec, switch_frame_t *frame)
|
||||
{
|
||||
switch_assert(frame);
|
||||
|
||||
*img = (switch_image_t *)frame->user_data;
|
||||
frame->img = (switch_image_t *)frame->user_data;
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -114,7 +114,6 @@ struct vlc_video_context {
|
|||
int height;
|
||||
int force_width;
|
||||
int force_height;
|
||||
int video_refresh_req;
|
||||
int channels;
|
||||
};
|
||||
|
||||
|
@ -243,6 +242,7 @@ static void vlc_video_unlock_callback(void *data, void *id, void *const *p_pixel
|
|||
|
||||
yuyv_to_i420(*p_pixels, context->img->img_data, context->width, context->height);
|
||||
|
||||
|
||||
switch_mutex_unlock(context->video_mutex);
|
||||
}
|
||||
|
||||
|
@ -267,13 +267,11 @@ static void vlc_video_channel_unlock_callback(void *data, void *id, void *const
|
|||
{
|
||||
vlc_video_context_t *context = (vlc_video_context_t *)data;
|
||||
|
||||
|
||||
switch_assert(id == NULL); /* picture identifier, not needed here */
|
||||
|
||||
if (context->channel && !switch_channel_test_flag(context->channel, CF_VIDEO)) return;
|
||||
|
||||
if (!context->img) context->img = switch_img_alloc(NULL, SWITCH_IMG_FMT_I420, context->width, context->height, 0);
|
||||
switch_assert(context->img);
|
||||
if (!context->img) context->img = switch_img_alloc(NULL, SWITCH_IMG_FMT_I420, context->width, context->height, 0); switch_assert(context->img);
|
||||
|
||||
yuyv_to_i420(*p_pixels, context->img->img_data, context->width, context->height);
|
||||
|
||||
|
@ -282,19 +280,15 @@ static void vlc_video_channel_unlock_callback(void *data, void *id, void *const
|
|||
|
||||
static void vlc_video_display_callback(void *data, void *id)
|
||||
{
|
||||
vlc_video_context_t *context = (vlc_video_context_t *) data;
|
||||
int32_t flag = 0;
|
||||
|
||||
/* VLC wants to display the video */
|
||||
|
||||
vlc_video_context_t *context = (vlc_video_context_t *) data;
|
||||
|
||||
if (context->channel && !switch_channel_test_flag(context->channel, CF_VIDEO)) return;
|
||||
|
||||
if (context->video_refresh_req > 0) {
|
||||
flag |= SFF_WAIT_KEY_FRAME;
|
||||
context->video_refresh_req--;
|
||||
}
|
||||
context->vid_frame->img = context->img;
|
||||
|
||||
switch_core_session_write_video_image(context->session, context->vid_frame, context->img, SWITCH_DEFAULT_VIDEO_SIZE, NULL);
|
||||
switch_core_session_write_video_frame(context->session, context->vid_frame, SWITCH_IO_FLAG_NONE, 0);
|
||||
}
|
||||
|
||||
unsigned video_format_setup_callback(void **opaque, char *chroma, unsigned *width, unsigned *height, unsigned *pitches, unsigned *lines)
|
||||
|
@ -321,6 +315,7 @@ unsigned video_format_setup_callback(void **opaque, char *chroma, unsigned *widt
|
|||
|
||||
frame_size = (*width) * (*height) * 4 * 2;
|
||||
context->raw_yuyv_data = malloc(frame_size);
|
||||
|
||||
if (context->raw_yuyv_data == NULL) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "memory error\n");
|
||||
return 0;
|
||||
|
@ -1200,7 +1195,7 @@ static switch_call_cause_t vlc_outgoing_channel(switch_core_session_t *session,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
start_core_video_thread(*new_session);
|
||||
switch_core_session_start_video_thread(*new_session);
|
||||
switch_channel_set_state(channel, CS_INIT);
|
||||
|
||||
if (switch_core_session_thread_launch(*new_session) != SWITCH_STATUS_SUCCESS) {
|
||||
|
@ -1390,7 +1385,7 @@ static switch_status_t vlc_receive_message(switch_core_session_t *session, switc
|
|||
case SWITCH_MESSAGE_INDICATE_JITTER_BUFFER:
|
||||
break;
|
||||
case SWITCH_MESSAGE_INDICATE_VIDEO_REFRESH_REQ:
|
||||
tech_pvt->context->video_refresh_req = 1;
|
||||
switch_core_media_gen_key_frame(session);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -788,9 +788,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_codec_decode(switch_codec_t *codec,
|
|||
return status;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_core_codec_encode_video(switch_codec_t *codec,
|
||||
switch_image_t *img,
|
||||
void *encoded_data, uint32_t *encoded_data_len, unsigned int *flag)
|
||||
SWITCH_DECLARE(switch_status_t) switch_core_codec_encode_video(switch_codec_t *codec, switch_frame_t *frame)
|
||||
{
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
|
||||
|
@ -809,7 +807,14 @@ SWITCH_DECLARE(switch_status_t) switch_core_codec_encode_video(switch_codec_t *c
|
|||
if (codec->mutex) switch_mutex_lock(codec->mutex);
|
||||
|
||||
if (codec->implementation->encode_video) {
|
||||
status = codec->implementation->encode_video(codec, img, encoded_data, encoded_data_len, flag);
|
||||
status = codec->implementation->encode_video(codec, frame);
|
||||
|
||||
if (frame->datalen) {
|
||||
frame->packetlen = frame->datalen + 12;
|
||||
frame->flags |= SFF_SAME_IMAGE;
|
||||
} else {
|
||||
frame->flags &= ~SFF_SAME_IMAGE;
|
||||
}
|
||||
}
|
||||
|
||||
if (codec->mutex) switch_mutex_unlock(codec->mutex);
|
||||
|
@ -818,9 +823,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_codec_encode_video(switch_codec_t *c
|
|||
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_core_codec_decode_video(switch_codec_t *codec,
|
||||
switch_frame_t *frame,
|
||||
switch_image_t **img, unsigned int *flag)
|
||||
SWITCH_DECLARE(switch_status_t) switch_core_codec_decode_video(switch_codec_t *codec, switch_frame_t *frame)
|
||||
{
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
|
||||
|
@ -840,7 +843,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_codec_decode_video(switch_codec_t *c
|
|||
if (codec->mutex) switch_mutex_lock(codec->mutex);
|
||||
|
||||
if (codec->implementation->decode_video) {
|
||||
status = codec->implementation->decode_video(codec, frame, img, flag);
|
||||
status = codec->implementation->decode_video(codec, frame);
|
||||
}
|
||||
if (codec->mutex) switch_mutex_unlock(codec->mutex);
|
||||
|
||||
|
|
|
@ -176,6 +176,7 @@ struct switch_media_handle_s {
|
|||
|
||||
switch_mutex_t *mutex;
|
||||
switch_mutex_t *sdp_mutex;
|
||||
switch_mutex_t *control_mutex;
|
||||
|
||||
const switch_codec_implementation_t *negotiated_codecs[SWITCH_MAX_CODECS];
|
||||
int num_negotiated_codecs;
|
||||
|
@ -196,6 +197,9 @@ struct switch_media_handle_s {
|
|||
switch_time_t video_last_key_time;
|
||||
switch_time_t video_init;
|
||||
switch_timer_t video_timer;
|
||||
switch_video_function_t video_function;
|
||||
void *video_user_data;
|
||||
int8_t video_function_running;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1510,7 +1514,7 @@ SWITCH_DECLARE(switch_status_t) switch_media_handle_create(switch_media_handle_t
|
|||
session->media_handle->mparams = params;
|
||||
|
||||
if (!session->media_handle->mparams->video_key_freq) {
|
||||
session->media_handle->mparams->video_key_freq = 15000000;
|
||||
session->media_handle->mparams->video_key_freq = 30000000;
|
||||
}
|
||||
|
||||
if (!session->media_handle->mparams->video_key_first) {
|
||||
|
@ -1524,6 +1528,7 @@ SWITCH_DECLARE(switch_status_t) switch_media_handle_create(switch_media_handle_t
|
|||
|
||||
switch_mutex_init(&session->media_handle->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
|
||||
switch_mutex_init(&session->media_handle->sdp_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
|
||||
switch_mutex_init(&session->media_handle->control_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
|
||||
|
||||
session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO].ssrc =
|
||||
(uint32_t) ((intptr_t) &session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO] + (uint32_t) time(NULL));
|
||||
|
@ -1804,14 +1809,12 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_read_frame(switch_core_session
|
|||
|
||||
engine = &smh->engines[type];
|
||||
|
||||
engine->read_frame.datalen = 0;
|
||||
|
||||
if (!engine->read_codec.implementation || !switch_core_codec_ready(&engine->read_codec)) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
switch_assert(engine->rtp_session != NULL);
|
||||
engine->read_frame.datalen = 0;
|
||||
|
||||
|
||||
if (!switch_channel_up_nosig(session->channel) || !switch_rtp_ready(engine->rtp_session) || switch_channel_test_flag(session->channel, CF_NOT_READY)) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
|
@ -1825,6 +1828,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_read_frame(switch_core_session
|
|||
}
|
||||
|
||||
|
||||
engine->read_frame.datalen = 0;
|
||||
engine->read_frame.flags = SFF_NONE;
|
||||
engine->read_frame.m = SWITCH_FALSE;
|
||||
engine->read_frame.img = NULL;
|
||||
|
||||
while (smh->media_flags[SCMF_RUNNING] && engine->read_frame.datalen == 0) {
|
||||
engine->read_frame.flags = SFF_NONE;
|
||||
|
||||
|
@ -4449,6 +4457,25 @@ static void *SWITCH_THREAD_FUNC video_helper_thread(switch_thread_t *thread, voi
|
|||
continue;
|
||||
}
|
||||
|
||||
if (smh->video_function) {
|
||||
int run = 0;
|
||||
|
||||
switch_mutex_lock(smh->control_mutex);
|
||||
if (smh->video_function_running == 0) {
|
||||
smh->video_function_running = 1;
|
||||
run = 1;
|
||||
}
|
||||
switch_mutex_unlock(smh->control_mutex);
|
||||
|
||||
if (run) {
|
||||
smh->video_function(session, smh->video_user_data);
|
||||
switch_mutex_lock(smh->control_mutex);
|
||||
smh->video_function = NULL;
|
||||
smh->video_user_data = NULL;
|
||||
smh->video_function_running = 0;
|
||||
switch_mutex_unlock(smh->control_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
status = switch_core_session_read_video_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
|
||||
|
||||
|
@ -4457,7 +4484,6 @@ static void *SWITCH_THREAD_FUNC video_helper_thread(switch_thread_t *thread, voi
|
|||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (switch_channel_test_flag(channel, CF_VIDEO_REFRESH_REQ)) {
|
||||
switch_core_session_refresh_video(session);
|
||||
switch_channel_clear_flag(channel, CF_VIDEO_REFRESH_REQ);
|
||||
|
@ -4467,14 +4493,6 @@ static void *SWITCH_THREAD_FUNC video_helper_thread(switch_thread_t *thread, voi
|
|||
continue;
|
||||
}
|
||||
|
||||
status = switch_core_session_video_thread_callback(session, read_frame);
|
||||
|
||||
if (status != SWITCH_STATUS_CONTINUE) {
|
||||
if (status == SWITCH_STATUS_SUCCESS) continue;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (switch_channel_test_flag(channel, CF_VIDEO_ECHO)) {
|
||||
switch_core_session_write_video_frame(session, read_frame, SWITCH_IO_FLAG_NONE, 0);
|
||||
}
|
||||
|
@ -4491,8 +4509,7 @@ static void *SWITCH_THREAD_FUNC video_helper_thread(switch_thread_t *thread, voi
|
|||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_core_media_start_video_thread(switch_core_session_t *session)
|
||||
SWITCH_DECLARE(switch_status_t) switch_core_session_start_video_thread(switch_core_session_t *session)
|
||||
{
|
||||
switch_threadattr_t *thd_attr = NULL;
|
||||
switch_memory_pool_t *pool = switch_core_session_get_pool(session);
|
||||
|
@ -4527,6 +4544,61 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_start_video_thread(switch_core
|
|||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(void) switch_core_media_start_video_function(switch_core_session_t *session, switch_video_function_t video_function, void *user_data)
|
||||
{
|
||||
switch_media_handle_t *smh;
|
||||
|
||||
if (!(smh = session->media_handle)) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch_mutex_lock(smh->control_mutex);
|
||||
if (!smh->video_function_running) {
|
||||
smh->video_function = video_function;
|
||||
smh->video_user_data = user_data;
|
||||
switch_core_session_video_reset(session);
|
||||
switch_core_session_start_video_thread(session);
|
||||
}
|
||||
switch_mutex_unlock(smh->control_mutex);
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(int) switch_core_media_check_video_function(switch_core_session_t *session)
|
||||
{
|
||||
switch_media_handle_t *smh;
|
||||
int r;
|
||||
|
||||
if (!(smh = session->media_handle)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch_mutex_lock(smh->control_mutex);
|
||||
r = (smh->video_function_running > 0);
|
||||
switch_mutex_unlock(smh->control_mutex);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(void) switch_core_media_end_video_function(switch_core_session_t *session)
|
||||
{
|
||||
switch_media_handle_t *smh;
|
||||
|
||||
if (!(smh = session->media_handle)) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch_mutex_lock(smh->control_mutex);
|
||||
if (smh->video_function_running > 0) {
|
||||
smh->video_function_running = -1;
|
||||
}
|
||||
switch_mutex_unlock(smh->control_mutex);
|
||||
|
||||
while(smh->video_function_running != 0) {
|
||||
switch_yield(10000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
>>>>>>> another refactoring pass, temp code still in place, WORK IN PROGRESS
|
||||
//?
|
||||
#define RA_PTR_LEN 512
|
||||
SWITCH_DECLARE(switch_status_t) switch_core_media_proxy_remote_addr(switch_core_session_t *session, const char *sdp_str)
|
||||
|
@ -4658,8 +4730,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_proxy_remote_addr(switch_core_
|
|||
!switch_channel_test_flag(session->channel, CF_WEBRTC)) {
|
||||
/* Reactivate the NAT buster flag. */
|
||||
switch_rtp_set_flag(v_engine->rtp_session, SWITCH_RTP_FLAG_AUTOADJ);
|
||||
switch_core_media_start_video_thread(session);
|
||||
|
||||
switch_core_session_start_video_thread(session);
|
||||
}
|
||||
if (switch_media_handle_test_media_flag(smh, SCMF_AUTOFIX_TIMING)) {
|
||||
v_engine->check_frames = 0;
|
||||
|
@ -5631,8 +5702,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
|
|||
v_engine->local_sdp_ip, v_engine->local_sdp_port, v_engine->cur_payload_map->remote_sdp_ip,
|
||||
v_engine->cur_payload_map->remote_sdp_port, v_engine->cur_payload_map->agreed_pt);
|
||||
|
||||
|
||||
switch_core_media_start_video_thread(session);
|
||||
switch_core_session_start_video_thread(session);
|
||||
switch_rtp_set_default_payload(v_engine->rtp_session, v_engine->cur_payload_map->agreed_pt);
|
||||
}
|
||||
}
|
||||
|
@ -5665,7 +5735,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
|
|||
!((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
|
||||
/* Reactivate the NAT buster flag. */
|
||||
switch_rtp_set_flag(v_engine->rtp_session, SWITCH_RTP_FLAG_AUTOADJ);
|
||||
switch_core_media_start_video_thread(session);
|
||||
switch_core_session_start_video_thread(session);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5764,8 +5834,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
|
|||
}
|
||||
|
||||
switch_rtp_set_payload_map(v_engine->rtp_session, &v_engine->payload_map);
|
||||
|
||||
switch_core_media_start_video_thread(session);
|
||||
switch_core_session_start_video_thread(session);
|
||||
switch_channel_set_flag(session->channel, CF_VIDEO);
|
||||
|
||||
if ((ssrc = switch_channel_get_variable(session->channel, "rtp_use_video_ssrc"))) {
|
||||
|
@ -7911,7 +7980,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_receive_message(switch_core_se
|
|||
case SWITCH_MESSAGE_INDICATE_VIDEO_REFRESH_REQ:
|
||||
{
|
||||
if (v_engine->rtp_session) {
|
||||
if (switch_rtp_test_flag(v_engine->rtp_session, SWITCH_RTP_FLAG_FIR)) {
|
||||
switch_rtp_video_refresh(v_engine->rtp_session);
|
||||
} else if (switch_rtp_test_flag(v_engine->rtp_session, SWITCH_RTP_FLAG_PLI)) {
|
||||
switch_rtp_video_loss(v_engine->rtp_session);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9454,77 +9527,34 @@ SWITCH_DECLARE(void) switch_core_session_set_image_write_callback(switch_core_se
|
|||
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)
|
||||
static switch_status_t raw_write_video(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
|
||||
{
|
||||
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_media_handle_t *smh;
|
||||
//switch_rtp_engine_t *v_engine;
|
||||
switch_io_event_hook_video_write_frame_t *ptr;
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
|
||||
switch_assert(session);
|
||||
|
||||
if (!(smh = session->media_handle)) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
if (session->endpoint_interface->io_routines->write_video_frame) {
|
||||
if ((status = session->endpoint_interface->io_routines->write_video_frame(session, frame, flags, stream_id)) == SWITCH_STATUS_SUCCESS) {
|
||||
for (ptr = session->event_hooks.video_write_frame; ptr; ptr = ptr->next) {
|
||||
if ((status = ptr->video_write_frame(session, frame, flags, stream_id)) != SWITCH_STATUS_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
|
||||
|
||||
|
||||
if (!flag) {
|
||||
flagp = &lflag;
|
||||
}
|
||||
|
||||
if (!(timer = switch_core_media_get_timer(session, SWITCH_MEDIA_TYPE_VIDEO))) {
|
||||
|
||||
if (!smh->video_timer.timer_interface) {
|
||||
switch_core_timer_init(&smh->video_timer, "soft", 1, 90, switch_core_session_get_pool(session));
|
||||
}
|
||||
|
||||
timer = &smh->video_timer;
|
||||
}
|
||||
|
||||
|
||||
do {
|
||||
encoded_data_len = size;
|
||||
switch_core_codec_encode_video(codec, img, frame->data, &encoded_data_len, flagp);
|
||||
|
||||
if (*flagp & SFF_PICTURE_RESET) {
|
||||
smh->video_init = 0;
|
||||
smh->video_last_key_time = 0;
|
||||
*flagp &= ~SFF_PICTURE_RESET;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
img = NULL;
|
||||
|
||||
} while(encoded_data_len);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
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_io_event_hook_video_write_frame_t *ptr;
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
switch_media_handle_t *smh;
|
||||
|
||||
switch_time_t now = switch_micro_time_now();
|
||||
switch_codec_t *codec = switch_core_session_get_video_write_codec(session);
|
||||
switch_timer_t *timer;
|
||||
switch_media_handle_t *smh;
|
||||
switch_image_t *img = frame->img;
|
||||
|
||||
switch_assert(session);
|
||||
|
||||
|
@ -9555,15 +9585,43 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_video_frame(switch_cor
|
|||
smh->video_last_key_time = now;
|
||||
}
|
||||
|
||||
if (session->endpoint_interface->io_routines->write_video_frame) {
|
||||
if ((status = session->endpoint_interface->io_routines->write_video_frame(session, frame, flags, stream_id)) == SWITCH_STATUS_SUCCESS) {
|
||||
for (ptr = session->event_hooks.video_write_frame; ptr; ptr = ptr->next) {
|
||||
if ((status = ptr->video_write_frame(session, frame, flags, stream_id)) != SWITCH_STATUS_SUCCESS) {
|
||||
break;
|
||||
if (!img) {
|
||||
return raw_write_video(session, frame, flags, stream_id);
|
||||
}
|
||||
|
||||
if (!(timer = switch_core_media_get_timer(session, SWITCH_MEDIA_TYPE_VIDEO))) {
|
||||
|
||||
if (!smh->video_timer.timer_interface) {
|
||||
switch_core_timer_init(&smh->video_timer, "soft", 1, 90, switch_core_session_get_pool(session));
|
||||
}
|
||||
|
||||
timer = &smh->video_timer;
|
||||
}
|
||||
|
||||
frame->timestamp = timer->samplecount;
|
||||
frame->flags &= ~SFF_SAME_IMAGE;
|
||||
|
||||
do {
|
||||
frame->datalen = SWITCH_DEFAULT_VIDEO_SIZE;
|
||||
switch_core_codec_encode_video(codec, frame);
|
||||
|
||||
if (frame->flags & SFF_PICTURE_RESET) {
|
||||
smh->video_init = 0;
|
||||
smh->video_last_key_time = 0;
|
||||
frame->flags &= ~SFF_PICTURE_RESET;
|
||||
}
|
||||
|
||||
switch_set_flag(frame, SFF_RAW_RTP_PARSE_FRAME);
|
||||
|
||||
status = raw_write_video(session, frame, flags, stream_id);
|
||||
|
||||
if (status == SWITCH_STATUS_SUCCESS && session->image_write_callback) {
|
||||
session->image_write_callback(session, frame, img, session->image_write_callback_user_data);
|
||||
}
|
||||
|
||||
} while(frame->datalen);
|
||||
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -9572,10 +9630,15 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_video_frame(switch_core
|
|||
{
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
switch_io_event_hook_video_read_frame_t *ptr;
|
||||
uint32_t loops = 0;
|
||||
|
||||
switch_assert(session != NULL);
|
||||
|
||||
if (switch_channel_down(session->channel)) {
|
||||
top:
|
||||
|
||||
loops++;
|
||||
|
||||
if (switch_channel_down_nosig(session->channel)) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
|
@ -9657,6 +9720,20 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_video_frame(switch_core
|
|||
}
|
||||
}
|
||||
|
||||
if (switch_channel_test_flag(session->channel, CF_VIDEO_DECODED_READ)) {
|
||||
switch_status_t decode_status = switch_core_codec_decode_video((*frame)->codec, *frame);
|
||||
|
||||
if (switch_test_flag((*frame), SFF_WAIT_KEY_FRAME)) {
|
||||
switch_core_session_refresh_video(session);
|
||||
switch_clear_flag((*frame), SFF_WAIT_KEY_FRAME);
|
||||
}
|
||||
|
||||
if (decode_status == SWITCH_STATUS_MORE_DATA) {
|
||||
printf("mo data\n");
|
||||
goto top;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
return status;
|
||||
|
|
|
@ -2676,6 +2676,7 @@ SWITCH_DECLARE(void) switch_core_session_video_reset(switch_core_session_t *sess
|
|||
{
|
||||
switch_channel_set_flag(session->channel, CF_VIDEO_ECHO);
|
||||
switch_channel_clear_flag(session->channel, CF_VIDEO_PASSIVE);
|
||||
switch_channel_clear_flag(session->channel, CF_VIDEO_DECODED_READ);
|
||||
switch_core_session_refresh_video(session);
|
||||
session->image_write_callback = NULL;
|
||||
session->image_write_callback_user_data = NULL;
|
||||
|
@ -3065,31 +3066,6 @@ SWITCH_DECLARE(void) switch_core_session_debug_pool(switch_stream_handle_t *stre
|
|||
session_manager.running, session_manager.busy, session_manager.popping);
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_core_session_set_video_thread_callback(switch_core_session_t *session, switch_core_video_thread_callback_func_t *func, void *user_data)
|
||||
{
|
||||
if (!func) {
|
||||
session->_video_thread_callback = NULL;
|
||||
session->_video_thread_user_data = NULL;
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
} else if (session->_video_thread_callback) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
} else {
|
||||
session->_video_thread_callback = func;
|
||||
session->_video_thread_user_data = user_data;
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_core_session_video_thread_callback(switch_core_session_t *session, switch_frame_t *frame)
|
||||
{
|
||||
if (session->_video_thread_callback) {
|
||||
return session->_video_thread_callback(session, frame, session->_video_thread_user_data);
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
|
|
|
@ -46,38 +46,47 @@ struct vid_helper {
|
|||
int up;
|
||||
};
|
||||
|
||||
static void *SWITCH_THREAD_FUNC video_bridge_thread(switch_thread_t *thread, void *obj)
|
||||
static void video_bridge_thread(switch_core_session_t *session, void *obj)
|
||||
{
|
||||
struct vid_helper *vh = obj;
|
||||
switch_channel_t *channel = switch_core_session_get_channel(vh->session_a);
|
||||
switch_channel_t *b_channel = switch_core_session_get_channel(vh->session_b);
|
||||
switch_status_t status;
|
||||
switch_frame_t *read_frame = 0;
|
||||
const char *source = switch_channel_get_variable(channel, "source");
|
||||
const char *b_source = switch_channel_get_variable(b_channel, "source");
|
||||
|
||||
vh->up = 1;
|
||||
|
||||
switch_core_session_read_lock(vh->session_a);
|
||||
switch_core_session_read_lock(vh->session_b);
|
||||
|
||||
if (!switch_stristr("loopback", source) && !switch_stristr("loopback", b_source)) {
|
||||
switch_channel_set_flag(channel, CF_VIDEO_PASSIVE);
|
||||
//switch_channel_set_flag(b_channel, CF_VIDEO_PASSIVE);
|
||||
}
|
||||
|
||||
switch_core_session_refresh_video(vh->session_a);
|
||||
switch_core_session_refresh_video(vh->session_b);
|
||||
|
||||
while (switch_channel_up_nosig(channel) && switch_channel_up_nosig(b_channel) && vh->up == 1) {
|
||||
|
||||
if (switch_channel_media_up(channel)) {
|
||||
switch_codec_t *a_codec = switch_core_session_get_video_read_codec(vh->session_a);
|
||||
switch_codec_t *b_codec = switch_core_session_get_video_write_codec(vh->session_b);
|
||||
|
||||
if (!b_codec || !a_codec || a_codec->implementation->impl_id == b_codec->implementation->impl_id) {
|
||||
//switch_channel_clear_flag(channel, CF_VIDEO_DECODED_READ);
|
||||
} else {
|
||||
//switch_channel_set_flag(channel, CF_VIDEO_DECODED_READ);
|
||||
}
|
||||
|
||||
switch_channel_set_flag(channel, CF_VIDEO_DECODED_READ);
|
||||
|
||||
status = switch_core_session_read_video_frame(vh->session_a, &read_frame, SWITCH_IO_FLAG_NONE, 0);
|
||||
|
||||
if (!SWITCH_READ_ACCEPTABLE(status)) {
|
||||
switch_cond_next();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!switch_test_flag(read_frame, SFF_CNG)) {
|
||||
switch_core_session_write_video_frame(vh->session_a, read_frame, SWITCH_IO_FLAG_NONE, 0);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (switch_test_flag(read_frame, SFF_CNG)) {
|
||||
|
@ -93,9 +102,6 @@ static void *SWITCH_THREAD_FUNC video_bridge_thread(switch_thread_t *thread, voi
|
|||
|
||||
}
|
||||
|
||||
switch_channel_clear_flag(channel, CF_VIDEO_PASSIVE);
|
||||
//switch_channel_clear_flag(b_channel, CF_VIDEO_PASSIVE);
|
||||
|
||||
switch_core_session_kill_channel(vh->session_b, SWITCH_SIG_BREAK);
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(vh->session_a), SWITCH_LOG_DEBUG, "%s video thread ended.\n", switch_channel_get_name(channel));
|
||||
|
||||
|
@ -106,18 +112,12 @@ static void *SWITCH_THREAD_FUNC video_bridge_thread(switch_thread_t *thread, voi
|
|||
switch_core_session_rwunlock(vh->session_b);
|
||||
|
||||
vh->up = 0;
|
||||
return NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
static switch_thread_t *launch_video(struct vid_helper *vh)
|
||||
static void launch_video(struct vid_helper *vh)
|
||||
{
|
||||
switch_thread_t *thread;
|
||||
switch_threadattr_t *thd_attr = NULL;
|
||||
|
||||
switch_threadattr_create(&thd_attr, switch_core_session_get_pool(vh->session_a));
|
||||
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
|
||||
switch_thread_create(&thread, thd_attr, video_bridge_thread, vh, switch_core_session_get_pool(vh->session_a));
|
||||
return thread;
|
||||
switch_core_media_start_video_function(vh->session_a, video_bridge_thread, vh);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -229,7 +229,6 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
|
|||
const char *exec_data = NULL;
|
||||
|
||||
#ifdef SWITCH_VIDEO_IN_THREADS
|
||||
switch_thread_t *vid_thread = NULL;
|
||||
struct vid_helper vh = { 0 };
|
||||
uint32_t vid_launch = 0;
|
||||
#endif
|
||||
|
@ -247,6 +246,9 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
|
|||
chan_a = switch_core_session_get_channel(session_a);
|
||||
chan_b = switch_core_session_get_channel(session_b);
|
||||
|
||||
switch_channel_clear_flag(chan_a, CF_VIDEO_ECHO);
|
||||
switch_channel_clear_flag(chan_b, CF_VIDEO_ECHO);
|
||||
|
||||
|
||||
if ((exec_app = switch_channel_get_variable(chan_a, "bridge_pre_execute_app"))) {
|
||||
exec_data = switch_channel_get_variable(chan_a, "bridge_pre_execute_data");
|
||||
|
@ -410,7 +412,10 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
|
|||
vid_launch++;
|
||||
vh.session_a = session_a;
|
||||
vh.session_b = session_b;
|
||||
vid_thread = launch_video(&vh);
|
||||
//DFF TEMP
|
||||
if (switch_channel_test_flag(chan_a, CF_BRIDGE_ORIGINATOR)) {
|
||||
launch_video(&vh);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -590,7 +595,7 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
|
|||
end_of_bridge_loop:
|
||||
|
||||
#ifdef SWITCH_VIDEO_IN_THREADS
|
||||
if (vid_thread) {
|
||||
if (vh.up > 0) {
|
||||
vh.up = -1;
|
||||
switch_channel_set_flag(chan_a, CF_NOT_READY);
|
||||
//switch_channel_set_flag(chan_b, CF_NOT_READY);
|
||||
|
@ -634,9 +639,7 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
|
|||
end:
|
||||
|
||||
#ifdef SWITCH_VIDEO_IN_THREADS
|
||||
if (vid_thread) {
|
||||
switch_status_t st;
|
||||
|
||||
if (switch_core_media_check_video_function(session_a)) {
|
||||
if (vh.up == 1) {
|
||||
vh.up = -1;
|
||||
}
|
||||
|
@ -647,7 +650,7 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
|
|||
switch_core_session_kill_channel(session_b, SWITCH_SIG_BREAK);
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_a), SWITCH_LOG_DEBUG, "Ending video thread.\n");
|
||||
switch_thread_join(&st, vid_thread);
|
||||
switch_core_media_end_video_function(session_a);
|
||||
switch_channel_clear_flag(chan_a, CF_NOT_READY);
|
||||
switch_channel_clear_flag(chan_b, CF_NOT_READY);
|
||||
}
|
||||
|
@ -689,6 +692,9 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
|
|||
|
||||
switch_core_session_kill_channel(session_b, SWITCH_SIG_BREAK);
|
||||
data->done = 1;
|
||||
switch_core_session_video_reset(session_a);
|
||||
switch_core_session_video_reset(session_b);
|
||||
|
||||
switch_core_session_rwunlock(session_b);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -1444,7 +1444,7 @@ static uint8_t get_next_write_ts(switch_rtp_t *rtp_session, uint32_t timestamp)
|
|||
static void send_fir(switch_rtp_t *rtp_session)
|
||||
{
|
||||
|
||||
if (!rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] && rtp_session->ice.ice_user) {
|
||||
if (!rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1557,7 +1557,7 @@ static void send_fir(switch_rtp_t *rtp_session)
|
|||
static void send_pli(switch_rtp_t *rtp_session)
|
||||
{
|
||||
|
||||
if (!rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] && rtp_session->ice.ice_user) {
|
||||
if (!rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2035,7 +2035,6 @@ static int check_rtcp_and_ice(switch_rtp_t *rtp_session)
|
|||
}
|
||||
|
||||
if (rtp_session->pli_countdown) {
|
||||
|
||||
if (rtp_session->pli_countdown == PLI_COUNTDOWN || (rtp_session->pli_countdown == PLI_COUNTDOWN / 2) || rtp_session->pli_countdown == 1) {
|
||||
send_pli(rtp_session);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue