Fix memory leak in MediaFoundation

Fix SDP renegotiation issue
Fix deadlock in BFCP video producer (when stopped while encoding)
This commit is contained in:
bossiel 2014-05-21 05:51:30 +00:00
parent a28212a852
commit 5f80c12eed
5 changed files with 61 additions and 33 deletions

View File

@ -575,11 +575,9 @@ static int _plugin_win_mf_producer_video_unprepare(plugin_win_mf_producer_video_
}
if(pSelf->pSource){
pSelf->pSource->Shutdown();
pSelf->pSource = NULL;
}
if(pSelf->pSession){
pSelf->pSession->Shutdown();
pSelf->pSession = NULL;
}
SafeRelease(&pSelf->pEncoder);

View File

@ -51,6 +51,7 @@ typedef struct tdav_session_video_s
tsk_bool_t jb_enabled;
tsk_bool_t zero_artifacts;
tsk_bool_t fps_changed;
tsk_bool_t started;
struct{
const void* context;

View File

@ -274,13 +274,13 @@ static int _tdav_producer_screencast_grab(tdav_producer_screencast_gdi_t* p_self
hSrcDC = GetDC(p_self->hwnd_src);
if (!hSrcDC) {
TSK_DEBUG_ERROR("GetDC(%llu) failed", *((uint64_t*)p_self->hwnd_src));
TSK_DEBUG_ERROR("GetDC(%x) failed", p_self->hwnd_src);
ret = -5;
goto bail;
}
hMemDC = CreateCompatibleDC(hSrcDC);
if (!hMemDC) {
TSK_DEBUG_ERROR("CreateCompatibleDC(%llu) failed", *((uint64_t*)hSrcDC));
TSK_DEBUG_ERROR("CreateCompatibleDC(%x) failed", hSrcDC);
ret = -6;
goto bail;
}
@ -374,7 +374,7 @@ static int _tdav_producer_screencast_grab(tdav_producer_screencast_gdi_t* p_self
}
}
// encode and send
// encode and send data
TMEDIA_PRODUCER(p_self)->enc_cb.callback(TMEDIA_PRODUCER(p_self)->enc_cb.callback_data, p_self->p_buff_neg, p_self->bitmapInfoNeg.bmiHeader.biSizeImage);
bail:

View File

@ -347,7 +347,13 @@ static int tdav_session_video_producer_enc_cb(const void* callback_data, const v
// do nothing if session is held
// when the session is held the end user will get feedback he also has possibilities to put the consumer and producer on pause
if(TMEDIA_SESSION(base)->lo_held){
if (TMEDIA_SESSION(base)->lo_held) {
return 0;
}
// do nothing if not started yet
if (!video->started) {
TSK_DEBUG_INFO("Video session not started yet");
return 0;
}
@ -1053,7 +1059,7 @@ static int tdav_session_video_start(tmedia_session_t* self)
tdav_session_av_t* base;
tmedia_param_t* media_param;
if(!self){
if (!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
@ -1062,7 +1068,7 @@ static int tdav_session_video_start(tmedia_session_t* self)
base = (tdav_session_av_t*)self;
// ENCODER codec
if(!(codec = tdav_session_av_get_best_neg_codec(base))){
if (!(codec = tdav_session_av_get_best_neg_codec(base))) {
TSK_DEBUG_ERROR("No codec matched");
return -2;
}
@ -1083,18 +1089,18 @@ static int tdav_session_video_start(tmedia_session_t* self)
}
tsk_mutex_unlock(video->encoder.h_mutex);
if(video->jb){
if((ret = tdav_video_jb_start(video->jb))){
if (video->jb) {
if ((ret = tdav_video_jb_start(video->jb))) {
TSK_DEBUG_ERROR("Failed to start jitter buffer");
return ret;
}
}
if((ret = tdav_session_av_start(base, video->encoder.codec))){
if ((ret = tdav_session_av_start(base, video->encoder.codec))) {
TSK_DEBUG_ERROR("tdav_session_av_start(video) failed");
return ret;
}
video->started = tsk_true;
return ret;
}
@ -1108,8 +1114,11 @@ static int tdav_session_video_stop(tmedia_session_t* self)
video = (tdav_session_video_t*)self;
base = (tdav_session_av_t*)self;
// must be here to make sure not other thread will lock the encoder once we have done it
video->started = tsk_false;
if(video->jb){
if (video->jb) {
ret = tdav_video_jb_stop(video->jb);
}
// clear AVPF packets and wait for the dtor() before destroying the list

View File

@ -53,7 +53,9 @@ const tmedia_session_plugin_def_t* __tmedia_session_plugins[TMED_SESSION_MAX_PLU
/* === local functions === */
static int _tmedia_session_mgr_recv_rtcp_event(tmedia_session_mgr_t* self, tmedia_type_t media_type, tmedia_rtcp_event_type_t event_type, uint32_t ssrc_media, uint64_t session_id);
static int _tmedia_session_mgr_load_sessions(tmedia_session_mgr_t* self);
static int _tmedia_session_mgr_disable_session_with_type(tmedia_session_mgr_t* self, tmedia_type_t media_type);
static int _tmedia_session_mgr_disable_or_enable_session_with_type(tmedia_session_mgr_t* self, tmedia_type_t media_type, tsk_bool_t enable);
#define _tmedia_session_mgr_disable_session_with_type(self, media_type) _tmedia_session_mgr_disable_or_enable_session_with_type((self), (media_type), tsk_false)
#define _tmedia_session_mgr_enable_session_with_type(self, media_type) _tmedia_session_mgr_disable_or_enable_session_with_type((self), (media_type), tsk_true)
static const tmedia_session_t* _tmedia_session_mgr_find_session_at_index(const tmedia_sessions_L_t* list, tsk_size_t index);
static int _tmedia_session_mgr_clear_sessions(tmedia_session_mgr_t* self);
static int _tmedia_session_mgr_apply_params(tmedia_session_mgr_t* self);
@ -1988,23 +1990,32 @@ static int _tmedia_session_mgr_load_sessions(tmedia_session_mgr_t* self)
//while (tsk_list_remove_item_by_pred(self->sessions, __pred_find_session_by_type, &__none_media_type)) ;
/* for each registered plugin create a session instance */
while ((i < TMED_SESSION_MAX_PLUGINS) && (plugin = __tmedia_session_plugins[i++])) {
if ((plugin->type & self->type) == plugin->type && !has_media(plugin->type)) {// we don't have a session with this media type yet
if ((session = tmedia_session_create(plugin->type))) {
/* do not call "tmedia_session_mgr_set()" here to avoid applying parms before the creation of all session */
if ((plugin->type & self->type) == plugin->type) { /* media_type *IS* enabled */
if (has_media(plugin->type)) {
// we already have a matching media session -> enable it if not already done
_tmedia_session_mgr_enable_session_with_type(self, plugin->type);
}
else {
// we don't have a matching media session yet
if ((session = tmedia_session_create(plugin->type))) {
/* do not call "tmedia_session_mgr_set()" here to avoid applying parms before the creation of all session */
/* set other default values */
/* set other default values */
// set callback functions
tmedia_session_set_onerror_cbfn(session, self->onerror_cb.usrdata, self->onerror_cb.fun);
/* push session */
tsk_list_push_back_data(self->sessions, (void**)(&session));
// set callback functions
tmedia_session_set_onerror_cbfn(session, self->onerror_cb.usrdata, self->onerror_cb.fun);
/* push session */
tsk_list_push_back_data(self->sessions, (void**)(&session));
}
}
}
else if (!(plugin->type & self->type) && has_media(plugin->type)) { // we have media session from previous call (before update)
// do not remove to make sure media indexes match -> see rfc 3264 section 8
// tsk_list_remove_item_by_pred(self->sessions, __pred_find_session_by_type, &(plugin->type));
_tmedia_session_mgr_disable_session_with_type(self, plugin->type);
else { /* media_type *IS NOT* enabled */
if (has_media(plugin->type)) {
// do not remove to make sure media indexes match -> see rfc 3264 section 8
// tsk_list_remove_item_by_pred(self->sessions, __pred_find_session_by_type, &(plugin->type));
_tmedia_session_mgr_disable_session_with_type(self, plugin->type);
}
}
}
/* set default values and apply params*/
@ -2037,7 +2048,7 @@ static const tmedia_session_t* _tmedia_session_mgr_find_session_at_index(const t
}
/* internal function */
static int _tmedia_session_mgr_disable_session_with_type(tmedia_session_mgr_t* self, tmedia_type_t media_type)
static int _tmedia_session_mgr_disable_or_enable_session_with_type(tmedia_session_mgr_t* self, tmedia_type_t media_type, tsk_bool_t enable)
{
tsk_list_item_t *item;
tmedia_session_t *session;
@ -2045,13 +2056,22 @@ static int _tmedia_session_mgr_disable_session_with_type(tmedia_session_mgr_t* s
tsk_list_foreach(item, self->sessions) {
if ((session = (tmedia_session_t*)item->data) && session->plugin && session->plugin->type == media_type) {
if (session->plugin->stop) {
session->plugin->stop(session);
if (enable) {
if (session->M.lo && !session->M.lo->port) {
TSK_OBJECT_SAFE_FREE(session->M.ro);
TSK_OBJECT_SAFE_FREE(session->M.lo);
session->prepared = tsk_false;
}
}
if (session->M.lo) {
session->M.lo->port = 0;
else {
if (session->plugin->stop) {
session->plugin->stop(session);
}
if (session->M.lo) {
session->M.lo->port = 0;
}
session->prepared = tsk_false;
}
session->prepared = tsk_false;
}
}