📄 mp4_file.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
*/
/*
* qtime_file.cpp - provides generic class for quicktime file access control.
* file access is then used by quicktime audio and video bytestreams.
*/
#include "systems.h"
#include "player_session.h"
#include "player_media.h"
#include "player_util.h"
#include "media_utils.h"
#include <mp4.h>
#include "mp4_bytestream.h"
#include "mp4_file.h"
#include <mp4util/mpeg4_audio_config.h>
#include "our_config_file.h"
#include "codec_plugin_private.h"
/*
* Create the media for the quicktime file, and set up some session stuff.
*/
static void close_mp4_file (void *data)
{
CMp4File *Mp4File1 = (CMp4File *)data;
if (Mp4File1 != NULL) {
delete Mp4File1;
Mp4File1 = NULL;
}
}
int create_media_for_mp4_file (CPlayerSession *psptr,
const char *name,
char *errmsg,
uint32_t errlen,
int have_audio_driver,
control_callback_vft_t *cc_vft)
{
MP4FileHandle fh;
CMp4File *Mp4File1;
fh = MP4Read(name, MP4_DETAILS_ERROR);
if (!MP4_IS_VALID_FILE_HANDLE(fh)) {
snprintf(errmsg, errlen, "`%s\' is not an mp4 file", name);
return -1;
}
Mp4File1 = new CMp4File(fh);
// quicktime is searchable...
psptr->set_media_close_callback(close_mp4_file, (void *)Mp4File1);
psptr->session_set_seekable(1);
int ret;
ret = Mp4File1->create_media(psptr,
errmsg,
errlen,
have_audio_driver,
cc_vft);
if (ret <= 0) return ret;
int offset = 0;
if (Mp4File1->get_illegal_video_codec() != 0) {
offset = snprintf(errmsg, errlen, "Unknown or unused Video tracks ");
}
if (Mp4File1->have_audio() != 0 && have_audio_driver == 0) {
offset += snprintf(errmsg + offset, errlen - offset,
"%sNo Audio driver - can't play audio",
offset == 0 ? "" : "and ");
} else if (Mp4File1->get_illegal_audio_codec() != 0) {
snprintf(errmsg + offset, errlen - offset,
"%sUnknown or unused audio tracks",
offset == 0 ? "" : "and ");
}
return (1);
}
CMp4File::CMp4File (MP4FileHandle filehandle)
{
m_mp4file = filehandle;
m_file_mutex = SDL_CreateMutex();
m_illegal_audio_codec = 0;
m_illegal_video_codec = 0;
m_have_audio = 0;
}
CMp4File::~CMp4File (void)
{
MP4Close(m_mp4file);
m_mp4file = NULL;
if (m_file_mutex) {
SDL_DestroyMutex(m_file_mutex);
m_file_mutex = NULL;
}
}
int CMp4File::create_video(CPlayerSession *psptr,
video_query_t *vq,
int video_offset,
char *errmsg,
uint32_t errlen,
int &start_desc)
{
int ix;
CPlayerMedia *mptr;
codec_plugin_t *plugin;
for (ix = 0; ix < video_offset; ix++) {
if (vq[ix].enabled != 0) {
mptr = new CPlayerMedia(psptr);
if (mptr == NULL) {
return (-1);
}
video_info_t *vinfo;
vinfo = (video_info_t *)malloc(sizeof(video_info_t));
vinfo->height = vq[ix].h;
vinfo->width = vq[ix].w;
plugin = check_for_video_codec("MP4 FILE",
NULL,
vq[ix].type,
vq[ix].profile,
vq[ix].config,
vq[ix].config_len);
int ret = mptr->create_video_plugin(plugin,
NULL, // sdp info
vinfo, // video info
vq[ix].config,
vq[ix].config_len);
if (ret < 0) {
mp4f_message(LOG_ERR, "Failed to create plugin data");
snprintf(errmsg, errlen, "Failed to start plugin");
delete mptr;
return -1;
}
CMp4VideoByteStream *vbyte;
vbyte = new CMp4VideoByteStream(this, vq[ix].track_id);
if (vbyte == NULL) {
delete mptr;
return (-1);
}
ret = mptr->create_from_file(vbyte, TRUE);
if (ret != 0) {
return (-1);
}
char *mp4info = MP4Info(m_mp4file, vq[ix].track_id);
char *temp = mp4info;
while (*temp != '\0') {
if (isspace(*temp)) *temp = ' ';
if (!isprint(*temp)) *temp = '*';
temp++;
}
psptr->set_session_desc(start_desc, mp4info);
free(mp4info);
start_desc++;
} else {
if (vq[ix].config != NULL) free((void *)vq[ix].config);
}
}
return 0;
}
int CMp4File::create_audio(CPlayerSession *psptr,
audio_query_t *aq,
int audio_offset,
char *errmsg,
uint32_t errlen,
int &start_desc)
{
int ix;
CPlayerMedia *mptr;
codec_plugin_t *plugin;
for (ix = 0; ix < audio_offset; ix++) {
if (aq[ix].enabled != 0) {
CMp4AudioByteStream *abyte;
mptr = new CPlayerMedia(psptr);
if (mptr == NULL) {
return (-1);
}
abyte = new CMp4AudioByteStream(this, aq[ix].track_id);
audio_info_t *ainfo;
ainfo = (audio_info_t *)malloc(sizeof(audio_info_t));
memset(ainfo, 0, sizeof(*ainfo));
ainfo->freq = aq[ix].sampling_freq;
if (aq[ix].type == MP4_PCM16_AUDIO_TYPE) {
ainfo->bitspersample = 16;
}
int ret;
plugin = check_for_audio_codec("MP4 FILE",
NULL,
aq[ix].type,
aq[ix].profile,
aq[ix].config,
aq[ix].config_len);
ret = mptr->create_audio_plugin(plugin,
NULL, // sdp info
ainfo, // audio info
aq[ix].config,
aq[ix].config_len);
if (ret < 0) {
mp4f_message(LOG_ERR, "Couldn't create audio from plugin %s",
plugin->c_name);
snprintf(errmsg, errlen, "Couldn't start audio plugin %s",
plugin->c_name);
delete mptr;
delete abyte;
return -1;
}
ret = mptr->create_from_file(abyte, FALSE);
if (ret != 0) {
return (-1);
}
char *mp4info = MP4Info(m_mp4file, aq[ix].track_id);
char *temp = mp4info;
while (*temp != '\0') {
if (isspace(*temp)) *temp = ' ';
if (!isprint(*temp)) *temp = '*';
temp++;
}
psptr->set_session_desc(start_desc, mp4info);
free(mp4info);
start_desc++;
} else {
if (aq[ix].config != NULL) free((void *)aq[ix].config);
}
}
return 0;
}
int CMp4File::create_media (CPlayerSession *psptr,
char *errmsg,
uint32_t errlen,
int have_audio_driver,
control_callback_vft_t *cc_vft)
{
int video_count, video_offset;
int audio_count, audio_offset;
MP4TrackId trackId;
video_query_t *vq;
audio_query_t *aq;
int ix;
codec_plugin_t *plugin;
int ret_value = 0;
video_count = 0;
do {
trackId = MP4FindTrackId(m_mp4file, video_count, MP4_VIDEO_TRACK_TYPE);
if (MP4_IS_VALID_TRACK_ID(trackId)) {
video_count++;
}
} while (MP4_IS_VALID_TRACK_ID(trackId));
audio_count = 0;
do {
trackId = MP4FindTrackId(m_mp4file, audio_count, MP4_AUDIO_TRACK_TYPE);
if (MP4_IS_VALID_TRACK_ID(trackId)) {
audio_count++;
}
} while (MP4_IS_VALID_TRACK_ID(trackId));
if (video_count == 0 && audio_count == 0) {
snprintf(errmsg, errlen, "No audio or video tracks in file");
return -1;
}
if (video_count > 0) {
vq = (video_query_t *)malloc(sizeof(video_query_t) * video_count);
} else {
vq = NULL;
}
if (have_audio_driver && audio_count > 0) {
aq = (audio_query_t *)malloc(sizeof(audio_query_t) * audio_count);
} else {
aq = NULL;
}
for (ix = 0, video_offset = 0; ix < video_count; ix++) {
trackId = MP4FindTrackId(m_mp4file, ix, MP4_VIDEO_TRACK_TYPE);
uint8_t video_type = MP4GetTrackVideoType(m_mp4file, trackId);
uint8_t profileID = MP4GetVideoProfileLevel(m_mp4file);
mp4f_message(LOG_DEBUG, "MP4 - got track %x profile ID %d",
trackId, profileID);
uint8_t *foo;
u_int32_t bufsize;
MP4GetTrackESConfiguration(m_mp4file, trackId, &foo, &bufsize);
plugin = check_for_video_codec("MP4 FILE",
NULL,
video_type,
profileID,
foo,
bufsize);
if (plugin == NULL) {
snprintf(errmsg, errlen,
"Can't find plugin for video type %d, profile %d",
video_type, profileID);
m_illegal_video_codec++;
ret_value = 1;
} else {
vq[video_offset].track_id = trackId;
vq[video_offset].compressor = "MP4 FILE";
vq[video_offset].type = video_type;
vq[video_offset].profile = profileID;
vq[video_offset].fptr = NULL;
vq[video_offset].h = MP4GetTrackVideoHeight(m_mp4file, trackId);
vq[video_offset].w = MP4GetTrackVideoWidth(m_mp4file, trackId);
vq[video_offset].frame_rate = MP4GetTrackVideoFrameRate(m_mp4file, trackId);
vq[video_offset].config = foo;
vq[video_offset].config_len = bufsize;
vq[video_offset].enabled = 0;
vq[video_offset].reference = NULL;
video_offset++;
}
}
audio_offset = 0;
if (have_audio_driver) {
for (ix = 0; ix < audio_count; ix++) {
trackId = MP4FindTrackId(m_mp4file, ix, MP4_AUDIO_TRACK_TYPE);
uint8_t audio_type;
uint8_t profile;
uint8_t *userdata = NULL;
u_int32_t userdata_size;
audio_type = MP4GetTrackAudioType(m_mp4file, trackId);
profile = MP4GetAudioProfileLevel(m_mp4file);
MP4GetTrackESConfiguration(m_mp4file,
trackId,
&userdata,
&userdata_size);
plugin = check_for_audio_codec("MP4 FILE",
NULL,
audio_type,
profile,
userdata,
userdata_size);
if (plugin != NULL) {
aq[audio_offset].track_id = trackId;
aq[audio_offset].compressor = "MP4 FILE";
aq[audio_offset].type = audio_type;
aq[audio_offset].profile = profile;
aq[audio_offset].fptr = NULL;
aq[audio_offset].config = userdata;
aq[audio_offset].config_len = userdata_size;
aq[audio_offset].sampling_freq =
MP4GetTrackTimeScale(m_mp4file, trackId);
aq[audio_offset].chans = -1;
aq[audio_offset].enabled = 0;
aq[audio_offset].reference = NULL;
audio_offset++;
} else {
m_illegal_audio_codec++;
ret_value = 1;
}
}
} else {
if (audio_count)
ret_value = 1;
}
if (cc_vft && 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;
}
}
int ret;
int start_desc = 1;
ret = create_video(psptr, vq, video_offset, errmsg, errlen,start_desc);
free(vq);
if (ret < 0) {
free(aq);
return -1;
}
ret = create_audio(psptr, aq, audio_offset, errmsg, errlen, start_desc);
free(aq);
if (ret < 0) ret_value = -1;
return (ret_value);
}
/* end file mp4_file.cpp */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -