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

流媒体/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. #include "systems.h"
  25. #include "mp4_bytestream.h"
  26. #include "player_util.h"
  27. //#define DEBUG_MP4_FRAME 1
  28. /**************************************************************************
  29.  * Quicktime stream base class functions
  30.  **************************************************************************/
  31. CMp4ByteStream::CMp4ByteStream (CMp4File *parent,
  32. MP4TrackId track,
  33. const char *type,
  34. int has_video)
  35.   : COurInByteStream(type)
  36. {
  37. #ifdef OUTPUT_TO_FILE
  38.   char buffer[80];
  39.   strcpy(buffer, type);
  40.   strcat(buffer, ".raw");
  41.   m_output_file = fopen(buffer, "w");
  42. #endif
  43.   m_track = track;
  44.   m_frame_on = 1;
  45.   m_parent = parent;
  46.   m_eof = 0;
  47.   MP4FileHandle fh = parent->get_file();
  48.   m_frames_max = MP4GetTrackNumberOfSamples(fh, m_track);
  49.   m_max_frame_size = MP4GetTrackMaxSampleSize(fh, m_track) + 4;
  50.   m_buffer = (u_int8_t *) malloc(m_max_frame_size * sizeof(u_int8_t));
  51.   m_has_video = has_video;
  52.   m_frame_in_buffer = 0xffffffff;
  53.   MP4Duration trackDuration;
  54.   trackDuration = MP4GetTrackDuration(fh, m_track);
  55.   uint64_t max_ts;
  56.   max_ts = MP4ConvertFromTrackDuration(fh, 
  57.        m_track, 
  58.        trackDuration,
  59.        MP4_MSECS_TIME_SCALE);
  60. #ifdef _WINDOWS
  61.   m_max_time = (int64_t)(max_ts);
  62. #else
  63.   m_max_time = max_ts;
  64. #endif
  65.   m_max_time /= 1000.0;
  66.   mp4f_message(LOG_DEBUG, 
  67.        "MP4 %s max time is "LLU" %g", type, max_ts, m_max_time);
  68.   read_frame(1);
  69. }
  70. CMp4ByteStream::~CMp4ByteStream()
  71. {
  72.   if (m_buffer != NULL) {
  73.     free(m_buffer);
  74.     m_buffer = NULL;
  75.   }
  76. #ifdef OUTPUT_TO_FILE
  77.   fclose(m_output_file);
  78. #endif
  79. }
  80. int CMp4ByteStream::eof(void)
  81. {
  82.   return m_eof != 0;
  83. }
  84. void CMp4ByteStream::check_for_end_of_frame (void)
  85. {
  86.   if (m_byte_on >= m_this_frame_size) {
  87.     uint32_t next_frame;
  88.     next_frame = m_frame_in_buffer + 1;
  89. #if 0
  90.     mp4f_message(LOG_DEBUG, "%s - next frame %d", 
  91.  m_name, 
  92.  next_frame); 
  93. #endif
  94.     if (next_frame >= m_frames_max + 1) {
  95. m_eof = 1;
  96.     } else {
  97.       read_frame(next_frame);
  98.     }
  99.   }
  100. }
  101. void CMp4ByteStream::set_timebase (MP4SampleId frame)
  102. {
  103.   m_eof = 0;
  104.   if (frame == 0) frame = 1;
  105.   m_frame_on = frame;
  106.   read_frame(m_frame_on);
  107. }
  108. void CMp4ByteStream::reset (void) 
  109. {
  110.   set_timebase(1);
  111. }
  112. uint64_t CMp4ByteStream::start_next_frame (uint8_t **buffer, 
  113.    uint32_t *buflen,
  114.    void **ud)
  115. {
  116.   if (m_frame_on >= m_frames_max) {
  117.     m_eof = 1;
  118.   }
  119.   read_frame(m_frame_on);
  120. #if 0
  121.   mp4f_message(LOG_DEBUG, "%s - Reading frame %d ts %llu - len %u %02x %02x %02x %02x", 
  122.        m_name, m_frame_on, m_frame_on_ts, m_this_frame_size,
  123.        m_buffer[m_byte_on],
  124.        m_buffer[m_byte_on + 1],
  125.        m_buffer[m_byte_on + 2],
  126.        m_buffer[m_byte_on + 3]);
  127. #endif
  128.   m_frame_on++;
  129.   if (buffer != NULL) {
  130.     *buffer = m_buffer + m_byte_on;
  131.     *buflen = m_this_frame_size;
  132.   }
  133.   return (m_frame_on_ts);
  134. }
  135. void CMp4ByteStream::used_bytes_for_frame (uint32_t bytes_used)
  136. {
  137.   m_byte_on += bytes_used;
  138.   m_total += bytes_used;
  139.   check_for_end_of_frame();
  140. }
  141. int CMp4ByteStream::skip_next_frame (uint64_t *pts, 
  142.      int *pSync,
  143.      uint8_t **buffer, 
  144.      uint32_t *buflen)
  145. {
  146.   uint64_t ts;
  147.   ts = start_next_frame(buffer, buflen, NULL);
  148.   *pts = ts;
  149.   *pSync = m_frame_on_has_sync;
  150.   return (1);
  151. }
  152. /*
  153.  * read_frame for video - this will try to read the next frame - it
  154.  * tries to be smart about reading it 1 time if we've already read it
  155.  * while bookmarking
  156.  */
  157. void CMp4ByteStream::read_frame (uint32_t frame_to_read)
  158. {
  159. #ifdef DEBUG_MP4_FRAME 
  160.   mp4f_message(LOG_DEBUG, "%s - Reading frame %d", m_name, frame_to_read);
  161. #endif
  162.   if (m_frame_in_buffer == frame_to_read) {
  163. #ifdef DEBUG_MP4_FRAME
  164.     mp4f_message(LOG_DEBUG, 
  165.  "%s - frame in buffer %u %u", m_name, 
  166.  m_byte_on, m_this_frame_size);
  167. #endif
  168.     m_byte_on = 0;
  169.     m_frame_on_ts = m_frame_in_buffer_ts;
  170.     m_frame_on_has_sync = m_frame_in_buffer_has_sync;
  171.     return;
  172.   }
  173.   // Haven't already read the next frame,  so - get the size, see if
  174.   // it fits, then read it into the appropriate buffer
  175.   m_parent->lock_file_mutex();
  176.   m_frame_in_buffer = frame_to_read;
  177.   MP4Timestamp sampleTime;
  178.   MP4Duration sampleDuration, sampleRenderingOffset;
  179.   bool isSyncSample = FALSE;
  180.   bool ret;
  181.   u_int8_t *temp;
  182.   m_this_frame_size = m_max_frame_size;
  183.   temp = m_buffer;
  184.   ret = MP4ReadSample(m_parent->get_file(),
  185.       m_track,
  186.       frame_to_read,
  187.       &temp,
  188.       &m_this_frame_size,
  189.       &sampleTime,
  190.       &sampleDuration,
  191.       &sampleRenderingOffset,
  192.       &isSyncSample);
  193.   if (ret == FALSE) {
  194.     mp4f_message(LOG_ALERT, "Couldn't read frame from mp4 file - frame %d", 
  195.  frame_to_read);
  196.     m_eof = 1;
  197.     m_parent->unlock_file_mutex();
  198.     return;
  199.   }
  200.   memset(m_buffer + m_this_frame_size, 0, sizeof(uint32_t));
  201.   //*(uint32_t *)(m_buffer + m_this_frame_size) = 0; // add some 0's
  202. #ifdef OUTPUT_TO_FILE
  203.   fwrite(m_buffer, m_this_frame_size, 1, m_output_file);
  204. #endif
  205. #if 0
  206.   //    mp4f_message(LOG_DEBUG, "reading into buffer %u %u", 
  207.   //  frame_to_read, m_this_frame_size);
  208.     //mp4f_message(LOG_DEBUG, "%s Sample time "LLU, m_name, sampleTime);
  209.     //    mp4f_message(LOG_DEBUG, "%s values %x %x %x %x", m_name, m_buffer[0], 
  210.     //  m_buffer[1], m_buffer[2], m_buffer[3]);
  211. #endif
  212.   uint64_t ts;
  213.   ts = MP4ConvertFromTrackTimestamp(m_parent->get_file(),
  214.     m_track,
  215.     sampleTime,
  216.     MP4_MSECS_TIME_SCALE);
  217.   //if (isSyncSample == TRUE && m_has_video != 0 ) player_debug_message("%s has sync sample %llu", m_name, ts);
  218. #if 0
  219.   mp4f_message(LOG_DEBUG, "%s frame %u sample time "LLU " converts to time "LLU, 
  220.        m_name, frame_to_read, sampleTime, ts);
  221. #endif
  222.   m_frame_in_buffer_ts = ts;
  223.   m_frame_on_ts = ts;
  224.   m_frame_in_buffer_has_sync = m_frame_on_has_sync = isSyncSample;
  225.   m_parent->unlock_file_mutex();
  226.   m_byte_on = 0;
  227. }
  228. void CMp4ByteStream::set_start_time (uint64_t start)
  229. {
  230.   m_play_start_time = start;
  231.   MP4Timestamp mp4_ts;
  232.   MP4SampleId mp4_sampleId;
  233.   m_parent->lock_file_mutex();
  234.   mp4_ts = MP4ConvertToTrackTimestamp(m_parent->get_file(),
  235.       m_track,
  236.       start,
  237.       MP4_MSECS_TIME_SCALE);
  238.   mp4_sampleId = MP4GetSampleIdFromTime(m_parent->get_file(),
  239. m_track,
  240. mp4_ts, 
  241. TRUE);
  242.   uint64_t ts;
  243.   MP4Timestamp sampleTime;
  244.   sampleTime = MP4GetSampleTime(m_parent->get_file(),
  245. m_track,
  246. mp4_sampleId);
  247.   ts = MP4ConvertFromTrackTimestamp(m_parent->get_file(),
  248.     m_track,
  249.     sampleTime,
  250.     MP4_MSECS_TIME_SCALE);
  251.   m_parent->unlock_file_mutex();
  252. #ifdef DEBUG_MP4_FRAME
  253.   mp4f_message(LOG_DEBUG, "%s searching timestamp "LLU" gives "LLU,
  254.        m_name, start, mp4_ts);
  255.   mp4f_message(LOG_DEBUG, "%s values are sample time "LLU" ts "LLU,
  256.        m_name, sampleTime, ts);
  257. #endif
  258.   set_timebase(mp4_sampleId);
  259. }
  260. double CMp4ByteStream::get_max_playtime (void) 
  261. {
  262.   return (m_max_time);
  263. };
  264. /* end file qtime_bytestream.cpp */