static event_t * rtmp_process_event(rtmp_t *r, event_t *e, media_buf_t **mbp) { media_pipe_t *mp = r->mp; if(event_is_type(e, EVENT_EXIT) || event_is_type(e, EVENT_PLAY_URL) || event_is_action(e, ACTION_SKIP_FORWARD)) return e; if(event_is_action(e, ACTION_SKIP_BACKWARD)) { if(mp->mp_seek_base < MP_SKIP_LIMIT) { return e; } video_seek(r, mp, mbp, 0, "direct"); } if(event_is_type(e, EVENT_CURRENT_TIME)) { event_ts_t *ets = (event_ts_t *)e; int sec = ets->ts / 1000000; if(sec != r->restartpos_last && r->can_seek) { r->restartpos_last = sec; metadb_set_video_restartpos(r->canonical_url, mp->mp_seek_base / 1000); } } else if(r->can_seek && event_is_type(e, EVENT_SEEK)) { event_ts_t *ets = (event_ts_t *)e; video_seek(r, mp, mbp, ets->ts, "direct"); } else if(event_is_action(e, ACTION_STOP)) { mp_set_playstatus_stop(mp); } else if(event_is_type(e, EVENT_SELECT_SUBTITLE_TRACK)) { event_select_track_t *est = (event_select_track_t *)e; prop_set_string(mp->mp_prop_subtitle_track_current, est->id); if(!strcmp(est->id, "sub:off")) { mp_load_ext_sub(mp, NULL); } else { mp_load_ext_sub(mp, est->id); } } event_release(e); return NULL; }
static event_t * rtmp_process_event(rtmp_t *r, event_t *e, media_buf_t **mbp) { media_pipe_t *mp = r->mp; if(event_is_type(e, EVENT_EXIT) || event_is_type(e, EVENT_PLAY_URL)) return e; if(event_is_action(e, ACTION_PLAYPAUSE) || event_is_action(e, ACTION_PLAY) || event_is_action(e, ACTION_PAUSE)) { r->hold = action_update_hold_by_event(r->hold, e); mp_send_cmd_head(mp, &mp->mp_video, r->hold ? MB_CTRL_PAUSE : MB_CTRL_PLAY); mp_send_cmd_head(mp, &mp->mp_audio, r->hold ? MB_CTRL_PAUSE : MB_CTRL_PLAY); mp_set_playstatus_by_hold(mp, r->hold, NULL); r->lost_focus = 0; } else if(event_is_type(e, EVENT_MP_NO_LONGER_PRIMARY)) { r->hold = 1; r->lost_focus = 1; mp_send_cmd_head(mp, &mp->mp_video, MB_CTRL_PAUSE); mp_send_cmd_head(mp, &mp->mp_audio, MB_CTRL_PAUSE); mp_set_playstatus_by_hold(mp, r->hold, e->e_payload); } else if(event_is_type(e, EVENT_MP_IS_PRIMARY)) { if(r->lost_focus) { r->hold = 0; r->lost_focus = 0; mp_send_cmd_head(mp, &mp->mp_video, MB_CTRL_PLAY); mp_send_cmd_head(mp, &mp->mp_audio, MB_CTRL_PLAY); mp_set_playstatus_by_hold(mp, r->hold, NULL); } } else if(event_is_type(e, EVENT_INTERNAL_PAUSE)) { r->hold = 1; r->lost_focus = 0; mp_send_cmd_head(mp, &mp->mp_video, MB_CTRL_PAUSE); mp_send_cmd_head(mp, &mp->mp_audio, MB_CTRL_PAUSE); mp_set_playstatus_by_hold(mp, r->hold, e->e_payload); } else if(event_is_type(e, EVENT_CURRENT_PTS)) { event_ts_t *ets = (event_ts_t *)e; r->seekbase = ets->ts; int sec = r->seekbase / 1000000; if(sec != r->restartpos_last && r->can_seek) { r->restartpos_last = sec; metadb_set_video_restartpos(r->canonical_url, r->seekbase / 1000); } } else if(r->can_seek && event_is_type(e, EVENT_SEEK)) { event_ts_t *ets = (event_ts_t *)e; r->epoch++; r->seekbase = video_seek(r, mp, mbp, ets->ts, 1, "direct"); } else if(r->can_seek && event_is_action(e, ACTION_SEEK_FAST_BACKWARD)) { r->seekbase = video_seek(r, mp, mbp, r->seekbase - 60000000, 1, "-60s"); } else if(r->can_seek && event_is_action(e, ACTION_SEEK_BACKWARD)) { r->seekbase = video_seek(r, mp, mbp, r->seekbase - 15000000, 1, "-15s"); } else if(r->can_seek && event_is_action(e, ACTION_SEEK_FORWARD)) { r->seekbase = video_seek(r, mp, mbp, r->seekbase + 15000000, 1, "+15s"); } else if(r->can_seek && event_is_action(e, ACTION_SEEK_FAST_FORWARD)) { r->seekbase = video_seek(r, mp, mbp, r->seekbase + 60000000, 1, "+60s"); } else if(event_is_action(e, ACTION_STOP)) { mp_set_playstatus_stop(mp); } else if(event_is_type(e, EVENT_SELECT_SUBTITLE_TRACK)) { event_select_track_t *est = (event_select_track_t *)e; prop_set_string(mp->mp_prop_subtitle_track_current, est->id); if(!strcmp(est->id, "sub:off")) { mp_load_ext_sub(mp, NULL); } else { mp_load_ext_sub(mp, est->id); } } event_release(e); return NULL; }
static event_t * rtmp_loop(rtmp_t *r, media_pipe_t *mp, char *url, char *errbuf, size_t errlen) { RTMPPacket p = {0}; int pos = -1, ret; uint32_t dts; event_t *e = NULL; mp_set_playstatus_by_hold(mp, 0, NULL); while(1) { if(pos == -1) { mp->mp_eof = 0; ret = RTMP_GetNextMediaPacket(r->r, &p); if(ret == 2) { /* Wait for queues to drain */ mp->mp_eof = 1; again: e = mp_wait_for_empty_queues(mp); if(e != NULL) { e = rtmp_process_event(r, e, NULL); if(e == NULL) goto again; } mp_set_playstatus_stop(mp); if(e == NULL) e = event_create_type(EVENT_EOF); break; } if(ret == 0) { RTMP_Close(r->r); RTMP_Init(r->r); memset(&p, 0, sizeof(p)); TRACE(TRACE_DEBUG, "RTMP", "Reconnecting stream at pos %d", r->seekbase); if(!RTMP_SetupURL(r->r, url)) { snprintf(errbuf, errlen, "Unable to setup RTMP session"); e = NULL; break; } if(!RTMP_Connect(r->r, NULL)) { snprintf(errbuf, errlen, "Unable to connect RTMP session"); e = NULL; break; } if(!RTMP_ConnectStream(r->r, r->can_seek ? r->seekbase / 1000 : 0)) { snprintf(errbuf, errlen, "Unable to stream RTMP session"); return NULL; } r->epoch++; r->lastdts = 0; r->seekbase = AV_NOPTS_VALUE; mp_flush(mp, 0); continue; } dts = p.m_nTimeStamp; switch(p.m_packetType) { case RTMP_PACKET_TYPE_INFO: if(handle_metadata(r, p.m_body, p.m_nBodySize, mp, errbuf, errlen)) { RTMPPacket_Free(&p); return NULL; } break; case RTMP_PACKET_TYPE_VIDEO: e = get_packet_v(r, (void *)p.m_body, p.m_nBodySize, dts, mp); break; case RTMP_PACKET_TYPE_AUDIO: e = get_packet_a(r, (void *)p.m_body, p.m_nBodySize, dts, mp); break; case 0x16: pos = 0; break; default: TRACE(TRACE_DEBUG, "RTMP", "Got unknown packet type %d\n", p.m_packetType); break; } if(pos == -1) RTMPPacket_Free(&p); } if(pos != -1) { if(pos + 11 < p.m_nBodySize) { uint32_t ds = AMF_DecodeInt24(p.m_body + pos + 1); if(pos + 11 + ds + 4 > p.m_nBodySize) { snprintf(errbuf, errlen, "Corrupt stream"); RTMPPacket_Free(&p); return NULL; } dts = AMF_DecodeInt24(p.m_body + pos + 4); dts |= (p.m_body[pos + 7] << 24); if(p.m_body[pos] == RTMP_PACKET_TYPE_INFO) { if(handle_metadata(r, p.m_body, p.m_nBodySize, mp, errbuf, errlen)) { RTMPPacket_Free(&p); return NULL; } } else if(p.m_body[pos] == RTMP_PACKET_TYPE_VIDEO) { e = get_packet_v(r, (void *)p.m_body + pos + 11, ds, dts, mp); } else if(p.m_body[pos] == RTMP_PACKET_TYPE_AUDIO) { e = get_packet_a(r, (void *)p.m_body + pos + 11, ds, dts, mp); } else { TRACE(TRACE_DEBUG, "RTMP", "Got unknown packet type %d\n", p.m_body[pos]); } pos += 11 + ds + 4; } else { pos = -1; RTMPPacket_Free(&p); } } if(e != NULL) break; } return e; }
static event_t * rtmp_process_event(rtmp_t *r, event_t *e, media_buf_t **mbp) { media_pipe_t *mp = r->mp; if(event_is_type(e, EVENT_EXIT) || event_is_type(e, EVENT_PLAY_URL)) return e; if(event_is_action(e, ACTION_PLAYPAUSE) || event_is_action(e, ACTION_PLAY) || event_is_action(e, ACTION_PAUSE)) { r->hold = action_update_hold_by_event(r->hold, e); mp_send_cmd_head(mp, &mp->mp_video, r->hold ? MB_CTRL_PAUSE : MB_CTRL_PLAY); mp_send_cmd_head(mp, &mp->mp_audio, r->hold ? MB_CTRL_PAUSE : MB_CTRL_PLAY); mp_set_playstatus_by_hold(mp, r->hold, NULL); r->lost_focus = 0; } else if(event_is_type(e, EVENT_MP_NO_LONGER_PRIMARY)) { r->hold = 1; r->lost_focus = 1; mp_send_cmd_head(mp, &mp->mp_video, MB_CTRL_PAUSE); mp_send_cmd_head(mp, &mp->mp_audio, MB_CTRL_PAUSE); mp_set_playstatus_by_hold(mp, r->hold, e->e_payload); } else if(event_is_type(e, EVENT_MP_IS_PRIMARY)) { if(r->lost_focus) { r->hold = 0; r->lost_focus = 0; mp_send_cmd_head(mp, &mp->mp_video, MB_CTRL_PLAY); mp_send_cmd_head(mp, &mp->mp_audio, MB_CTRL_PLAY); mp_set_playstatus_by_hold(mp, r->hold, NULL); } } else if(event_is_type(e, EVENT_INTERNAL_PAUSE)) { r->hold = 1; r->lost_focus = 0; mp_send_cmd_head(mp, &mp->mp_video, MB_CTRL_PAUSE); mp_send_cmd_head(mp, &mp->mp_audio, MB_CTRL_PAUSE); mp_set_playstatus_by_hold(mp, r->hold, e->e_payload); } else if(event_is_type(e, EVENT_CURRENT_PTS)) { event_ts_t *ets = (event_ts_t *)e; r->seekbase = ets->pts; } else if(event_is_type(e, EVENT_SEEK)) { event_ts_t *ets = (event_ts_t *)e; r->epoch++; r->seekbase = video_seek(r, mp, mbp, ets->pts, 1, "direct"); } else if(event_is_action(e, ACTION_SEEK_FAST_BACKWARD)) { r->seekbase = video_seek(r, mp, mbp, r->seekbase - 60000000, 1, "-60s"); } else if(event_is_action(e, ACTION_SEEK_BACKWARD)) { r->seekbase = video_seek(r, mp, mbp, r->seekbase - 15000000, 1, "-15s"); } else if(event_is_action(e, ACTION_SEEK_FORWARD)) { r->seekbase = video_seek(r, mp, mbp, r->seekbase + 15000000, 1, "+15s"); } else if(event_is_action(e, ACTION_SEEK_FAST_FORWARD)) { r->seekbase = video_seek(r, mp, mbp, r->seekbase + 60000000, 1, "+60s"); } else if(event_is_action(e, ACTION_STOP)) { mp_set_playstatus_stop(mp); } else if(event_is_type(e, EVENT_SELECT_TRACK)) { event_select_track_t *est = (event_select_track_t *)e; prop_set_string(mp->mp_prop_subtitle_track_current, est->id); if(r->sub != NULL) subtitles_destroy(r->sub); r->sub = subtitles_load(est->id); } event_release(e); return NULL; }