📄 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 <stdlib.h>
#include <sdp/sdp.h>
#include <libhttp/http.h>
#include "media_utils.h"
#include "player_session.h"
#include "player_media.h"
#include "codec/mp3/mp3_rtp_bytestream.h"
#include "avi_file.h"
#include "mp4_file.h"
#include "qtime_file.h"
#include "our_config_file.h"
#include "rtp_bytestream.h"
#include "codec/aa/isma_rtp_bytestream.h"
#include "codec_plugin_private.h"
#include <gnu/strcasestr.h>
#include "rfc3119_bytestream.h"
#include "mpeg3_rtp_bytestream.h"
#include "mpeg3_file.h"
#include "audio.h"
#include "mpeg2t.h"
/*
* This needs to be global so we can store any ports that we don't
* care about but need to reserve
*/
enum {
VIDEO_MPEG4_ISO,
VIDEO_DIVX,
VIDEO_MPEG4_ISO_OR_DIVX,
VIDEO_MPEG12,
};
enum {
MPEG4IP_AUDIO_AAC,
MPEG4IP_AUDIO_MP3,
MPEG4IP_AUDIO_WAV,
MPEG4IP_AUDIO_MPEG4_GENERIC,
MPEG4IP_AUDIO_MP3_ROBUST,
MPEG4IP_AUDIO_GENERIC,
};
/*
* 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[] = {
{"MPEG4-GENERIC", MPEG4IP_AUDIO_MPEG4_GENERIC},
{"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,
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);
}
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
}
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) 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) 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,
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,
cc_vft));
}
/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -