qtime_file.cpp
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:9k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /*
  2.  * The contents of this file are subject to the Mozilla Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/MPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is MPEG4IP.
  13.  * 
  14.  * The Initial Developer of the Original Code is Cisco Systems Inc.
  15.  * Portions created by Cisco Systems Inc. are
  16.  * Copyright (C) Cisco Systems Inc. 2000, 2001.  All Rights Reserved.
  17.  * 
  18.  * Contributor(s): 
  19.  *              Bill May        wmay@cisco.com
  20.  */
  21. /*
  22.  * qtime_file.cpp - provides generic class for quicktime file access control.
  23.  * file access is then used by quicktime audio and video bytestreams.
  24.  */
  25. #include "systems.h"
  26. #include "player_session.h"
  27. #include "player_media.h"
  28. #include "player_util.h"
  29. #include "media_utils.h"
  30. #include "mp4/quicktime.h"
  31. #include "qtime_bytestream.h"
  32. #include "qtime_file.h"
  33. #include <mp4util/mpeg4_audio_config.h>
  34. #include "our_config_file.h"
  35. #include "codec_plugin_private.h"
  36. #include <gnu/strcasestr.h>
  37. #include <mp4v2/mp4.h>
  38. static void close_qt_file (void *data)
  39. {
  40.   CQtimeFile *QTfile1 = (CQtimeFile *)data;
  41.   if (QTfile1 != NULL) {
  42.     delete QTfile1;
  43.     QTfile1 = NULL;
  44.   }
  45. }
  46. /*
  47.  * Create the media for the quicktime file, and set up some session stuff.
  48.  */
  49. int create_media_for_qtime_file (CPlayerSession *psptr, 
  50.  const char *name,
  51.  char *errmsg,
  52.  uint32_t errlen,
  53.  int have_audio_driver)
  54. {
  55.   CQtimeFile *QTfile1;
  56.   if (quicktime_check_sig(name) == 0) {
  57.     snprintf(errmsg, errlen, "File %s is not a quicktime file", name);
  58.     player_error_message(errmsg);
  59.     return (-1);
  60.   }
  61.  
  62.   QTfile1 = new CQtimeFile(name);
  63.   // quicktime is searchable...
  64.   psptr->set_media_close_callback(close_qt_file, QTfile1);
  65.   psptr->session_set_seekable(1);
  66.   int video;
  67.   video = QTfile1->create_video(psptr);
  68.   if (video < 0) {
  69.     snprintf(errmsg, errlen, "Internal quicktime video error");
  70.     return (-1);
  71.   }
  72.   int audio = 0;
  73.   if (have_audio_driver > 0) {
  74.     audio = QTfile1->create_audio(psptr);
  75.     if (audio < 0) {
  76.       snprintf(errmsg, errlen, "Internal quicktime audio error");
  77.       return (-1);
  78.     }
  79.   }
  80.   if (audio == 0 && video == 0) {
  81.     snprintf(errmsg, errlen, "No valid codecs in file %s", name);
  82.     return (-1);
  83.   }
  84.   if (audio == 0 && QTfile1->get_audio_tracks() > 0) {
  85.     if (have_audio_driver > 0) 
  86.       snprintf(errmsg, errlen, "Invalid Audio Codec");
  87.     else 
  88.       snprintf(errmsg, errlen, "No Audio driver - no sound");
  89.     return (1);
  90.   }
  91.   if ((QTfile1->get_video_tracks() != 0) && video == 0) {
  92.     snprintf(errmsg, errlen, "Invalid Video Codec");
  93.     return (1);
  94.   }
  95.   return (0);
  96. }
  97. CQtimeFile::CQtimeFile (const char *name)
  98. {
  99.   m_name = strdup(name);
  100.   m_qtfile = quicktime_open(m_name, 1, 0, 0);
  101.   m_file_mutex = SDL_CreateMutex();
  102. }
  103. CQtimeFile::~CQtimeFile (void)
  104. {
  105.   free(m_name);
  106.   m_name = NULL;
  107.   quicktime_close(m_qtfile);
  108.   if (m_file_mutex) {
  109.     SDL_DestroyMutex(m_file_mutex);
  110.     m_file_mutex = NULL;
  111.   }
  112. }
  113. int CQtimeFile::create_video (CPlayerSession *psptr)
  114. {
  115.   CPlayerMedia *mptr;
  116.   codec_plugin_t *plugin;
  117.   int ret;
  118.   int vid_cnt = 0;
  119.   m_video_tracks = quicktime_video_tracks(m_qtfile);
  120.   player_debug_message("qtime video tracks %d", m_video_tracks);
  121.   for (int ix = 0; ix < m_video_tracks && vid_cnt == 0; ix++) { 
  122.     video_info_t *vinfo;
  123.     const char *codec_name = quicktime_video_compressor(m_qtfile, ix);
  124.     if (codec_name == NULL) 
  125.       continue;
  126.     int profileID = -1;
  127.     int type = -1;
  128.     if (strcasestr(m_name, ".mp4") != NULL && 
  129. strcasecmp(codec_name, "mp4v") == 0) {
  130.       profileID = quicktime_get_iod_video_profile_level(m_qtfile);
  131.       codec_name = "mpeg4";
  132.       type = MP4_MPEG4_VIDEO_TYPE;
  133.     }
  134.     plugin = check_for_video_codec(codec_name,
  135.    NULL, 
  136.    type,
  137.    profileID,
  138.    NULL,
  139.    0);
  140.     if (plugin == NULL) {
  141.       player_debug_message("Couldn't find video codec %s", codec_name);
  142.       continue;
  143.     }
  144.     mptr = new CPlayerMedia(psptr);
  145.     if (mptr == NULL) {
  146.       return (-1);
  147.     }
  148.     
  149.     /*
  150.      * Set up vinfo structure
  151.      */
  152.     vinfo = (video_info_t *)malloc(sizeof(video_info_t));
  153.     if (vinfo == NULL) 
  154.       return (-1);
  155.     vinfo->height = quicktime_video_height(m_qtfile, ix);
  156.     vinfo->width = quicktime_video_width(m_qtfile, ix);
  157.     player_debug_message("qtime file h %d w %d frame rate %g", 
  158.  vinfo->height,
  159.  vinfo->width,
  160.  quicktime_video_frame_rate(m_qtfile, ix));
  161.     /*
  162.      * See if there is userdata
  163.      */
  164.     unsigned char *foo;
  165.     int bufsize;
  166. #undef SORENSON
  167. #ifdef SORENSON
  168.     bufsize = 0;
  169.     ret = quicktime_video_sequence_header(m_qtfile, ix, NULL, &length);
  170.     if (ret < 0) {
  171.       bufsize = -ret;
  172.       uint8_t *foo = (uint8_t *)malloc(bufsize);
  173.       int ret2 = quicktime_video_sequence_header(m_qtfile, ix, foo, &bufsize);
  174.       if (ret2 != 1) {
  175. player_debug_message("Weird error here %d %d", ret, ret2);
  176. return (-1);
  177.       }
  178.     }
  179. #else
  180.     ret = quicktime_get_mp4_video_decoder_config(m_qtfile, ix, &foo, &bufsize);
  181. #endif
  182.     /*
  183.      * Create plugin
  184.      */
  185.     ret = mptr->create_video_plugin(plugin, 
  186.     NULL,
  187.     vinfo,
  188.     (uint8_t *)foo,
  189.     bufsize);
  190.     /*
  191.      * Create bytestream
  192.      */
  193.     CQTVideoByteStream *vbyte;
  194.     vbyte = new CQTVideoByteStream(this, ix);
  195.     if (vbyte == NULL) {
  196.       return (-1);
  197.     }
  198.     player_debug_message("qt file length %ld", quicktime_video_length(m_qtfile, ix));
  199.     player_debug_message("qt video time scale %d", quicktime_video_time_scale(m_qtfile, ix));
  200.     vbyte->config(quicktime_video_length(m_qtfile, ix),
  201.   quicktime_video_frame_rate(m_qtfile, ix),
  202.   quicktime_video_time_scale(m_qtfile, ix));
  203.     player_debug_message("Video Max time is %g", vbyte->get_max_playtime());
  204.     ret = mptr->create_from_file(vbyte, TRUE);
  205.     if (ret != 0) {
  206.       return (-1);
  207.     }
  208.     vid_cnt++;
  209.   }
  210.   return (vid_cnt);
  211. }
  212. int CQtimeFile::create_audio (CPlayerSession *psptr)
  213. {
  214.   CPlayerMedia *mptr;
  215.   uint8_t *ud;
  216.   int udsize, ret;
  217.   long sample_rate;
  218.   int samples_per_frame;
  219.   codec_plugin_t *plugin = NULL;
  220.   m_audio_tracks = quicktime_audio_tracks(m_qtfile);
  221.   if (m_audio_tracks > 0) {
  222.     player_debug_message("qtime audio tracks %d", m_audio_tracks);
  223.     const char *codec = quicktime_audio_compressor(m_qtfile, 0);
  224.     if (codec == NULL)
  225.       return (0);
  226.     ud = NULL;
  227.     udsize = 0;
  228.     ret = quicktime_get_mp4_audio_decoder_config(m_qtfile, 0, (unsigned char **)&ud, &udsize);
  229.     plugin = check_for_audio_codec(codec, NULL, -1, -1, ud, udsize);
  230.     if (plugin == NULL) {
  231.       player_debug_message("Couldn't find audio codec %s", codec);
  232.       return (0);
  233.     }
  234.     if (ret >= 0 && ud != NULL) {
  235.       mpeg4_audio_config_t audio_config;
  236.       decode_mpeg4_audio_config(ud, udsize, &audio_config);
  237.       sample_rate = audio_config.frequency;
  238.       if (audio_object_type_is_aac(&audio_config) != 0) {
  239. samples_per_frame = audio_config.codec.aac.frame_len_1024 == 0 ? 
  240.   960 : 1024;
  241.       } else {
  242. player_debug_message("Unknown audio codec type %d", audio_config.audio_object_type);
  243. return (0);
  244.       }
  245.       player_debug_message("From audio rate %ld samples %d", sample_rate, samples_per_frame);
  246.     } else {
  247.       sample_rate = quicktime_audio_sample_rate(m_qtfile, 0);
  248.       samples_per_frame = quicktime_audio_sample_duration(m_qtfile, 0);
  249.       player_debug_message("audio - rate %ld samples %d", 
  250.    sample_rate, samples_per_frame);
  251.     }
  252.     CQTAudioByteStream *abyte;
  253.     mptr = new CPlayerMedia(psptr);
  254.     if (mptr == NULL) {
  255.       return (-1);
  256.     }
  257.     audio_info_t *audio = (audio_info_t *)malloc(sizeof(audio_info_t));
  258.     memset(audio, 0, sizeof(*audio));
  259.     audio->freq = sample_rate;
  260.     int ret = mptr->create_audio_plugin(plugin,
  261. NULL, // SDP info
  262. audio,
  263. ud,
  264. udsize);
  265.     if (ret < 0) {
  266.       delete mptr;
  267.       return 0;
  268.     }
  269.     abyte = new CQTAudioByteStream(this, 0);
  270.     long len = quicktime_audio_length(m_qtfile, 0);
  271.     abyte->config(len, sample_rate, samples_per_frame);
  272.     player_debug_message("audio Max time is %g len %ld", 
  273.  abyte->get_max_playtime(), len);
  274.     ret = mptr->create_from_file(abyte, FALSE);
  275.     if (ret != 0) {
  276.       return (-1);
  277.     }
  278.     return (1);
  279.   }
  280.   return (0);
  281. }
  282. /* end file qtime_file.cpp */