📄 media_utils.cpp
字号:
/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is MPEG4IP. * * The Initial Developer of the Original Code is Cisco Systems Inc. * Portions created by Cisco Systems Inc. are * Copyright (C) Cisco Systems Inc. 2000-2005. All Rights Reserved. * * Contributor(s): * Bill May wmay@cisco.com *//* * media_utils.cpp - various utilities, globals (ick). */#include "mpeg4ip.h"#include <sdp/sdp.h>#include <libhttp/http.h>#include "media_utils.h"#include "player_session.h"#include "player_media.h"#include "avi_file.h"#include "mp4_file.h"#include "qtime_file.h"#include "our_config_file.h"#include "rtp_bytestream.h"#include "codec_plugin_private.h"#include "audio.h"#ifndef _WIN32#include "mpeg3_file.h"#include "mpeg2t.h"#include "mpeg2t_file.h"#endif#include "our_bytestream_file.h"#include <rtp/net_udp.h> /* * This needs to be global so we can store any ports that we don't * care about but need to reserve *//* * these are lists of supported audio and video codecs */static struct codec_list_t { const char *name; int val;} video_codecs[] = { {"mp4 ", VIDEO_MPEG4_ISO}, {"mp4v", VIDEO_MPEG4_ISO}, {"encv", VIDEO_MPEG4_ISO}, {"MPG4", VIDEO_MPEG4_ISO}, {"MP4V-ES", VIDEO_MPEG4_ISO_OR_DIVX}, {"MPEG4-GENERIC", VIDEO_DIVX}, {"divx", VIDEO_DIVX}, {"dvx1", VIDEO_DIVX}, {"div4", VIDEO_DIVX}, {NULL, -1},}, audio_codecs[] = { {"MPA", MPEG4IP_AUDIO_MP3 }, {"mpa-robust", MPEG4IP_AUDIO_MP3_ROBUST}, {"L16", MPEG4IP_AUDIO_GENERIC }, {"L8", MPEG4IP_AUDIO_GENERIC }, {NULL, -1}, };static int lookup_codec_by_name (const char *name, struct codec_list_t *codec_list){ for (struct codec_list_t *cptr = codec_list; cptr->name != NULL; cptr++) { if (strcasecmp(name, cptr->name) == 0) { return (cptr->val); } } return (-1);} int lookup_audio_codec_by_name (const char *name){ return (lookup_codec_by_name(name, audio_codecs));}int lookup_video_codec_by_name (const char *name){ return (lookup_codec_by_name(name, video_codecs));} static int create_media_from_sdp (CPlayerSession *psptr, session_desc_t *sdp, int have_audio_driver, int broadcast, int only_check_first, control_callback_vft_t *cc_vft){ int err; int media_count = 0; int invalid_count = 0; int have_audio_but_no_driver = 0; char buffer[80]; codec_plugin_t *codec; format_list_t *fmt; uint audio_count, video_count, text_count; uint audio_offset, video_offset, text_offset; uint ix; if (sdp->session_name != NULL) { snprintf(buffer, sizeof(buffer), "Name: %s", sdp->session_name); psptr->set_session_desc(0, buffer); } if (sdp->session_desc != NULL) { snprintf(buffer, sizeof(buffer), "Description: %s", sdp->session_desc); psptr->set_session_desc(1, buffer); }#ifndef _WIN32 if (sdp->media != NULL && sdp->media->next == NULL && strcasecmp(sdp->media->media, "video") == 0 && sdp->media->fmt_list != NULL && strcmp(sdp->media->fmt_list->fmt, "33") == 0) { // we have a mpeg2 transport stream return (create_mpeg2t_session(psptr, NULL, sdp, have_audio_driver, cc_vft)); }#endif media_desc_t *sdp_media; audio_count = video_count = text_count = 0; for (sdp_media = psptr->get_sdp_info()->media; sdp_media != NULL; sdp_media = sdp_media->next) { if (strcasecmp(sdp_media->media, "audio") == 0) { if (have_audio_driver == 0) { have_audio_but_no_driver = 1; } else { audio_count++; } } else if (strcasecmp(sdp_media->media, "video") == 0) { video_count++; } else if (strcasecmp(sdp_media->media, "control") == 0 || strcasecmp(sdp_media->media, "application") == 0) { text_count++; } } video_query_t *vq; audio_query_t *aq; text_query_t *tq; if (video_count > 0) { vq = (video_query_t *)malloc(sizeof(video_query_t) * video_count); } else { vq = NULL; } if (audio_count > 0) { aq = (audio_query_t *)malloc(sizeof(audio_query_t) * audio_count); } else { aq = NULL; } if (text_count > 0) { tq = (text_query_t *)malloc(sizeof(text_query_t) * text_count); } else { tq = NULL; } video_offset = audio_offset = text_offset = 0; for (sdp_media = psptr->get_sdp_info()->media; sdp_media != NULL; sdp_media = sdp_media->next) { if (have_audio_driver != 0 && strcasecmp(sdp_media->media, "audio") == 0) { fmt = sdp_media->fmt_list; codec = NULL; while (codec == NULL && fmt != NULL) { codec = check_for_audio_codec(STREAM_TYPE_RTP, NULL, fmt, -1, -1, NULL, 0, &config); if (codec == NULL) { if (only_check_first != 0) fmt = NULL; else fmt = fmt->next; } } if (codec == NULL) { invalid_count++; continue; } else { // set up audio qualifier aq[audio_offset].track_id = audio_offset; aq[audio_offset].stream_type = STREAM_TYPE_RTP; aq[audio_offset].compressor = NULL; aq[audio_offset].type = -1; aq[audio_offset].profile = -1; aq[audio_offset].fptr = fmt; aq[audio_offset].sampling_freq = -1; aq[audio_offset].chans = -1; aq[audio_offset].enabled = 0; aq[audio_offset].reference = NULL; audio_offset++; } } else if (strcasecmp(sdp_media->media, "video") == 0) { fmt = sdp_media->fmt_list; codec = NULL; while (codec == NULL && fmt != NULL) { codec = check_for_video_codec(STREAM_TYPE_RTP, NULL, fmt, -1, -1, NULL, 0, &config); if (codec == NULL) { if (only_check_first != 0) fmt = NULL; else fmt = fmt->next; } } if (codec == NULL) { invalid_count++; continue; } else { vq[video_offset].track_id = video_offset; vq[video_offset].stream_type = STREAM_TYPE_RTP; vq[video_offset].compressor = NULL; vq[video_offset].type = -1; vq[video_offset].profile = -1; vq[video_offset].fptr = fmt; vq[video_offset].h = -1; vq[video_offset].w = -1; vq[video_offset].frame_rate = -1; vq[video_offset].enabled = 0; vq[video_offset].reference = NULL; video_offset++; } } else if (strcasecmp(sdp_media->media, "application") == 0 || strcasecmp(sdp_media->media, "control") == 0) { fmt = sdp_media->fmt_list; codec = NULL; while (codec == NULL && fmt != NULL) { codec = check_for_text_codec(STREAM_TYPE_RTP, NULL, fmt, NULL, 0, &config); if (codec == NULL) { if (only_check_first != 0) { fmt = NULL; } else { fmt = fmt->next; } } else { if (fmt != sdp_media->fmt_list || fmt->next != NULL) { player_error_message("Disallow sdp stream %s - more than 1 possible format", sdp_media->media); codec = NULL; fmt = fmt->next; } } } if (codec == NULL) { invalid_count++; continue; } else { tq[text_offset].track_id = text_offset; tq[text_offset].stream_type = STREAM_TYPE_RTP; tq[text_offset].compressor = NULL; tq[text_offset].fptr = fmt; tq[text_offset].config = NULL; tq[text_offset].config_len = 0; tq[text_offset].enabled = 0; tq[text_offset].reference = NULL; text_offset++; } } else { player_error_message("Skipping media type `%s\'", sdp_media->media); continue; } } // okay - from here, write the callback call, and go ahead... if (cc_vft != NULL && cc_vft->media_list_query != NULL) { (cc_vft->media_list_query)(psptr, video_offset, vq, audio_offset, aq, text_offset, tq); } else { if (video_offset > 0) { vq[0].enabled = 1; } if (audio_offset > 0) { aq[0].enabled = 1; } if (text_offset > 0) { tq[0].enabled = 1; } } for (ix = 0; ix < video_offset; ix++) { if (vq[ix].enabled != 0) { CPlayerMedia *mptr = new CPlayerMedia(psptr, VIDEO_SYNC); err = mptr->create_streaming(vq[ix].fptr->media, broadcast, config.get_config_value(CONFIG_USE_RTP_OVER_RTSP), media_count, ix == 0 ? psptr->get_video_rtp_session() : NULL); if (err < 0) { return (-1); } if (err > 0) { delete mptr; } else media_count++; } } for (ix = 0; ix < audio_offset; ix++) { if (aq[ix].enabled != 0) { CPlayerMedia *mptr = new CPlayerMedia(psptr, AUDIO_SYNC); err = mptr->create_streaming(aq[ix].fptr->media, broadcast, config.get_config_value(CONFIG_USE_RTP_OVER_RTSP), media_count, ix == 0 ? psptr->get_audio_rtp_session() : NULL); if (err < 0) { return (-1); } if (err > 0) { delete mptr; } else media_count++; } } for (ix = 0; ix < text_offset; ix++) { if (tq[ix].enabled != 0) { CPlayerMedia *mptr = new CPlayerMedia(psptr, TIMED_TEXT_SYNC); err = mptr->create_streaming(tq[ix].fptr->media, broadcast, config.get_config_value(CONFIG_USE_RTP_OVER_RTSP), media_count, NULL); if (err < 0) { return (-1); } if (err > 0) { delete mptr; } else media_count++; } } if (aq != NULL) free(aq); if (vq != NULL) free(vq); if (tq != NULL) free(tq); if (media_count == 0) { psptr->set_message("No known codecs found in SDP"); return (-1); } psptr->streaming_media_set_up(); if (have_audio_but_no_driver > 0) { psptr->set_message("Not playing audio codecs - no driver"); return (1); } if (invalid_count > 0) { psptr->set_message("There were unknowns codecs during decode - playing valid ones"); return (1); } return (0);}/* * This is where we get the sdp from a source, iptv or http */static int create_media_for_streaming_broadcast (CPlayerSession *psptr, session_desc_t *sdp, int have_audio_driver, control_callback_vft_t *cc_vft){ int err; // need to set range in player session... err = psptr->create_streaming_broadcast(sdp); if (err != 0) { return (-1); } return (create_media_from_sdp(psptr, sdp, have_audio_driver, 0, 1, cc_vft));}/* * create_media_for_streaming_ondemand - create streaming media session * for an on demand program. */static int create_media_for_streaming_ondemand (CPlayerSession *psptr, const char *name, control_callback_vft_t *cc_vft){ int err; session_desc_t *sdp; /* * This will open the rtsp session */ err = psptr->create_streaming_ondemand(name, config.get_config_value(CONFIG_USE_RTP_OVER_RTSP)); if (err != 0) { return (-1); } sdp = psptr->get_sdp_info(); int have_audio_driver = do_we_have_audio(); return (create_media_from_sdp(psptr, sdp, have_audio_driver, 1, 0, cc_vft));}/* * create_media_from_sdp_file - create a streaming session based on an * sdp file. It could be either an on-demand program (we look for the * url in the control string), or a broadcast. */static int create_from_sdp (CPlayerSession *psptr, const char *name, sdp_decode_info_t *sdp_info, int have_audio_driver, control_callback_vft_t *cc_vft) { session_desc_t *sdp; int translated; if (sdp_info == NULL) { psptr->set_message("SDP error"); return (-1); } if (sdp_decode(sdp_info, &sdp, &translated) != 0) { psptr->set_message("Invalid SDP file"); sdp_decode_info_free(sdp_info); return (-1); } if (translated != 1) { psptr->set_message("More than 1 program described in SDP"); sdp_decode_info_free(sdp_info); return (-1); } int err; if (sdp->control_string != NULL) { // An on demand file... Just use the URL... err = create_media_for_streaming_ondemand(psptr, sdp->control_string, cc_vft); sdp_free_session_desc(sdp); sdp_decode_info_free(sdp_info); return (err); } sdp_decode_info_free(sdp_info); return (create_media_for_streaming_broadcast(psptr, sdp, have_audio_driver, cc_vft));}static int create_media_from_sdp_file(CPlayerSession *psptr, const char *name, int have_audio_driver, control_callback_vft_t *cc_vft){ sdp_decode_info_t *sdp_info; sdp_info = set_sdp_decode_from_filename(name); return (create_from_sdp(psptr, name, sdp_info, have_audio_driver, cc_vft));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -