📄 mpeg2t_thread.cpp
字号:
have_duration = endptr != dptr; } } } } } } else { // not good, but try anyway for setup. } if (decode != NULL) free_decode_response(decode); // we're done with describe - we might have something, we might not // lets go with a SETUP. memset(&cmd, 0, sizeof(rtsp_command_t)); decode = NULL; char buffer[2048]; char *ouraddr = get_host_ip_address(); C2ConsecIpPort *port = new C2ConsecIpPort(psptr->get_unused_ip_port_ptr()); snprintf(buffer, sizeof(buffer), "RAW/RAW/UDP;unicast;destination=%s;client_port=%u", ouraddr, port->first_port()); cmd.transport = buffer; rtsp_session_t *session; err = rtsp_send_setup(rptr, rtsp_url, &cmd, &session, &decode, 1); free(ouraddr); if (err != RTSP_RESPONSE_GOOD) { if (decode != NULL) { psptr->set_message("RTSP error %s %s", decode->retcode, decode->retresp); } else { psptr->set_message("RTSP setup error %d", err); } free_rtsp_client(rptr); free_decode_response(decode); free(rtsp_url); return NULL; } // we have a good setup - we'll need to parse the transport for the // ports to set up, then create the client. rtsp_transport_parse_t parse; memset(&parse, 0, sizeof(parse)); parse.client_port = port->first_port(); delete port; err = process_rtsp_transport(&parse, decode->transport, "RAW/RAW/UDP"); if (err < 0) { psptr->set_message("error in rtsp transport \"%s\"", decode->transport); free_rtsp_client(rptr); free_decode_response(decode); free(rtsp_url); return NULL; } free_decode_response(decode); mp2t = mpeg2t_create_client(psptr, parse.source, parse.client_port, parse.server_port, 0, 0.0, 0, rptr, rtsp_url); // now, we'll start playing, and capturingr until we get enough to set // up the decoders - we'll save everything for a bit if (mp2t != NULL) { mp2t->m_have_end_time = have_duration; mp2t->m_end_time = duration; } return mp2t;}void mpeg2t_check_streams (video_query_t **pvq, audio_query_t **paq, mpeg2t_t *decoder, uint &audio_count, uint &video_count, CPlayerSession *psptr, control_callback_vft_t *cc_vft){ uint audio_info_count, video_info_count; mpeg2t_pid_t *pid_ptr; mpeg2t_es_t *es_pid; int passes; pid_ptr = &decoder->pas.pid; audio_count = video_count = 0; audio_info_count = video_info_count = 0; passes = 0; do { SDL_LockMutex(decoder->pid_mutex); while (pid_ptr != NULL) { switch (pid_ptr->pak_type) { case MPEG2T_PAS_PAK: case MPEG2T_PROG_MAP_PAK: break; case MPEG2T_ES_PAK: es_pid = (mpeg2t_es_t *)pid_ptr; switch (es_pid->stream_type) { case MPEG2T_ST_MPEG_VIDEO: case MPEG2T_ST_MPEG4_VIDEO: case MPEG2T_ST_11172_VIDEO: case MPEG2T_ST_H264_VIDEO: video_count++; if (es_pid->info_loaded) video_info_count++; break; case MPEG2T_ST_11172_AUDIO: case MPEG2T_ST_MPEG_AUDIO: case 129: audio_count++; if (es_pid->info_loaded) audio_info_count++; break; case MPEG2T_ST_MPEG_AUDIO_6_A: case MPEG2T_ST_MPEG_AUDIO_6_B: case MPEG2T_ST_MPEG_AUDIO_6_C: case MPEG2T_ST_MPEG_AUDIO_6_D: case MPEG2T_ST_MPEG2_AAC: default: mpeg2t_message(LOG_INFO, "PID %x - Unknown/unused stream type %d", pid_ptr->pid, es_pid->stream_type); break; } break; } pid_ptr = pid_ptr->next_pid; } SDL_UnlockMutex(decoder->pid_mutex); passes++; if (audio_count != audio_info_count || video_info_count != video_count) { SDL_Delay(1 * 1000); } } while (audio_info_count != audio_count && video_info_count != video_info_count); video_query_t *vq; audio_query_t *aq; if (video_count > 0) { vq = (video_query_t *)malloc(sizeof(video_query_t) * video_count); memset(vq, 0, sizeof(video_query_t) * video_count); } else { vq = NULL; } if (audio_count > 0) { aq = (audio_query_t *)malloc(sizeof(audio_query_t) * audio_count); memset(aq, 0, sizeof(audio_query_t) * audio_count); } else { aq = NULL; } *pvq = vq; *paq = aq; uint vid_cnt = 0, aud_cnt = 0; codec_plugin_t *plugin; pid_ptr = &decoder->pas.pid; SDL_LockMutex(decoder->pid_mutex); while (pid_ptr != NULL) { switch (pid_ptr->pak_type) { case MPEG2T_PAS_PAK: case MPEG2T_PROG_MAP_PAK: break; case MPEG2T_ES_PAK: es_pid = (mpeg2t_es_t *)pid_ptr; if (es_pid->is_video > 0) { if (vid_cnt < video_count) { plugin = check_for_video_codec(STREAM_TYPE_MPEG2_TRANSPORT_STREAM, NULL, NULL, es_pid->stream_type, -1, es_pid->es_data, es_pid->es_info_len, &config); if (plugin == NULL) { psptr->set_message( "Can't find video plugin for stream type %d", es_pid->stream_type); mpeg2t_message(LOG_ERR, "%s", psptr->get_message()); } else { vq[vid_cnt].track_id = pid_ptr->pid; vq[vid_cnt].stream_type = STREAM_TYPE_MPEG2_TRANSPORT_STREAM; vq[vid_cnt].compressor = NULL; vq[vid_cnt].type = es_pid->stream_type; vq[vid_cnt].profile = -1; vq[vid_cnt].fptr = NULL; if (es_pid->info_loaded != 0) { vq[vid_cnt].h = es_pid->h; vq[vid_cnt].w = es_pid->w; vq[vid_cnt].frame_rate = es_pid->frame_rate; mpeg2t_message(LOG_DEBUG, "video stream h %d w %d fr %g bitr %g", es_pid->h, es_pid->w, es_pid->frame_rate, es_pid->bitrate); } else { vq[vid_cnt].h = -1; vq[vid_cnt].w = -1; vq[vid_cnt].frame_rate = 0.0; } vq[vid_cnt].config = es_pid->es_data; vq[vid_cnt].config_len = es_pid->es_info_len; es_pid->es_data = NULL; es_pid->es_info_len = 0; vq[vid_cnt].enabled = 0; vq[vid_cnt].reference = NULL; vid_cnt++; } } } else { if (aud_cnt < audio_count) { plugin = check_for_audio_codec(STREAM_TYPE_MPEG2_TRANSPORT_STREAM, NULL, NULL, es_pid->stream_type, -1, es_pid->es_data, es_pid->es_info_len, &config); if (plugin == NULL) { psptr->set_message( "Can't find audio plugin for stream type %d", es_pid->stream_type); mpeg2t_message(LOG_ERR, "%s", psptr->get_message()); } else { aq[aud_cnt].track_id = pid_ptr->pid; aq[aud_cnt].stream_type = STREAM_TYPE_MPEG2_TRANSPORT_STREAM; aq[aud_cnt].compressor = NULL; aq[aud_cnt].type = es_pid->stream_type; aq[aud_cnt].profile = -1; aq[aud_cnt].fptr = NULL; aq[aud_cnt].config = es_pid->es_data; aq[aud_cnt].config_len = es_pid->es_info_len; es_pid->es_data = NULL; es_pid->es_info_len = 0; if (es_pid->info_loaded != 0) { aq[aud_cnt].chans = es_pid->audio_chans; aq[aud_cnt].sampling_freq = es_pid->sample_freq; mpeg2t_message(LOG_DEBUG, "audio stream chans %d sf %d bitrate %g", es_pid->audio_chans, es_pid->sample_freq, es_pid->bitrate / 1000.0); } else { aq[aud_cnt].chans = -1; aq[aud_cnt].sampling_freq = -1; } aq[aud_cnt].enabled = 0; aq[aud_cnt].reference = NULL; aud_cnt++; } } } } pid_ptr = pid_ptr->next_pid; } SDL_UnlockMutex(decoder->pid_mutex); if (cc_vft && cc_vft->media_list_query != NULL) { (cc_vft->media_list_query)(psptr, vid_cnt, vq, aud_cnt, aq, 0, NULL); } else { if (video_count > 0) { vq[0].enabled = 1; } if (audio_count > 0) { aq[0].enabled = 1; } } video_count = vid_cnt; audio_count = aud_cnt;}int create_mpeg2t_session (CPlayerSession *psptr, const char *orig_name, session_desc_t *sdp, int have_audio_driver, control_callback_vft_t *cc_vft){ const char *colon, *slash, *name; char *addr, *port; uint32_t addrlen, portlen; mpeg2t_client_t *mp2t; in_port_t rxport; if (orig_name != NULL) { name = orig_name + strlen("mpeg2t://"); colon = strchr(name, ':'); slash = strchr(name, '/'); if (slash == NULL) { slash = name + strlen(name); if (colon == NULL || slash == NULL || colon > slash) { psptr->set_message("Misformed mpeg2 url %s", orig_name); return -1; } addrlen = colon - name; portlen = slash - colon - 1; addr = (char *)malloc(1 + addrlen); port = (char *)malloc(1 + portlen); memcpy(addr, name, addrlen); addr[addrlen] = '\0'; memcpy(port, colon + 1, portlen); port[portlen] = '\0'; char *eport; rxport = strtoul(port, &eport, 10); if (eport == NULL || *eport != '\0') { psptr->set_message("Illegal port number in url %s", orig_name); free(addr); free(port); return -1; } free(port); mp2t = mpeg2t_create_client(psptr, addr, rxport, 0, 0, 0.0, 0); free(addr); } else { // we have a rtsp like url. mp2t = mpeg2t_start_rtsp(psptr, orig_name); if (mp2t == NULL) return -1; } } else if (sdp != NULL) { // from SDP connect_desc_t *cptr; double bw; cptr = get_connect_desc_from_media(sdp->media); if (find_rtcp_bandwidth_from_media(sdp->media, &bw) < 0) { bw = 5000.0; } mp2t = mpeg2t_create_client(psptr, cptr->conn_addr, sdp->media->port, 0, 1, // use rtp bw, cptr->ttl); } else { return -1; } if (mp2t == NULL) { return -1; } psptr->set_media_close_callback(close_mpeg2t_client, mp2t); // Okay - we need to gather together information about pids and // lists, then call the audio/video query vectors. uint audio_count, video_count; video_query_t *vq; audio_query_t *aq; mp2t->decoder->save_frames_at_start = 0; mpeg2t_check_streams(&vq, &aq, mp2t->decoder, audio_count, video_count, psptr, cc_vft); int total_enabled = 0; psptr->set_session_desc(0, "MPEG2 Transport Stream"); int sdesc = 1; // create video media int ret = mpeg2t_create_video(mp2t, psptr, vq, video_count, sdesc); if (ret < 0) { free(aq); free(vq); return -1; } total_enabled += ret; // create audio media ret = mpeg2t_create_audio(mp2t, psptr, aq, audio_count, sdesc); if (ret < 0) { free(aq); free(vq); return -1; } total_enabled += ret; free(aq); free(vq); if (total_enabled != 0) { // This is to get the m_streaming bit set, so we can do the // elapsed time correctly if (mp2t->m_rtsp_client) { psptr->create_streaming_ondemand_other(mp2t->m_rtsp_client, mp2t->m_rtsp_url, mp2t->m_have_end_time, mp2t->m_end_time, 1, 0); } else { psptr->create_streaming_broadcast(NULL); } return 0; } return -1;} // NOTE TO SELF - need to add a mechanism that indicates that // we're paused. We'll need to keep reading the RTP packets, but// will want to flush them.// Options are to add a do_pause to the bytestream.// or have a pause registration in either player media or playersession
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -