📄 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, 2001. All Rights Reserved. * * Contributor(s): * Bill May wmay@cisco.com *//* * media_utils.cpp - various utilities, globals (ick). */#include "systems.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 <gnu/strcasestr.h>#include "mpeg3_file.h"#include "audio.h"#ifndef _WIN32#include "mpeg2t.h"#endif/* * 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}, {"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, const char *name, session_desc_t *sdp, char *errmsg, uint32_t errlen, 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; int audio_count, video_count; int audio_offset, video_offset; int 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 != NULL && strcmp(sdp->media->fmt->fmt, "33") == 0) { // we have a mpeg2 transport stream return (create_mpeg2t_session(psptr, NULL, sdp, errmsg, errlen, have_audio_driver, cc_vft)); }#endif media_desc_t *sdp_media; audio_count = video_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++; } } video_query_t *vq; audio_query_t *aq; 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; } video_offset = audio_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; codec = NULL; while (codec == NULL && fmt != NULL) { codec = check_for_audio_codec(NULL, fmt, -1, -1, NULL, 0); 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].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; codec = NULL; while (codec == NULL && fmt != NULL) { codec = check_for_video_codec(NULL, fmt, -1, -1, NULL, 0); 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].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 { 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); } else { if (video_offset > 0) { vq[0].enabled = 1; } if (audio_offset > 0) { aq[0].enabled = 1; } } for (ix = 0; ix < video_offset; ix++) { if (vq[ix].enabled != 0) { CPlayerMedia *mptr = new CPlayerMedia(psptr); err = mptr->create_streaming(vq[ix].fptr->media, errmsg, errlen, broadcast, config.get_config_value(CONFIG_USE_RTP_OVER_RTSP), media_count); 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); err = mptr->create_streaming(aq[ix].fptr->media, errmsg, errlen, broadcast, config.get_config_value(CONFIG_USE_RTP_OVER_RTSP), media_count); if (err < 0) { return (-1); } if (err > 0) { delete mptr; } else media_count++; } } if (aq != NULL) free(aq); if (vq != NULL) free(vq); if (media_count == 0) { snprintf(errmsg, errlen, "No known codecs found in SDP"); return (-1); } psptr->streaming_media_set_up(); if (have_audio_but_no_driver > 0) { snprintf(errmsg, errlen, "Not playing audio codecs - no driver"); return (1); } if (invalid_count > 0) { snprintf(errmsg, errlen, "There were unknowns codecs during decode - playing valid ones"); return (1); } return (0);}static int create_media_for_streaming_broadcast (CPlayerSession *psptr, const char *name, session_desc_t *sdp, char *errmsg, uint32_t errlen, 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, errmsg, errlen); if (err != 0) { return (-1); } return (create_media_from_sdp(psptr, name, sdp, errmsg, errlen, 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, char *errmsg, uint32_t errlen, control_callback_vft_t *cc_vft){ int err; session_desc_t *sdp; /* * This will open the rtsp session */ err = psptr->create_streaming_ondemand(name, errmsg, errlen, 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, name, sdp, errmsg, errlen, 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, char *errmsg, uint32_t errlen, 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) { strcpy(errmsg, "SDP error"); return (-1); } if (sdp_decode(sdp_info, &sdp, &translated) != 0) { snprintf(errmsg, errlen, "Invalid SDP file"); sdp_decode_info_free(sdp_info); return (-1); } if (translated != 1) { snprintf(errmsg, errlen, "More than 1 program described in SDP");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -