bool CQTAudioByteStream::start_next_frame (uint8_t **buffer, uint32_t *buflen, frame_timestamp_t *pts, void **ud) { uint64_t ret; if (m_frame_on >= m_frames_max) { #ifdef DEBUG_QTIME_AUDIO_FRAME player_debug_message("Setting EOF from start_next_frame %d %d", m_frame_on, m_frames_max); #endif m_eof = 1; } ret = m_frame_on; ret *= m_samples_per_frame; pts->audio_freq_timestamp = ret; pts->audio_freq = m_frame_rate; ret *= 1000; ret /= m_frame_rate; #ifdef DEBUG_QTIME_AUDIO_FRAME player_debug_message("audio - start frame %d %d", m_frame_on, m_frames_max); #endif #if 0 player_debug_message("audio Start next frame "U64 " offset %u %u", ret, m_byte_on, m_this_frame_size); #endif read_frame(m_frame_on); *buffer = m_buffer; *buflen = m_this_frame_size; m_frame_on++; pts->msec_timestamp = ret; pts->timestamp_is_pts = false; return (true); }
bool CQTVideoByteStream::start_next_frame (uint8_t **buffer, uint32_t *buflen, frame_timestamp_t *ts, void **ud) { uint64_t ret; long start; int duration; #if 0 if (m_frame_on != 0) { player_debug_message("frame %d on %u %d", m_frame_on, m_byte_on, m_this_frame_size); if (m_byte_on != 0 && m_byte_on != m_this_frame_size) { for (uint32_t ix = m_byte_on; ix < m_this_frame_size - 4; ix++) { if ((m_buffer[ix] == 0) && (m_buffer[ix + 1] == 0) && (m_buffer[ix + 2] == 1)) { player_debug_message("correct start code %x", m_buffer[ix + 3]); player_debug_message("offset %d %d %d", m_byte_on, ix, m_this_frame_size); } } } } #endif if (m_frame_on >= m_frames_max) { m_eof = 1; } #ifdef DEBUG_QTIME_VIDEO_FRAME player_debug_message("start_next_frame %d", m_frame_on); #endif if (quicktime_video_frame_time(m_parent->get_file(), m_track, m_frame_on, &start, &duration) != 0) { ret = start; ret *= 1000; ret /= m_time_scale; //player_debug_message("Returning "U64, ret); } else { ret = m_frame_on; ret *= 1000; ret /= m_frame_rate; } read_frame(m_frame_on); *buffer = m_buffer; *buflen = m_this_frame_size; m_frame_on++; ts->msec_timestamp = ret; ts->timestamp_is_pts = false; return (true); }
void CMpeg3VideoByteStream::play (uint64_t start) { player_debug_message("mpeg3 play "U64, start); m_play_start_time = start; set_timebase(start); }
/* * read_frame for video - this will try to read the next frame */ void CQTVideoByteStream::read_frame (uint32_t frame_to_read) { uint32_t next_frame_size; if (m_frame_in_buffer == frame_to_read) { #ifdef DEBUG_QTIME_VIDEO_FRAME player_debug_message("frame in buffer %u %u", m_byte_on, m_this_frame_size); #endif m_byte_on = 0; return; } // Haven't already read the next frame, so - get the size, see if // it fits, then read it into the appropriate buffer m_parent->lock_file_mutex(); next_frame_size = quicktime_frame_size(m_parent->get_file(), frame_to_read, m_track); if (next_frame_size > m_max_frame_size) { m_max_frame_size = next_frame_size + 4; m_buffer = (uint8_t *)realloc(m_buffer, (next_frame_size + 4) * sizeof(char)); } m_this_frame_size = next_frame_size; quicktime_set_video_position(m_parent->get_file(), frame_to_read, m_track); m_frame_in_buffer = frame_to_read; #ifdef DEBUG_QTIME_VIDEO_FRAME player_debug_message("reading into buffer %u", m_this_frame_size); #endif quicktime_read_frame(m_parent->get_file(), (unsigned char *)m_buffer, m_track); #ifdef DEBUG_QTIME_VIDEO_FRAME player_debug_message("Buffer %d %02x %02x %02x %02x", frame_to_read, m_buffer[0], m_buffer[1], m_buffer[2], m_buffer[3]); #endif m_parent->unlock_file_mutex(); m_byte_on = 0; }
void CQTAudioByteStream::read_frame (uint32_t frame_to_read) { #ifdef DEBUG_QTIME_AUDIO_FRAME player_debug_message("audio read_frame %d", frame_to_read); #endif if (m_frame_in_buffer == frame_to_read) { m_byte_on = 0; return; } m_parent->lock_file_mutex(); m_frame_in_buffer = frame_to_read; unsigned char *buff = (unsigned char *)m_buffer; quicktime_set_audio_position(m_parent->get_file(), frame_to_read, m_track); m_this_frame_size = quicktime_read_audio_frame(m_parent->get_file(), buff, m_max_frame_size, m_track); if (m_this_frame_size < 0) { m_max_frame_size = -m_this_frame_size; m_buffer = (uint8_t *)realloc(m_buffer, m_max_frame_size * sizeof(char)); // Okay - I could have used a goto, but it really grates... m_frame_in_buffer = frame_to_read; buff = (unsigned char *)m_buffer; quicktime_set_audio_position(m_parent->get_file(), frame_to_read, m_track); m_this_frame_size = quicktime_read_audio_frame(m_parent->get_file(), buff, m_max_frame_size, m_track); } #if 0 player_debug_message("qta frame size %u", m_this_frame_size); #endif m_parent->unlock_file_mutex(); m_byte_on = 0; }
static inline bool convert_psts (mpeg2t_es_t *es_pid, mpeg2t_frame_t *fptr, uint64_t start_psts) { uint64_t ps_ts; #ifdef DEBUG_MPEG2T_PSTS uint64_t initial; #endif // we want to 0 out the timestamps of the incoming transport // stream so that the on-demand shows the correct timestamps // see if we've set the initial timestamp // here, we want to check for a gross change in the psts if (fptr->have_ps_ts == 0 && fptr->have_dts == 0) return true; if (fptr->have_dts) { ps_ts = fptr->dts; if (ps_ts < start_psts) return false; #ifdef DEBUG_MPEG2T_PSTS initial = fptr->dts; #endif fptr->dts -= start_psts; #ifdef DEBUG_MPEG2T_PSTS player_debug_message(" convert dts "U64" to "U64" "U64, fptr->dts, start_psts, initial); #endif } else { ps_ts = fptr->ps_ts; if (ps_ts < start_psts) return false; #ifdef DEBUG_MPEG2T_PSTS initial = fptr->dts; #endif fptr->ps_ts -= start_psts; #ifdef DEBUG_MPEG2T_PSTS player_debug_message(" convert psts "U64" to "U64" "U64, fptr->ps_ts, start_psts, initial); #endif } return true; }
void CQTVideoByteStream::play (uint64_t start) { m_play_start_time = start; uint32_t ix; long frame_start; int duration; m_parent->lock_file_mutex(); for (ix = 0; ix < m_frames_max; ix++) { if (quicktime_video_frame_time(m_parent->get_file(), m_track, ix, &frame_start, &duration) != 0) { uint64_t cmp; cmp = frame_start + duration; cmp *= 1000; cmp /= m_time_scale; //player_debug_message("frame %d "U64, ix, cmp); if (cmp >= start) { player_debug_message("Searched through - frame %d is "U64, ix, start); break; } } else { m_parent->unlock_file_mutex(); ix = (uint32_t)((start * m_frame_rate) / 1000); video_set_timebase(ix); return; } } #if 0 player_debug_message("qtime video frame " D64 , start); #endif // we've got the position; m_parent->unlock_file_mutex(); video_set_timebase(ix); }
void CAviVideoByteStream::play (uint64_t start) { m_play_start_time = start; double time = UINT64_TO_DOUBLE(start); time *= m_frame_rate; time /= 1000; #if 0 player_debug_message("avi video frame " D64 , start); #endif // we've got the position; video_set_timebase((uint32_t)time); }
void CAviAudioByteStream::play (uint64_t start) { m_play_start_time = start; #if 0 start *= m_frame_rate; start /= 1000 * m_samples_per_frame; player_debug_message("qtime audio frame " D64, start); #endif // we've got the position; audio_set_timebase((uint32_t)start); m_play_start_time = start; }
bool CAviAudioByteStream::start_next_frame (uint8_t **buffer, uint32_t *buflen, frame_timestamp_t *ts, void **ud) { int value; if (m_buffer_on < m_this_frame_size) { value = m_this_frame_size - m_buffer_on; memmove(m_buffer, m_buffer + m_buffer_on, m_this_frame_size - m_buffer_on); m_this_frame_size -= m_buffer_on; } else { value = 0; m_this_frame_size = 0; } m_buffer_on = 0; m_parent->lock_file_mutex(); AVI_set_audio_position(m_parent->get_file(), m_file_pos); int ret; ret = AVI_read_audio(m_parent->get_file(), (char *)m_buffer + value, m_max_frame_size - m_this_frame_size); m_parent->unlock_file_mutex(); //player_debug_message("return from avi read %d", ret); m_this_frame_size += ret; m_file_pos += ret; if (m_file_pos >= AVI_audio_bytes(m_parent->get_file())) { m_eof = 1; } *buffer = m_buffer; *buflen = m_this_frame_size; #if 0 uint64_t ret; ret = m_frame_on; ret *= m_samples_per_frame; ret *= 1000; ret /= m_frame_rate; player_debug_message("Start next frame "U64 " offset %u %u", ret, m_byte_on, m_this_frame_size); return (ret); #endif ts->msec_timestamp = 0; ts->audio_freq_timestamp = 0; ts->audio_freq = AVI_audio_rate(m_parent->get_file()); ts->timestamp_is_pts = false; return true; }
/************************************************************************** * Quicktime Audio stream functions **************************************************************************/ void CQTAudioByteStream::audio_set_timebase (long frame) { #ifdef DEBUG_QTIME_AUDIO_FRAME player_debug_message("Setting qtime audio timebase to frame %ld", frame); #endif m_eof = 0; m_frame_on = frame; m_parent->lock_file_mutex(); quicktime_set_audio_position(m_parent->get_file(), frame, m_track); m_parent->unlock_file_mutex(); read_frame(0); }
bool CMpeg2fByteStream::start_next_frame (uint8_t **buffer, uint32_t *buflen, frame_timestamp_t *ts, void **ud) { if (m_frame) { mpeg2t_free_frame(m_frame); } // see if there is a frame ready for this pid. If not, // request one m_frame = mpeg2t_get_es_list_head(m_es_pid); if (m_frame == NULL) { m_file->get_frame_for_pid(m_es_pid); m_frame = mpeg2t_get_es_list_head(m_es_pid); if (m_frame == NULL) { player_debug_message("%s no frame %d", m_name, m_file->eof()); return false; } } // Convert the psts if (convert_psts(m_es_pid, m_frame, m_file->get_start_psts()) == false) { return false; } // convert the psts into a timestamp if (get_timestamp_for_frame(m_frame, ts) >= 0) { *buffer = m_frame->frame; *buflen = m_frame->frame_len; #ifdef DEBUG_MPEG2T_FRAME player_debug_message("%s - len %d time "U64" ftype %d", m_name, *buflen, ret, m_frame->frame_type); #endif return true; } return false; }
int CMpeg2fAudioByteStream::get_timestamp_for_frame (mpeg2t_frame_t *fptr, frame_timestamp_t *ts) { uint64_t pts_in_msec; // all ts for audio are stored in msec, not in timescale #ifdef DEBUG_MPEG2T_PSTS player_debug_message("audio frame len %d have dts %d ts "U64, fptr->frame_len, fptr->have_dts, fptr->dts); player_debug_message("audio frame len %d have psts %d ts "U64" %d %d", fptr->frame_len, fptr->have_ps_ts, fptr->ps_ts, m_es_pid->sample_per_frame, m_es_pid->sample_freq); #endif if (fptr->have_ps_ts != 0 || fptr->have_dts != 0) { m_timestamp_loaded = 1; pts_in_msec = fptr->have_dts ? fptr->dts : fptr->ps_ts; m_audio_last_freq_timestamp = ((pts_in_msec * m_es_pid->sample_freq) / TO_U64(90000)); ts->audio_freq_timestamp = m_audio_last_freq_timestamp; ts->audio_freq = m_es_pid->sample_freq; pts_in_msec *= TO_U64(1000); pts_in_msec /= TO_U64(90000); m_last_timestamp = pts_in_msec; ts->msec_timestamp = m_last_timestamp; m_frames_since_last_timestamp = 0; return 0; } if (m_timestamp_loaded == 0) return -1; if (m_es_pid->info_loaded == 0) return -1; ts->msec_timestamp = m_last_timestamp; ts->audio_freq_timestamp = m_audio_last_freq_timestamp; ts->audio_freq = m_es_pid->sample_freq; return 0; }
void CQTVideoByteStream::config (long num_frames, float frate, int time_scale) { m_frames_max = num_frames; m_frame_rate = (uint32_t)frate; m_time_scale = time_scale; long start; int duration; // Set up max play time, based on the timing of the last frame. if (quicktime_video_frame_time(m_parent->get_file(), m_track, m_frames_max - 1, &start, &duration) != 0) { player_debug_message("video frame time - %d %ld %d", m_frames_max, start, duration); m_max_time = (start + duration); m_max_time /= m_time_scale; } else { m_max_time = m_frames_max; m_max_time /= m_frame_rate; } player_debug_message("Max time is %g", m_max_time); }
void CQTByteStreamBase::check_for_end_of_frame (void) { if (m_byte_on >= m_this_frame_size) { uint32_t next_frame; next_frame = m_frame_in_buffer + 1; #if 0 player_debug_message("%s - next frame %d", m_name, next_frame); #endif if (next_frame >= m_frames_max) { m_eof = 1; } else { read_frame(next_frame); } } }
/* * pause_all_media - do a spin loop until the sync thread indicates it's * paused. */ int CPlayerSession::pause_all_media (void) { int ret; CPlayerMedia *p; m_session_state = SESSION_PAUSED; if (session_control_is_aggregate()) { rtsp_command_t cmd; rtsp_decode_t *decode; memset(&cmd, 0, sizeof(rtsp_command_t)); if (rtsp_send_aggregate_pause(m_rtsp_client, m_session_control_url, &cmd, &decode) != 0) { player_debug_message("RTSP aggregate pause command failed"); free_decode_response(decode); return (-1); } free_decode_response(decode); } p = m_my_media; while (p != NULL) { ret = p->do_pause(); if (ret != 0) return (ret); p = p->get_next(); } m_sync_pause_done = 0; send_sync_thread_a_message(MSG_PAUSE_SESSION); #ifndef NEED_SDL_VIDEO_IN_MAIN_THREAD do { #endif SDL_Delay(100); #ifndef NEED_SDL_VIDEO_IN_MAIN_THREAD } while (m_sync_pause_done == 0); #endif m_paused = 1; return (0); }
/* * C2ConsecIpPort::C2ConsecIpPort() - get 2 consecutive, even-odd, ip * port numbers */ C2ConsecIpPort::C2ConsecIpPort (CIpPort **global, in_port_t start_port) { CIpPort *newone; m_first = m_second = NULL; in_port_t firstport, maxport; maxport = (in_port_t)~0; if (start_port == 0) { firstport = 1024; if (config.get_config_value(CONFIG_IPPORT_MIN) != UINT32_MAX) { firstport = config.get_config_value(CONFIG_IPPORT_MIN); if (config.get_config_value(CONFIG_IPPORT_MAX) != UINT32_MAX) { maxport = config.get_config_value(CONFIG_IPPORT_MAX); if (maxport <= firstport) { player_error_message("IP port configuration error - %u %u - using 65535 as max port value", firstport, maxport); maxport = (in_port_t)~0; } } } } else { firstport = start_port; } while (1) { // first, get an even port number. If not even, save it in the // global queue. do { newone = new CIpPort(firstport, maxport); if (newone->valid() == 0) return; if ((newone->get_port_num() & 0x1) == 0x1) { newone->set_next(*global); *global = newone; firstport++; } } while ((newone->get_port_num() & 0x1) == 0x1); player_debug_message("First port is %d", newone->get_port_num()); // Okay, save the first, get the 2nd. If okay, just return m_first = newone; in_port_t next; next = m_first->get_port_num() + 1; m_second = new CIpPort(next, next); if ((m_second->valid() == 1) && (m_second->get_port_num() == next)) { player_debug_message("Ip ports are %u %u", next - 1, next); return; } else { player_debug_message("Got port %d invalid %d", m_second->get_port_num(), m_second->valid()); } // Not okay - save both off in the global queue, and try again... m_first->set_next(*global); *global = m_first; m_first = NULL; firstport = m_second->get_port_num() + 1; m_second->set_next(*global); *global = m_second; m_second = NULL; } }
/* * play_all_media - get all media to play */ int CPlayerSession::play_all_media (int start_from_begin, double start_time, char *errmsg, uint32_t errlen) { int ret; CPlayerMedia *p; if (m_set_end_time == 0) { range_desc_t *range; if (m_sdp_info && m_sdp_info->session_range.have_range != FALSE) { range = &m_sdp_info->session_range; } else { range = NULL; p = m_my_media; while (range == NULL && p != NULL) { media_desc_t *media; media = p->get_sdp_media_desc(); if (media && media->media_range.have_range) { range = &media->media_range; } p = p->get_next(); } } if (range != NULL) { m_end_time = (uint64_t)(range->range_end * 1000.0); m_set_end_time = 1; } } p = m_my_media; m_session_state = SESSION_BUFFERING; if (m_paused == 1 && start_time == 0.0 && start_from_begin == FALSE) { /* * we were paused. Continue. */ m_play_start_time = m_current_time; start_time = UINT64_TO_DOUBLE(m_current_time); start_time /= 1000.0; player_debug_message("Restarting at " U64 ", %g", m_current_time, start_time); } else { /* * We might have been paused, but we're told to seek */ // Indicate what time we're starting at for sync task. m_play_start_time = (uint64_t)(start_time * 1000.0); } m_paused = 0; send_sync_thread_a_message(MSG_START_SESSION); // If we're doing aggregate rtsp, send the play command... if (session_control_is_aggregate() && m_dont_send_first_rtsp_play == 0) { char buffer[80]; rtsp_command_t cmd; rtsp_decode_t *decode; memset(&cmd, 0, sizeof(rtsp_command_t)); if (m_set_end_time != 0) { uint64_t stime = (uint64_t)(start_time * 1000.0); sprintf(buffer, "npt="U64"."U64"-"U64"."U64, stime / 1000, stime % 1000, m_end_time / 1000, m_end_time % 1000); cmd.range = buffer; } if (rtsp_send_aggregate_play(m_rtsp_client, m_session_control_url, &cmd, &decode) != 0) { if (errmsg != NULL) { snprintf(errmsg, errlen, "RTSP Aggregate Play Error %s-%s", decode->retcode, decode->retresp != NULL ? decode->retresp : ""); } player_debug_message("RTSP aggregate play command failed"); free_decode_response(decode); return (-1); } if (decode->rtp_info == NULL) { player_error_message("No rtp info field"); } else { player_debug_message("rtp info is \'%s\'", decode->rtp_info); } int ret = process_rtsp_rtpinfo(decode->rtp_info, this, NULL); free_decode_response(decode); if (ret < 0) { if (errmsg != NULL) { snprintf(errmsg, errlen, "RTSP aggregate RtpInfo response failure"); } player_debug_message("rtsp aggregate rtpinfo failed"); return (-1); } } m_dont_send_first_rtsp_play = 0; while (p != NULL) { ret = p->do_play(start_time, errmsg, errlen); if (ret != 0) return (ret); p = p->get_next(); } return (0); }
int CMpeg2fVideoByteStream::get_timestamp_for_frame (mpeg2t_frame_t *fptr, frame_timestamp_t *ts) { #ifdef DEBUG_MPEG2T_PSTS if (fptr->have_dts) { player_debug_message("video frame len %d have dts %d ts "U64, fptr->frame_len, fptr->have_dts, fptr->dts); } if (fptr->have_ps_ts) { player_debug_message("video frame len %d have psts %d ts "U64, fptr->frame_len, fptr->have_ps_ts, fptr->ps_ts); } #endif #if 0 if (m_es_pid->stream_type == MPEG2T_STREAM_H264) { if (fptr->have_dts || fptr->have_ps_ts) { if (fptr->have_dts) outts = fptr->dts; else outts = fptr->ps_ts; outts *= TO_U64(1000); outts /= TO_U64(90000); // get msec from 90000 timescale return 0; } return -1; } uint64_t ts; // m_es_pid->frame_rate = 24; double value = 90000.0 / m_es_pid->frame_rate; uint64_t frame_time = (uint64_t)value; if (fptr->have_ps_ts == 0 && fptr->have_dts == 0) { // We don't have a timestamp on this - just increment from // the previous timestamp. if (m_timestamp_loaded == 0) return -1; if (m_es_pid->info_loaded == 0) return -1; outts = m_prev_ts + frame_time; m_have_prev_frame_type = 1; m_prev_frame_type = fptr->frame_type; m_prev_ts = outts; outts *= TO_U64(1000); outts /= TO_U64(90000); // get msec from 90000 timescale return 0; } m_timestamp_loaded = 1; if (fptr->have_dts != 0) { outts = fptr->dts; } else { ts = fptr->ps_ts; if (m_have_prev_frame_type) { if (fptr->frame_type == 3) { // B frame outts = ts; } else { outts = m_prev_ts + frame_time; } } else { if (fptr->frame_type == 1) { uint16_t temp_ref = MP4AV_Mpeg3PictHdrTempRef(fptr->frame + fptr->pict_header_offset); ts -= ((temp_ref + 1) * m_es_pid->tick_per_frame); outts = ts; } else { player_error_message( "no psts and no prev frame"); outts = ts; } } } m_have_prev_frame_type = 1; m_prev_frame_type = fptr->frame_type; m_prev_ts = outts; outts *= TO_U64(1000); outts /= TO_U64(90000); // get msec from 90000 timescale return 0; #endif ts->timestamp_is_pts = fptr->have_dts == false; uint64_t outts; if (fptr->have_dts) outts = fptr->dts; else outts = fptr->ps_ts; outts *= TO_U64(1000); outts /= TO_U64(90000); // get msec from 90000 timescale ts->msec_timestamp = outts; return 0; }
/* * Create the media for the quicktime file, and set up some session stuff. */ int create_media_for_avi_file (CPlayerSession *psptr, const char *name, char *errmsg, uint32_t errlen, int have_audio_driver, control_callback_vft_t *cc_vft) { CAviFile *Avifile1 = NULL; avi_t *avi; CPlayerMedia *mptr; avi = AVI_open_input_file(name, 1); if (avi == NULL) { snprintf(errmsg, errlen, "%s", AVI_strerror()); player_error_message("%s", AVI_strerror()); return (-1); } int video_count = 1; codec_plugin_t *plugin; video_query_t vq; const char *codec_name = AVI_video_compressor(avi); player_debug_message("Trying avi video codec %s", codec_name); plugin = check_for_video_codec(STREAM_TYPE_AVI_FILE, codec_name, NULL, -1, -1, NULL, 0, &config); if (plugin == NULL) { video_count = 0; } else { vq.track_id = 1; vq.stream_type = STREAM_TYPE_AVI_FILE; vq.compressor = codec_name; vq.type = -1; vq.profile = -1; vq.fptr = NULL; vq.h = AVI_video_height(avi); vq.w = AVI_video_width(avi); vq.frame_rate = AVI_video_frame_rate(avi); vq.config = NULL; vq.config_len = 0; vq.enabled = 0; vq.reference = NULL; } int have_audio = 0; int audio_count = 0; audio_query_t aq; if (AVI_audio_bytes(avi) != 0) { have_audio = 1; plugin = check_for_audio_codec(STREAM_TYPE_AVI_FILE, NULL, NULL, AVI_audio_format(avi), -1, NULL, 0, &config); if (plugin != NULL) { audio_count = 1; aq.track_id = 1; aq.stream_type = STREAM_TYPE_AVI_FILE; aq.compressor = NULL; aq.type = AVI_audio_format(avi); aq.profile = -1; aq.fptr = NULL; aq.sampling_freq = AVI_audio_rate(avi); aq.chans = AVI_audio_channels(avi); aq.config = NULL; aq.config_len = 0; aq.enabled = 0; aq.reference = NULL; } } if (cc_vft != NULL && cc_vft->media_list_query != NULL) { (cc_vft->media_list_query)(psptr, video_count, &vq, audio_count, &aq); } else { if (video_count != 0) vq.enabled = 1; if (audio_count != 0) aq.enabled = 1; } if ((video_count == 0 || vq.enabled == 0) && (audio_count == 0 || aq.enabled == 0)) { snprintf(errmsg, errlen, "No audio or video tracks enabled or playable"); AVI_close(avi); return -1; } Avifile1 = new CAviFile(name, avi, vq.enabled, audio_count); psptr->set_media_close_callback(close_avi_file, Avifile1); if (video_count != 0 && vq.enabled) { mptr = new CPlayerMedia(psptr); if (mptr == NULL) { return (-1); } video_info_t *vinfo = MALLOC_STRUCTURE(video_info_t); if (vinfo == NULL) return (-1); vinfo->height = vq.h; vinfo->width = vq.w; player_debug_message("avi file h %d w %d frame rate %g", vinfo->height, vinfo->width, vq.frame_rate); plugin = check_for_video_codec(STREAM_TYPE_AVI_FILE, codec_name, NULL, -1, -1, NULL, 0, &config); int ret; ret = mptr->create_video_plugin(plugin, STREAM_TYPE_AVI_FILE, codec_name, -1, -1, NULL, vinfo, NULL, 0); if (ret < 0) { snprintf(errmsg, errlen, "Failed to create video plugin %s", codec_name); player_error_message("Failed to create plugin data"); delete mptr; return -1; } CAviVideoByteStream *vbyte = new CAviVideoByteStream(Avifile1); if (vbyte == NULL) { delete mptr; return (-1); } vbyte->config(AVI_video_frames(avi), vq.frame_rate); ret = mptr->create(vbyte, TRUE, errmsg, errlen); if (ret != 0) { return (-1); } } int seekable = 1; if (have_audio_driver > 0 && audio_count > 0 && aq.enabled != 0) { plugin = check_for_audio_codec(STREAM_TYPE_AVI_FILE, NULL, NULL, aq.type, -1, NULL, 0, &config); CAviAudioByteStream *abyte; mptr = new CPlayerMedia(psptr); if (mptr == NULL) { return (-1); } audio_info_t *ainfo; ainfo = MALLOC_STRUCTURE(audio_info_t); ainfo->freq = aq.sampling_freq; ainfo->chans = aq.chans; ainfo->bitspersample = AVI_audio_bits(avi); int ret; ret = mptr->create_audio_plugin(plugin, aq.stream_type, aq.compressor, aq.type, aq.profile, NULL, ainfo, NULL, 0); if (ret < 0) { delete mptr; player_error_message("Couldn't create audio from plugin %s", plugin->c_name); return -1; } abyte = new CAviAudioByteStream(Avifile1); ret = mptr->create(abyte, FALSE, errmsg, errlen); if (ret != 0) { return (-1); } seekable = 0; } psptr->session_set_seekable(seekable); if (audio_count == 0 && have_audio != 0) { snprintf(errmsg, errlen, "Unknown Audio Codec in avi file "); return (1); } if (video_count != 1) { snprintf(errmsg, errlen, "Unknown Video Codec %s in avi file", codec_name); return (1); } return (0); }
/* * Create - will determine pids and psts ranges in file. Will also * loop through the file and determine CFilePosRec points at percentages */ int CMpeg2tFile::create (CPlayerSession *psptr) { m_mpeg2t = create_mpeg2_transport(); if (m_mpeg2t == NULL) { psptr->set_message("Couldn't create mpeg2 transport"); fclose(m_ifile); return -1; } // nice, large buffers to process m_buffer_size_max = 188 * 2000; m_buffer = (uint8_t *)malloc(m_buffer_size_max); if (m_buffer == NULL) { psptr->set_message("Malloc error"); return -1; } m_buffer[0] = MPEG2T_SYNC_BYTE; m_buffer_size = fread(&m_buffer[1], 1, m_buffer_size_max - 1, m_ifile) + 1; bool done = false; mpeg2t_pid_t *pidptr; uint32_t buflen_used; bool have_psts = false; uint64_t earliest_psts = 0; mpeg2t_es_t *es_pid; int olddebuglevel; olddebuglevel = config.get_config_value(CONFIG_MPEG2T_DEBUG); if (olddebuglevel != LOG_DEBUG) mpeg2t_set_loglevel(LOG_CRIT); m_mpeg2t->save_frames_at_start = 1; /* * We need to determine which PIDs are present, and try to establish * a starting psts. We also want to establish what type of video and * audio are in the mix. Note: if we try to run this on a file that * we don't understand the video, this could take a while, because the * info never gets loaded. */ do { m_buffer_on = 0; while (m_buffer_on + 188 < m_buffer_size && done == false) { pidptr = mpeg2t_process_buffer(m_mpeg2t, &m_buffer[m_buffer_on], m_buffer_size - m_buffer_on, &buflen_used); m_buffer_on += buflen_used; if (pidptr != NULL && pidptr->pak_type == MPEG2T_ES_PAK) { es_pid = (mpeg2t_es_t *)pidptr; mpeg2t_frame_t *fptr; // determine earliest PS_TS while ((fptr = mpeg2t_get_es_list_head(es_pid)) != NULL) { if (fptr->have_ps_ts != 0 || fptr->have_dts != 0) { uint64_t ps_ts = 0; bool store_psts = true; if (fptr->have_dts != 0) { ps_ts = fptr->dts; } else { if (es_pid->is_video == 1) { // mpeg2 // video - make sure we get the first I frame, then we can // get the real timestamp if (fptr->frame_type != 1) { store_psts = false; } else { ps_ts = fptr->ps_ts; uint16_t temp_ref = MP4AV_Mpeg3PictHdrTempRef(fptr->frame + fptr->pict_header_offset); ps_ts -= ((temp_ref + 1) * es_pid->tick_per_frame); } } else { ps_ts = fptr->ps_ts; } } if (store_psts) { // when we have the first psts for a ES_PID, turn off // parsing frames for that PID. mpeg2t_set_frame_status(es_pid, MPEG2T_PID_NOTHING); if (have_psts) { earliest_psts = MIN(earliest_psts, ps_ts); } else { earliest_psts = ps_ts; have_psts = true; } } } mpeg2t_free_frame(fptr); } // Each time, search through and see if there are any ES_PIDs // that have not returned a psts. We're done when the info is // loaded for all the es pids. pidptr = m_mpeg2t->pas.pid.next_pid; bool finished = true; while (pidptr != NULL && finished) { if (pidptr->pak_type == MPEG2T_ES_PAK) { es_pid = (mpeg2t_es_t *)pidptr; if (es_pid->info_loaded == 0) { finished = false; } } pidptr = pidptr->next_pid; } done = finished || have_psts; } } if (done == false) { m_buffer_size = fread(m_buffer, 1, m_buffer_size_max, m_ifile); } } while (m_buffer_size >=188 && done == false); if (done == false) { psptr->set_message("Could not find information in TS"); mpeg2t_set_loglevel(olddebuglevel); return -1; } #ifdef DEBUG_MPEG2F_SEARCH mpeg2f_message(LOG_DEBUG, "initial psts is "U64, earliest_psts); #endif m_start_psts = earliest_psts; // Now, we'll try to build a rough index for the file // enable psts reading for the pid for (pidptr = m_mpeg2t->pas.pid.next_pid; pidptr != NULL; pidptr = pidptr->next_pid) { if (pidptr->pak_type == MPEG2T_ES_PAK) { es_pid = (mpeg2t_es_t *)pidptr; mpeg2t_set_frame_status(es_pid, MPEG2T_PID_REPORT_PSTS); } } m_file_record.record_point(0, earliest_psts, 0); fpos_t fpos; uint64_t end; uint64_t perc, cur; // find out the length of the file. struct stat filestat; if (fstat(fileno(m_ifile), &filestat) != 0) { return -1; } end = filestat.st_size; perc = end; // perc is what size of the file to skip through to get a rough // timetable. We want to do 10% chunks, or 100Mb chunks, whichever is // less. while (perc > TO_U64(100000000)) { perc /= 2; } if (perc > (end / TO_U64(10))) { perc = end / TO_U64(10); } if (perc < (end / TO_U64(50))) { perc = end / TO_U64(50); } #ifdef DEBUG_MPEG2F_SEARCH mpeg2f_message(LOG_DEBUG, "perc is "U64" "U64, perc, (perc * TO_U64(100)) / end ); #endif cur = perc; bool is_seekable = true; uint64_t last_psts, ts; last_psts = earliest_psts; // Now - skip to the next perc chunk, and try to find the next psts // we'll record this info. do { #ifdef DEBUG_MPEG2F_SEARCH mpeg2f_message(LOG_DEBUG, "current "U64" end "U64, cur, end); #endif VAR_TO_FPOS(fpos, cur); fsetpos(m_ifile, &fpos); done = false; uint64_t count = 0; m_buffer_on = 0; m_buffer_size = 0; do { if (m_buffer_on + 188 > m_buffer_size) { if (m_buffer_on < m_buffer_size) { memmove(m_buffer, m_buffer + m_buffer_on, m_buffer_size - m_buffer_on); m_buffer_on = m_buffer_size - m_buffer_on; } else { m_buffer_on = 0; } m_buffer_size = fread(m_buffer + m_buffer_on, 1, (188 * 10) - m_buffer_on, m_ifile); count += m_buffer_size - m_buffer_on; m_buffer_size += m_buffer_on; m_buffer_on = 0; if (m_buffer_size < 188) { m_buffer_size = 0; done = true; } } pidptr = mpeg2t_process_buffer(m_mpeg2t, m_buffer + m_buffer_on, m_buffer_size - m_buffer_on, &buflen_used); m_buffer_on += buflen_used; if (pidptr != NULL && pidptr->pak_type == MPEG2T_ES_PAK) { es_pid = (mpeg2t_es_t *)pidptr; // If we have a psts, record it. // If it is less than the previous one, we've got a discontinuity, so // we can't seek. if (es_pid->have_ps_ts || es_pid->have_dts) { ts = es_pid->have_ps_ts ? es_pid->ps_ts : es_pid->dts; if (ts < last_psts) { player_error_message("pid %x psts "U64" is less than prev record point "U64, es_pid->pid.pid, ts, last_psts); cur = end; is_seekable = false; } else { #ifdef DEBUG_MPEG2F_SEARCH mpeg2f_message(LOG_DEBUG, "pid %x psts "U64" %d", pidptr->pid, ts, es_pid->is_video); #endif m_file_record.record_point(cur, ts, 0); } done = true; } } } while (done == false && count < perc / 2); cur += perc; } while (cur < end - (m_buffer_size_max * 2)); //mpeg2f_message(LOG_DEBUG, "starting end search"); // Now, we'll go to close to the end of the file, and look for a // final PSTS. This gives us a rough estimate of the elapsed time long seek_offset; seek_offset = 0; seek_offset -= (m_buffer_size_max) * 2; fseek(m_ifile, seek_offset, SEEK_END); m_buffer_on = m_buffer_size = 0; uint64_t max_psts; max_psts = m_start_psts; do { while (m_buffer_on + 188 <= m_buffer_size) { pidptr = mpeg2t_process_buffer(m_mpeg2t, &m_buffer[m_buffer_on], m_buffer_size - m_buffer_on, &buflen_used); m_buffer_on += buflen_used; if (pidptr != NULL && pidptr->pak_type == MPEG2T_ES_PAK) { es_pid = (mpeg2t_es_t *)pidptr; if (es_pid->have_ps_ts) { es_pid->have_ps_ts = 0; max_psts = MAX(es_pid->ps_ts, max_psts); } else if (es_pid->have_dts) { es_pid->have_dts = 0; max_psts = MAX(es_pid->dts, max_psts); } } } if (m_buffer_size > m_buffer_on) { memmove(m_buffer, m_buffer + m_buffer_on, m_buffer_size - m_buffer_on); } m_buffer_on = m_buffer_size - m_buffer_on; m_buffer_size = fread(m_buffer + m_buffer_on, 1, m_buffer_size_max - m_buffer_on, m_ifile); m_buffer_size += m_buffer_on; m_buffer_on = 0; if (m_buffer_size < 188) m_buffer_size = 0; } while (m_buffer_size > 188) ; m_last_psts = max_psts; // Calculate the rough max time; hopefully it will be greater than the // initial... m_max_time = max_psts; m_max_time -= m_start_psts; m_max_time /= 90000.0; #ifdef DEBUG_MPEG2F_SEARCH player_debug_message("last psts is "U64" "U64" %g", max_psts, (max_psts - m_start_psts) / TO_U64(90000), m_max_time); #endif mpeg2t_set_loglevel(olddebuglevel); if (is_seekable) { psptr->session_set_seekable(1); } m_ts_seeked_in_msec = UINT64_MAX; rewind(m_ifile); return 0; }
static int iso_decode (codec_data_t *ptr, frame_timestamp_t *ts, int from_rtp, int *sync_frame, uint8_t *buffer, uint32_t buflen, void *userdata) { Int iEof = 1; iso_decode_t *iso = (iso_decode_t *)ptr; uint32_t used = 0; if (buflen <= 4) return -1; // iso_message(LOG_DEBUG, "iso", "frame %d", iso->m_total_frames); iso->m_total_frames++; buffer[buflen] = 0; buffer[buflen + 1] = 0; buffer[buflen + 2] = 1; switch (iso->m_decodeState) { case DECODE_STATE_VOL_SEARCH: { if (buffer[0] == 0 && buffer[1] == 0 && (buffer[2] & 0xfc) == 0x80 && (buffer[3] & 0x03) == 0x02) { // we have the short header iso->m_short_header = 1; iso->m_pvodec->SetUpBitstreamBuffer((unsigned char *)buffer, buflen); iso->m_pvodec->video_plane_with_short_header(); iso->m_pvodec->postVO_VOLHeadInit(iso->m_pvodec->getWidth(), iso->m_pvodec->getHeight(), &iso->m_bSpatialScalability); iso_message(LOG_INFO, mp4iso, "Decoding using short headers"); iso->m_vft->video_configure(iso->m_ifptr, iso->m_pvodec->getWidth(), iso->m_pvodec->getHeight(), VIDEO_FORMAT_YUV, calculate_aspect_ratio(iso)); iso->m_decodeState = DECODE_STATE_NORMAL; try { iEof = iso->m_pvodec->h263_decode(FALSE); } catch (...) { iso_message(LOG_ERR, mp4iso, "Couldn't decode h263 in vol search"); } break; } else { uint8_t *volhdr = MP4AV_Mpeg4FindVol(buffer, buflen); if (volhdr != NULL) { used = volhdr - buffer; try { iso->m_pvodec->SetUpBitstreamBuffer((unsigned char *)volhdr, buflen - used); iso->m_pvodec->decodeVOLHead(); iso->m_pvodec->postVO_VOLHeadInit(iso->m_pvodec->getWidth(), iso->m_pvodec->getHeight(), &iso->m_bSpatialScalability); iso_message(LOG_INFO, mp4iso, "Found VOL"); iso->m_vft->video_configure(iso->m_ifptr, iso->m_pvodec->getWidth(), iso->m_pvodec->getHeight(), VIDEO_FORMAT_YUV, calculate_aspect_ratio(iso)); iso->m_decodeState = DECODE_STATE_WAIT_I; used += iso->m_pvodec->get_used_bytes(); } catch (int err) { iso_message(LOG_DEBUG, mp4iso, "Caught exception in VOL search %d", err); if (err == 1) used = buflen; else used += iso->m_pvodec->get_used_bytes(); } } } if (iso->m_decodeState != DECODE_STATE_WAIT_I) { if (iso->m_vinfo != NULL) { iso->m_pvodec->FakeOutVOVOLHead(iso->m_vinfo->height, iso->m_vinfo->width, 30, &iso->m_bSpatialScalability); iso->m_vft->video_configure(iso->m_ifptr, iso->m_vinfo->width, iso->m_vinfo->height, VIDEO_FORMAT_YUV, calculate_aspect_ratio(iso)); iso->m_decodeState = DECODE_STATE_NORMAL; } return used; } // else fall through } case DECODE_STATE_WAIT_I: { uint8_t *vophdr = MP4AV_Mpeg4FindVop(buffer, buflen); if (vophdr != NULL) { used = vophdr - buffer; } iso->m_pvodec->SetUpBitstreamBuffer((unsigned char *)buffer + used, buflen + 3 - used); try { iEof = iso->m_pvodec->decode(NULL, TRUE); if (iEof == -1) { iso->m_num_wait_i_frames++; return(iso->m_pvodec->get_used_bytes()); } iso_message(LOG_DEBUG, mp4iso, "Back to normal decode"); iso->m_decodeState = DECODE_STATE_NORMAL; iso->m_bCachedRefFrame = FALSE; iso->m_bCachedRefFrameCoded = FALSE; iso->m_cached_valid = FALSE; iso->m_cached_time = 0; } catch (int err) { if (err != 1) iso_message(LOG_DEBUG, mp4iso, "ts "U64",Caught exception in wait_i %d", ts->msec_timestamp, err); return (iso->m_pvodec->get_used_bytes()); //return (-1); } break; } case DECODE_STATE_NORMAL: try { if (iso->m_short_header != 0) { iso->m_pvodec->SetUpBitstreamBuffer((unsigned char *)buffer, buflen + 3); iEof = iso->m_pvodec->h263_decode(TRUE); } else { uint8_t *vophdr = MP4AV_Mpeg4FindVop(buffer, buflen); if (vophdr != NULL && vophdr != buffer) { iso_message(LOG_DEBUG, mp4iso, "Illegal code before VOP header"); used = vophdr - buffer; buflen -= used; buffer = vophdr; } iso->m_pvodec->SetUpBitstreamBuffer((unsigned char *)buffer, buflen + 3); iEof = iso->m_pvodec->decode(NULL, FALSE, FALSE); } } catch (int err) { // This is because sometimes, the encoder doesn't read all the bytes // it should out of the rtp packet. The rtp bytestream does a read // and determines that we're trying to read across bytestreams. // If we get this, we don't want to change anything - just fall up // to the decoder thread so it gives us a new timestamp. if (err == 1) { // throw from running past end of frame return -1; } iso_message(LOG_DEBUG, mp4iso, "Mpeg4 ncaught %d -> waiting for I", err); iso->m_decodeState = DECODE_STATE_WAIT_I; return (iso->m_pvodec->get_used_bytes()); } catch (...) { iso_message(LOG_DEBUG, mp4iso, "Mpeg4 ncaught -> waiting for I"); iso->m_decodeState = DECODE_STATE_WAIT_I; //return (-1); return (iso->m_pvodec->get_used_bytes()); } break; } /* * We've got a good frame. See if we need to display it */ const CVOPU8YUVBA *pvopcQuant = NULL; if (iso->m_pvodec->fSptUsage() == 1) { //player_debug_message("Sprite"); } uint64_t displaytime = 0; int cached_ts = 0; if (iEof == EOF) { if (iso->m_bCachedRefFrame) { iso->m_bCachedRefFrame = FALSE; if (iso->m_bCachedRefFrameCoded) { pvopcQuant = iso->m_pvodec->pvopcRefQLater(); displaytime = ts->msec_timestamp; } } } else { #if 0 iso_message(LOG_DEBUG, mp4iso, "frame "U64" type %d", ts->msec_timestamp, iso->m_pvodec->vopmd().vopPredType); #endif if (iso->m_pvodec->vopmd().vopPredType == BVOP) { if (iEof != FALSE) { pvopcQuant = iso->m_pvodec->pvopcReconCurr(); displaytime = ts->msec_timestamp; } } else { if (iso->m_bCachedRefFrame) { iso->m_bCachedRefFrame = FALSE; if (iso->m_bCachedRefFrameCoded) { pvopcQuant = iso->m_pvodec->pvopcRefQPrev(); if (ts->timestamp_is_pts) { int old_was_valid = iso->m_cached_valid; displaytime = iso->m_cached_time; cached_ts = 1; // old time stamp wasn't valid - instead of calculating it // ourselves, just punt on it. if (old_was_valid == 0) { return (iEof == EOF ? -1 : 0); } } else { displaytime = ts->msec_timestamp; } } } iso->m_cached_time = ts->msec_timestamp; iso->m_cached_valid = TRUE; iso->m_bCachedRefFrame = TRUE; iso->m_bCachedRefFrameCoded = (iEof != FALSE); } } if (pvopcQuant != NULL) { #if 0 player_debug_message("frame rtp_ts "U64" disp "U64" cached %d", ts->msec_timestamp, displaytime, cached_ts); #endif /* * Get the information to the video sync structure */ const uint8_t *y, *u, *v; int pixelw_y, pixelw_uv; pixelw_y = pvopcQuant->getPlane(Y_PLANE)->where().width; pixelw_uv = pvopcQuant->getPlane(U_PLANE)->where().width; y = (const uint8_t *)pvopcQuant->getPlane(Y_PLANE)->pixels(0,0); u = (const uint8_t *)pvopcQuant->getPlane(U_PLANE)->pixels(0,0); v = (const uint8_t *)pvopcQuant->getPlane(V_PLANE)->pixels(0,0); iso->m_last_time = displaytime; #if 0 player_debug_message("Adding video at "U64" %d", displaytime, iso->m_pvodec->vopmd().vopPredType); #endif iso->m_vft->video_have_frame(iso->m_ifptr, y, u, v, pixelw_y, pixelw_uv, displaytime); } else { iso_message(LOG_DEBUG, mp4iso, "decode but no frame "U64, ts->msec_timestamp); } return (iso->m_pvodec->get_used_bytes() + used); }
/* * create_streaming - create a session for streaming. Create an * RTSP session with the server, get the SDP information from it. */ int CPlayerSession::create_streaming_ondemand (const char *url, char *errmsg, uint32_t errlen, int use_tcp) { rtsp_command_t cmd; rtsp_decode_t *decode; sdp_decode_info_t *sdpdecode; int dummy; int err; // streaming has seek capability (at least on demand) session_set_seekable(1); player_debug_message("Creating streaming %s", url); memset(&cmd, 0, sizeof(rtsp_command_t)); /* * create RTSP session */ if (use_tcp != 0) { m_rtsp_client = rtsp_create_client_for_rtp_tcp(url, &err); } else { m_rtsp_client = rtsp_create_client(url, &err); } if (m_rtsp_client == NULL) { snprintf(errmsg, errlen, "Failed to create RTSP client"); player_error_message("Failed to create rtsp client - error %d", err); return (err); } m_rtp_over_rtsp = use_tcp; cmd.accept = "application/sdp"; /* * Send the RTSP describe. This should return SDP information about * the session. */ int rtsp_resp; rtsp_resp = rtsp_send_describe(m_rtsp_client, &cmd, &decode); if (rtsp_resp != RTSP_RESPONSE_GOOD) { int retval; if (decode != NULL) { retval = (((decode->retcode[0] - '0') * 100) + ((decode->retcode[1] - '0') * 10) + (decode->retcode[2] - '0')); snprintf(errmsg, errlen, "RTSP describe error %d %s", retval, decode->retresp != NULL ? decode->retresp : ""); free_decode_response(decode); } else { retval = -1; snprintf(errmsg, errlen, "RTSP return invalid %d", rtsp_resp); } player_error_message("Describe response not good\n"); return (retval); } sdpdecode = set_sdp_decode_from_memory(decode->body); if (sdpdecode == NULL) { snprintf(errmsg, errlen, "Memory failure"); player_error_message("Couldn't get sdp decode\n"); free_decode_response(decode); return (-1); } /* * Decode the SDP information into structures we can use. */ err = sdp_decode(sdpdecode, &m_sdp_info, &dummy); free(sdpdecode); if (err != 0) { snprintf(errmsg, errlen, "Couldn't decode session description %s", decode->body); player_error_message("Couldn't decode sdp %s", decode->body); free_decode_response(decode); return (-1); } if (dummy != 1) { snprintf(errmsg, errlen, "Incorrect number of sessions in sdp decode %d", dummy); player_error_message("%s", errmsg); free_decode_response(decode); return (-1); } /* * Make sure we can use the urls in the sdp info */ if (decode->content_location != NULL) { // Note - we may have problems if the content location is not absolute. m_content_base = strdup(decode->content_location); } else if (decode->content_base != NULL) { m_content_base = strdup(decode->content_base); } else { int urllen = strlen(url); if (url[urllen] != '/') { char *temp; temp = (char *)malloc(urllen + 2); strcpy(temp, url); strcat(temp, "/"); m_content_base = temp; } else { m_content_base = strdup(url); } } convert_relative_urls_to_absolute(m_sdp_info, m_content_base); if (m_sdp_info->control_string != NULL) { player_debug_message("setting control url to %s", m_sdp_info->control_string); set_session_control_url(m_sdp_info->control_string); } free_decode_response(decode); m_streaming = 1; m_streaming_ondemand = (get_range_from_sdp(m_sdp_info) != NULL); return (0); }
void CPlayerMedia::create_rtp_byte_stream (uint8_t rtp_pt, uint64_t tps, format_list_t *fmt) { int codec; rtp_check_return_t plugin_ret; rtp_plugin_t *rtp_plugin; int stream_ondemand; rtp_plugin = NULL; plugin_ret = check_for_rtp_plugins(fmt, rtp_pt, &rtp_plugin, &config); stream_ondemand = 0; if (m_stream_ondemand == 1 && get_range_from_media(m_media_info) != NULL) { // m_stream_ondemand == 1 means we're using RTSP, and having a range // in the SDP means that we have an ondemand presentation; otherwise, we // want to treat it like a broadcast session, and use the RTCP. stream_ondemand = 1; } if (plugin_ret != RTP_PLUGIN_NO_MATCH) { switch (plugin_ret) { case RTP_PLUGIN_MATCH: player_debug_message("Starting rtp bytestream %s from plugin", rtp_plugin->name); m_rtp_byte_stream = new CPluginRtpByteStream(rtp_plugin, fmt, rtp_pt, stream_ondemand, tps, &m_head, &m_tail, m_rtsp_base_seq_received, m_rtp_base_seq, m_rtsp_base_ts_received, m_rtp_base_ts, m_rtcp_received, m_rtcp_ntp_frac, m_rtcp_ntp_sec, m_rtcp_rtp_ts); return; case RTP_PLUGIN_MATCH_USE_VIDEO_DEFAULT: // just fall through... break; case RTP_PLUGIN_MATCH_USE_AUDIO_DEFAULT: m_rtp_byte_stream = new CAudioRtpByteStream(rtp_pt, fmt, stream_ondemand, tps, &m_head, &m_tail, m_rtsp_base_seq_received, m_rtp_base_seq, m_rtsp_base_ts_received, m_rtp_base_ts, m_rtcp_received, m_rtcp_ntp_frac, m_rtcp_ntp_sec, m_rtcp_rtp_ts); if (m_rtp_byte_stream != NULL) { player_debug_message("Starting generic audio byte stream"); return; } case RTP_PLUGIN_NO_MATCH: default: break; } } else { if (is_audio() == false && (rtp_pt == 32)) { codec = VIDEO_MPEG12; m_rtp_byte_stream = new CMpeg3RtpByteStream(rtp_pt, fmt, stream_ondemand, tps, &m_head, &m_tail, m_rtsp_base_seq_received, m_rtp_base_seq, m_rtsp_base_ts_received, m_rtp_base_ts, m_rtcp_received, m_rtcp_ntp_frac, m_rtcp_ntp_sec, m_rtcp_rtp_ts); if (m_rtp_byte_stream != NULL) { return; } } else { if (rtp_pt == 14) { codec = MPEG4IP_AUDIO_MP3; } else if (rtp_pt <= 23) { codec = MPEG4IP_AUDIO_GENERIC; } else { if (fmt->rtpmap_name == NULL) return; codec = lookup_audio_codec_by_name(fmt->rtpmap_name); if (codec < 0) { codec = MPEG4IP_AUDIO_NONE; // fall through everything to generic } } switch (codec) { case MPEG4IP_AUDIO_MP3: { m_rtp_byte_stream = new CAudioRtpByteStream(rtp_pt, fmt, stream_ondemand, tps, &m_head, &m_tail, m_rtsp_base_seq_received, m_rtp_base_seq, m_rtsp_base_ts_received, m_rtp_base_ts, m_rtcp_received, m_rtcp_ntp_frac, m_rtcp_ntp_sec, m_rtcp_rtp_ts); if (m_rtp_byte_stream != NULL) { m_rtp_byte_stream->set_skip_on_advance(4); player_debug_message("Starting mp3 2250 audio byte stream"); return; } } break; case MPEG4IP_AUDIO_MP3_ROBUST: m_rtp_byte_stream = new CRfc3119RtpByteStream(rtp_pt, fmt, stream_ondemand, tps, &m_head, &m_tail, m_rtsp_base_seq_received, m_rtp_base_seq, m_rtsp_base_ts_received, m_rtp_base_ts, m_rtcp_received, m_rtcp_ntp_frac, m_rtcp_ntp_sec, m_rtcp_rtp_ts); if (m_rtp_byte_stream != NULL) { player_debug_message("Starting mpa robust byte stream"); return; } break; case MPEG4IP_AUDIO_GENERIC: m_rtp_byte_stream = new CAudioRtpByteStream(rtp_pt, fmt, stream_ondemand, tps, &m_head, &m_tail, m_rtsp_base_seq_received, m_rtp_base_seq, m_rtsp_base_ts_received, m_rtp_base_ts, m_rtcp_received, m_rtcp_ntp_frac, m_rtcp_ntp_sec, m_rtcp_rtp_ts); if (m_rtp_byte_stream != NULL) { player_debug_message("Starting generic audio byte stream"); return; } default: break; } } } if (m_rtp_byte_stream == NULL) m_rtp_byte_stream = new CRtpByteStream(fmt->media->media, fmt, rtp_pt, stream_ondemand, tps, &m_head, &m_tail, m_rtsp_base_seq_received, m_rtp_base_seq, m_rtsp_base_ts_received, m_rtp_base_ts, m_rtcp_received, m_rtcp_ntp_frac, m_rtcp_ntp_sec, m_rtcp_rtp_ts); }