⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mp4_file.cpp

📁 jpeg and mpeg 编解码技术源代码
💻 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 + -