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

流媒体/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_bytestream.cpp - convert quicktime file to a bytestream
  23.  */
  24. //#define DEBUG_QTIME_AUDIO_FRAME 1
  25. //#define DEBUG_QTIME_VIDEO_FRAME 1
  26. #include "systems.h"
  27. #include "qtime_bytestream.h"
  28. #include "player_util.h"
  29. /**************************************************************************
  30.  * Quicktime stream base class functions
  31.  **************************************************************************/
  32. CQTByteStreamBase::CQTByteStreamBase (CQtimeFile *parent,
  33.       int track,
  34.       const char *name)
  35.   : COurInByteStream(name)
  36. {
  37.   m_track = track;
  38.   m_frame_on = 0;
  39.   m_parent = parent;
  40.   m_eof = 0;
  41.   m_max_frame_size = 16 * 1024;
  42.   m_buffer = (uint8_t *) malloc(m_max_frame_size * sizeof(char));
  43.   m_frame_in_buffer = 0xffffffff;
  44. }
  45. CQTByteStreamBase::~CQTByteStreamBase()
  46. {
  47.   if (m_buffer != NULL) {
  48.     free(m_buffer);
  49.     m_buffer = NULL;
  50.   }
  51. }
  52. int CQTByteStreamBase::eof(void)
  53. {
  54.   return m_eof != 0;
  55. }
  56. void CQTByteStreamBase::check_for_end_of_frame (void)
  57. {
  58.   if (m_byte_on >= m_this_frame_size) {
  59.     uint32_t next_frame;
  60.     next_frame = m_frame_in_buffer + 1;
  61. #if 0
  62.     player_debug_message("%s - next frame %d", 
  63.  m_name, 
  64.  next_frame);
  65. #endif
  66.     if (next_frame >= m_frames_max) {
  67.       m_eof = 1;
  68.     } else {
  69.       read_frame(next_frame);
  70.     }
  71.   }
  72. }
  73. void CQTByteStreamBase::used_bytes_for_frame (uint32_t bytes_used)
  74. {
  75.   m_byte_on += bytes_used;
  76.   m_total += bytes_used;
  77.   check_for_end_of_frame();
  78. }
  79. /**************************************************************************
  80.  * Quicktime video stream functions
  81.  **************************************************************************/
  82. void CQTVideoByteStream::video_set_timebase (long frame)
  83. {
  84.   m_eof = 0;
  85.   m_frame_on = frame;
  86.   m_parent->lock_file_mutex();
  87.   quicktime_set_video_position(m_parent->get_file(), 
  88.        frame, 
  89.        m_track);
  90.   m_parent->unlock_file_mutex();
  91.   read_frame(m_frame_on);
  92. }
  93. void CQTVideoByteStream::reset (void) 
  94. {
  95.   video_set_timebase(0);
  96. }
  97. uint64_t CQTVideoByteStream::start_next_frame (uint8_t **buffer, 
  98.        uint32_t *buflen,
  99.        void **ud)
  100. {
  101.   uint64_t ret;
  102.   long start;
  103.   int duration;
  104. #if 0
  105.   if (m_frame_on != 0) {
  106.     player_debug_message("frame %d on %u %d", m_frame_on,
  107.  m_byte_on, m_this_frame_size);
  108.     if (m_byte_on != 0 && m_byte_on != m_this_frame_size) {
  109.       for (uint32_t ix = m_byte_on; ix < m_this_frame_size - 4; ix++) {
  110. if ((m_buffer[ix] == 0) &&
  111.     (m_buffer[ix + 1] == 0) &&
  112.     (m_buffer[ix + 2] == 1)) {
  113.   player_debug_message("correct start code %x", m_buffer[ix + 3]);
  114.   player_debug_message("offset %d %d %d", m_byte_on,
  115.        ix, m_this_frame_size);
  116. }
  117.       }
  118.     }
  119.   }
  120. #endif
  121.   if (m_frame_on >= m_frames_max) {
  122.     m_eof = 1;
  123.   }
  124. #ifdef DEBUG_QTIME_VIDEO_FRAME
  125.   player_debug_message("start_next_frame %d", m_frame_on);
  126. #endif
  127.   if (quicktime_video_frame_time(m_parent->get_file(),
  128.  m_track,
  129.  m_frame_on,
  130.  &start,
  131.  &duration) != 0) {
  132.     ret = start;
  133.     ret *= 1000;
  134.     ret /= m_time_scale;
  135.    //player_debug_message("Returning %llu", ret);
  136.  } else {
  137.    ret = m_frame_on;
  138.    ret *= 1000;
  139.    ret /= m_frame_rate;
  140.  }
  141.   read_frame(m_frame_on);
  142.   *buffer = m_buffer;
  143.   *buflen = m_this_frame_size;
  144.   m_frame_on++;
  145.   return (ret);
  146. }
  147. int CQTVideoByteStream::skip_next_frame (uint64_t *ptr, int *hasSync,
  148.  uint8_t **buffer, 
  149.  uint32_t *buflen)
  150. {
  151.   *hasSync = 0;
  152.   *ptr = start_next_frame(buffer, buflen, NULL);
  153.   return 1;
  154. }
  155. /*
  156.  * read_frame for video - this will try to read the next frame 
  157.  */
  158. void CQTVideoByteStream::read_frame (uint32_t frame_to_read)
  159. {
  160.   uint32_t next_frame_size;
  161.   if (m_frame_in_buffer == frame_to_read) {
  162. #ifdef DEBUG_QTIME_VIDEO_FRAME
  163.     player_debug_message("frame in buffer %u %u", m_byte_on, m_this_frame_size);
  164. #endif
  165.     m_byte_on = 0;
  166.     return;
  167.   }
  168.   // Haven't already read the next frame,  so - get the size, see if
  169.   // it fits, then read it into the appropriate buffer
  170.   m_parent->lock_file_mutex();
  171.   next_frame_size = quicktime_frame_size(m_parent->get_file(),
  172.  frame_to_read,
  173.  m_track);
  174.   if (next_frame_size > m_max_frame_size) {
  175.     m_max_frame_size = next_frame_size + 4;
  176.     m_buffer = (uint8_t *)realloc(m_buffer, 
  177. (next_frame_size + 4) * sizeof(char));
  178.   }
  179.   m_this_frame_size = next_frame_size;
  180.   quicktime_set_video_position(m_parent->get_file(), frame_to_read, m_track);
  181.   m_frame_in_buffer = frame_to_read;
  182. #ifdef DEBUG_QTIME_VIDEO_FRAME
  183.   player_debug_message("reading into buffer %u", m_this_frame_size);
  184. #endif
  185.   quicktime_read_frame(m_parent->get_file(),
  186.        (unsigned char *)m_buffer,
  187.        m_track);
  188. #ifdef DEBUG_QTIME_VIDEO_FRAME
  189.   player_debug_message("Buffer %d %02x %02x %02x %02x", 
  190.        frame_to_read,
  191.  m_buffer[0],
  192.  m_buffer[1],
  193.  m_buffer[2],
  194.  m_buffer[3]);
  195. #endif
  196.   m_parent->unlock_file_mutex();
  197.   m_byte_on = 0;
  198. }
  199. void CQTVideoByteStream::set_start_time (uint64_t start)
  200. {
  201.   m_play_start_time = start;
  202.   uint32_t ix;
  203.   long frame_start;
  204.   int duration;
  205.   m_parent->lock_file_mutex();
  206.   for (ix = 0; ix < m_frames_max; ix++) {
  207.     if (quicktime_video_frame_time(m_parent->get_file(),
  208.    m_track, 
  209.    ix, 
  210.    &frame_start, 
  211.    &duration) != 0) {
  212.       uint64_t cmp;
  213.       cmp = frame_start + duration;
  214.       cmp *= 1000;
  215.       cmp /= m_time_scale;
  216.       //player_debug_message("frame %d %llu", ix, cmp);
  217.       if (cmp >= start) {
  218. player_debug_message("Searched through - frame %d is %llu", 
  219.      ix, start);
  220. break;
  221.       }
  222.     } else {
  223.       m_parent->unlock_file_mutex();
  224.       ix = (uint32_t)((start * m_frame_rate) / 1000);
  225.       video_set_timebase(ix);
  226.       return;
  227.     }
  228.   }
  229. #if 0
  230.   player_debug_message("qtime video frame " LLD , start);
  231. #endif
  232.   // we've got the position;
  233.   m_parent->unlock_file_mutex();
  234.   video_set_timebase(ix);
  235. }
  236. void CQTVideoByteStream::config (long num_frames, float frate, int time_scale)
  237. {
  238.   m_frames_max = num_frames;
  239.   m_frame_rate = (uint32_t)frate;
  240.   m_time_scale = time_scale;
  241.   long start;
  242.   int duration;
  243.   // Set up max play time, based on the timing of the last frame.
  244.   if (quicktime_video_frame_time(m_parent->get_file(),
  245.  m_track,
  246.  m_frames_max - 1,
  247.  &start,
  248.  &duration) != 0) {
  249.     player_debug_message("video frame time - %d %ld %d", 
  250.  m_frames_max, start, duration);
  251.     m_max_time = (start + duration);
  252.     m_max_time /= m_time_scale;
  253.   } else {
  254.     m_max_time = m_frames_max;
  255.     m_max_time /= m_frame_rate;
  256.   }
  257.   player_debug_message("Max time is %g", m_max_time);
  258. }
  259. double CQTVideoByteStream::get_max_playtime (void) 
  260. {
  261.   return (m_max_time);
  262. };
  263. /**************************************************************************
  264.  * Quicktime Audio stream functions
  265.  **************************************************************************/
  266. void CQTAudioByteStream::audio_set_timebase (long frame)
  267. {
  268. #ifdef DEBUG_QTIME_AUDIO_FRAME
  269.   player_debug_message("Setting qtime audio timebase to frame %ld", frame);
  270. #endif
  271.   m_eof = 0;
  272.   m_frame_on = frame;
  273.   m_parent->lock_file_mutex();
  274.   quicktime_set_audio_position(m_parent->get_file(), 
  275.        frame, 
  276.        m_track);
  277.   m_parent->unlock_file_mutex();
  278.   read_frame(0);
  279. }
  280. void CQTAudioByteStream::reset (void) 
  281. {
  282.   audio_set_timebase(0);
  283. }
  284. uint64_t CQTAudioByteStream::start_next_frame (uint8_t **buffer, 
  285.        uint32_t *buflen,
  286.        void **ud)
  287. {
  288.   uint64_t ret;
  289.   if (m_frame_on >= m_frames_max) {
  290. #ifdef DEBUG_QTIME_AUDIO_FRAME
  291.     player_debug_message("Setting EOF from start_next_frame %d %d", 
  292.  m_frame_on, m_frames_max);
  293. #endif
  294.     m_eof = 1;
  295.   }
  296.   ret = m_frame_on;
  297.   ret *= m_samples_per_frame;
  298.   ret *= 1000;
  299.   ret /= m_frame_rate;
  300. #ifdef DEBUG_QTIME_AUDIO_FRAME
  301.   player_debug_message("audio - start frame %d %d", m_frame_on, m_frames_max);
  302. #endif
  303. #if 0
  304.   player_debug_message("audio Start next frame "LLU " offset %u %u", 
  305.        ret, m_byte_on, m_this_frame_size);
  306. #endif
  307.   read_frame(m_frame_on);
  308.   *buffer = m_buffer;
  309.   *buflen = m_this_frame_size;
  310.   m_frame_on++;
  311.   return (ret);
  312. }
  313. void CQTAudioByteStream::read_frame (uint32_t frame_to_read)
  314. {
  315. #ifdef DEBUG_QTIME_AUDIO_FRAME
  316.   player_debug_message("audio read_frame %d", frame_to_read);
  317. #endif
  318.   if (m_frame_in_buffer == frame_to_read) {
  319.     m_byte_on = 0;
  320.     return;
  321.   }
  322.   m_parent->lock_file_mutex();
  323.   m_frame_in_buffer = frame_to_read;
  324.   unsigned char *buff = (unsigned char *)m_buffer;
  325.   quicktime_set_audio_position(m_parent->get_file(), 
  326.        frame_to_read, 
  327.        m_track);
  328.   m_this_frame_size = quicktime_read_audio_frame(m_parent->get_file(),
  329.  buff,
  330.  m_max_frame_size,
  331.  m_track);
  332.   if (m_this_frame_size < 0) {
  333.     m_max_frame_size = -m_this_frame_size;
  334.     m_buffer = (uint8_t *)realloc(m_buffer, m_max_frame_size * sizeof(char));
  335.     // Okay - I could have used a goto, but it really grates...
  336.     m_frame_in_buffer = frame_to_read;
  337.     buff = (unsigned char *)m_buffer;
  338.     quicktime_set_audio_position(m_parent->get_file(), 
  339.  frame_to_read, 
  340.  m_track);
  341.     m_this_frame_size = quicktime_read_audio_frame(m_parent->get_file(),
  342.    buff,
  343.    m_max_frame_size,
  344.  m_track);
  345.   }
  346. #if 0
  347.   player_debug_message("qta frame size %u", m_this_frame_size);
  348. #endif
  349.   m_parent->unlock_file_mutex();
  350.   m_byte_on = 0;
  351. }
  352. void CQTAudioByteStream::set_start_time (uint64_t start)
  353. {
  354.   m_play_start_time = start;
  355.   
  356.   start *= m_frame_rate;
  357.   start /= 1000 * m_samples_per_frame;
  358. #if 0
  359.   player_debug_message("qtime audio frame " LLD, start);
  360. #endif
  361.   // we've got the position;
  362.   audio_set_timebase((uint32_t)start);
  363.   m_play_start_time = start;
  364. }
  365. /* end file qtime_bytestream.cpp */