Changeset 3847


Ignore:
Timestamp:
Oct 25, 2011 4:36:46 AM (12 years ago)
Author:
bennylp
Message:

More #1394: fixed deadlock when format change is reported by vid_stream, which cause the clock to stop. It waits for the callback to return, but the callback is waiting to lock the jb_mutex, which is currently being held by the stopping clock. The workaround is to queue the event and report it later

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/src/pjmedia/vid_stream.c

    r3837 r3847  
    122122    unsigned                 dec_max_size;  /**< Size of decoded/raw picture*/ 
    123123    pjmedia_frame            dec_frame;     /**< Current decoded frame.     */ 
     124    pjmedia_event            fmt_event;     /**< Buffered fmt_changed event 
     125                                                 to avoid deadlock          */ 
    124126 
    125127    unsigned                 frame_size;    /**< Size of encoded base frame.*/ 
     
    347349        switch (event->type) { 
    348350        case PJMEDIA_EVENT_FMT_CHANGED: 
    349             /* Update param from codec */ 
    350             pjmedia_vid_codec_get_param(stream->codec, stream->info.codec_param); 
    351  
    352             /* Update decoding channel port info */ 
    353             pjmedia_format_copy(&stream->dec->port.info.fmt, 
    354                                 &stream->info.codec_param->dec_fmt); 
    355  
    356351            /* we process the event */ 
    357352            ++event->proc_cnt; 
    358353 
    359             dump_port_info(event->data.fmt_changed.dir==PJMEDIA_DIR_DECODING ? 
    360                             stream->dec : stream->enc, 
    361                           "changed"); 
    362             break; 
     354            /* Copy the event to avoid deadlock if we publish the event 
     355             * now. This happens because fmt_event may trigger restart 
     356             * while we're still holding the jb_mutex. 
     357             */ 
     358            pj_memcpy(&stream->fmt_event, event, sizeof(*event)); 
     359            return PJ_SUCCESS; 
    363360        default: 
    364361            break; 
     
    10711068        frame->size = 0; 
    10721069        return PJ_SUCCESS; 
     1070    } 
     1071 
     1072    /* Report pending events. Do not publish the event while holding the 
     1073     * jb_mutex as that would lead to deadlock. It should be safe to 
     1074     * operate on fmt_event without the mutex because format change normally 
     1075     * would only occur once during the start of the media. 
     1076     */ 
     1077    if (stream->fmt_event.type != PJMEDIA_EVENT_NONE) { 
     1078        /* Update param from codec */ 
     1079        pjmedia_vid_codec_get_param(stream->codec, stream->info.codec_param); 
     1080 
     1081        /* Update decoding channel port info */ 
     1082        pjmedia_format_copy(&stream->dec->port.info.fmt, 
     1083                            &stream->info.codec_param->dec_fmt); 
     1084 
     1085        dump_port_info(stream->fmt_event.data.fmt_changed.dir==PJMEDIA_DIR_DECODING ? 
     1086                        stream->dec : stream->enc, 
     1087                      "changed"); 
     1088 
     1089        pjmedia_event_publish(&stream->epub, &stream->fmt_event); 
     1090 
     1091        stream->fmt_event.type = PJMEDIA_EVENT_NONE; 
    10731092    } 
    10741093 
Note: See TracChangeset for help on using the changeset viewer.