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

流媒体/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.  * player_media_decode.cpp
  23.  * decode task thread for a CPlayerMedia
  24.  */
  25. #include "systems.h"
  26. #include "player_session.h"
  27. #include "player_media.h"
  28. #include "player_sdp.h"
  29. #include "player_util.h"
  30. #include "media_utils.h"
  31. #include "audio.h"
  32. #include "video.h"
  33. #include "rtp_bytestream.h"
  34. #include "codec_plugin_private.h"
  35. //#define DEBUG_DECODE 1
  36. //#define DEBUG_DECODE_MSGS 1
  37. /*
  38.  * start_decoding - API function to call for telling the decoding
  39.  * task it can start
  40.  */
  41. void CPlayerMedia::start_decoding (void)
  42. {
  43.   m_decode_msg_queue.send_message(MSG_START_DECODING, 
  44.   NULL, 
  45.   0, 
  46.   m_decode_thread_sem);
  47. }
  48. void CPlayerMedia::bytestream_primed (void)
  49. {
  50.   if (m_decode_thread_waiting != 0) {
  51.     m_decode_thread_waiting = 0;
  52.     SDL_SemPost(m_decode_thread_sem);
  53.   }
  54. }
  55. void CPlayerMedia::wait_on_bytestream (void)
  56. {
  57.   m_decode_thread_waiting = 1;
  58. #ifdef DEBUG_DECODE
  59.   media_message(LOG_INFO, "decode thread %s waiting", m_media_info->media);
  60. #endif
  61.   SDL_SemWait(m_decode_thread_sem);
  62.   m_decode_thread_waiting = 0;
  63. /*
  64.  * parse_decode_message - handle messages to the decode task
  65.  */
  66. void CPlayerMedia::parse_decode_message (int &thread_stop, int &decoding)
  67. {
  68.   CMsg *newmsg;
  69.   if ((newmsg = m_decode_msg_queue.get_message()) != NULL) {
  70. #ifdef DEBUG_DECODE_MSGS
  71.     media_message(LOG_DEBUG, "decode thread message %d",newmsg->get_value());
  72. #endif
  73.     switch (newmsg->get_value()) {
  74.     case MSG_STOP_THREAD:
  75.       thread_stop = 1;
  76.       break;
  77.     case MSG_PAUSE_SESSION:
  78.       decoding = 0;
  79.       if (m_video_sync != NULL) {
  80. m_video_sync->flush_decode_buffers();
  81.       }
  82.       if (m_audio_sync != NULL) {
  83. m_audio_sync->flush_decode_buffers();
  84.       }
  85.       break;
  86.     case MSG_START_DECODING:
  87.       if (m_video_sync != NULL) {
  88. m_video_sync->flush_decode_buffers();
  89.       }
  90.       if (m_audio_sync != NULL) {
  91. m_audio_sync->flush_decode_buffers();
  92.       }
  93.       decoding = 1;
  94.       break;
  95.     }
  96.     delete newmsg;
  97.   }
  98. }
  99. /*
  100.  * Main decode thread.
  101.  */
  102. int CPlayerMedia::decode_thread (void) 
  103. {
  104.   //  uint32_t msec_per_frame = 0;
  105.   int ret = 0;
  106.   int thread_stop = 0, decoding = 0;
  107.   uint32_t decode_skipped_frames = 0;
  108.   uint64_t ourtime;
  109.       // Tell bytestream we're starting the next frame - they'll give us
  110.       // the time.
  111.   uint8_t *frame_buffer;
  112.   uint32_t frame_len;
  113.   void *ud = NULL;
  114.   
  115.   uint32_t frames_decoded;
  116.   uint64_t bytes_decoded;
  117.   uint32_t frames_decoded_last_sec;
  118.   uint64_t bytes_decoded_last_sec;
  119.   uint64_t current_second;
  120.   uint32_t total_secs;
  121.   uint32_t last_div = 0;
  122.   total_secs = 0;
  123.   frames_decoded = 0;
  124.   bytes_decoded = 0;
  125.   frames_decoded_last_sec = 0;
  126.   bytes_decoded_last_sec = 0;
  127.   current_second = 0;
  128.   while (thread_stop == 0) {
  129.     // waiting here for decoding or thread stop
  130.     ret = SDL_SemWait(m_decode_thread_sem);
  131. #ifdef DEBUG_DECODE
  132.     media_message(LOG_DEBUG, "%s Decode thread awake",
  133.   is_video() ? "video" : "audio");
  134. #endif
  135.     parse_decode_message(thread_stop, decoding);
  136.     if (decoding == 1) {
  137.       // We've been told to start decoding - if we don't have a codec, 
  138.       // create one
  139.       if (is_video()) {
  140. if (m_video_sync == NULL) {
  141.   m_video_sync = m_parent->set_up_video_sync();
  142. }
  143. m_video_sync->set_wait_sem(m_decode_thread_sem);
  144.       } else {
  145. if (m_audio_sync == NULL) {
  146.   m_audio_sync = m_parent->set_up_audio_sync();
  147. }
  148. m_audio_sync->set_wait_sem(m_decode_thread_sem);
  149.       }
  150.       if (m_plugin == NULL) {
  151. if (is_video()) {
  152.   m_plugin = check_for_video_codec(NULL,
  153.    m_media_fmt,
  154.    -1,
  155.    -1,
  156.    m_user_data,
  157.    m_user_data_size);
  158.   if (m_plugin != NULL) {
  159.     m_plugin_data = (m_plugin->vc_create)(m_media_fmt,
  160.   m_video_info,
  161.   m_user_data,
  162.   m_user_data_size,
  163.   get_video_vft(),
  164.   m_video_sync);
  165.     if (m_plugin_data == NULL) {
  166.       m_plugin = NULL;
  167.     } else {
  168.       media_message(LOG_DEBUG, "Starting %s codec from decode thread",
  169.     m_plugin->c_name);
  170.     }
  171.   }
  172. } else {
  173.   m_plugin = check_for_audio_codec(NULL,
  174.    m_media_fmt,
  175.    -1, 
  176.    -1, 
  177.    m_user_data,
  178.    m_user_data_size);
  179.   if (m_plugin != NULL) {
  180.     m_plugin_data = (m_plugin->ac_create)(m_media_fmt,
  181.   m_audio_info,
  182.   m_user_data,
  183.   m_user_data_size,
  184.   get_audio_vft(),
  185.   m_audio_sync);
  186.     if (m_plugin_data == NULL) {
  187.       m_plugin = NULL;
  188.     } else {
  189.       media_message(LOG_DEBUG, "Starting %s codec from decode thread",
  190.     m_plugin->c_name);
  191.     }
  192.   }
  193. }
  194.       }
  195.       if (m_plugin != NULL) {
  196. m_plugin->c_do_pause(m_plugin_data);
  197.       } else {
  198. while (thread_stop == 0 && decoding) {
  199.   SDL_Delay(100);
  200.   if (m_rtp_byte_stream) {
  201.     m_rtp_byte_stream->flush_rtp_packets();
  202.   }
  203.   parse_decode_message(thread_stop, decoding);
  204. }
  205.       }
  206.     }
  207.     /*
  208.      * this is our main decode loop
  209.      */
  210. #ifdef DEBUG_DECODE
  211.     media_message(LOG_DEBUG, "%s Into decode loop",
  212.   is_video() ? "video" : "audio");
  213. #endif
  214.     frames_decoded_last_sec = 0;
  215.     bytes_decoded_last_sec = 0;
  216.     current_second = 0;
  217.     while ((thread_stop == 0) && decoding) {
  218.       parse_decode_message(thread_stop, decoding);
  219.       if (thread_stop != 0)
  220. continue;
  221.       if (decoding == 0) {
  222. m_plugin->c_do_pause(m_plugin_data);
  223. continue;
  224.       }
  225.       if (m_byte_stream->eof()) {
  226. media_message(LOG_INFO, "%s hit eof", m_is_video ? "video" : "audio");
  227. if (m_audio_sync) m_audio_sync->set_eof();
  228. if (m_video_sync) m_video_sync->set_eof();
  229. decoding = 0;
  230. continue;
  231.       }
  232.       if (m_byte_stream->have_no_data()) {
  233. // Indicate that we're waiting, and wait for a message from RTP
  234. // task.
  235. wait_on_bytestream();
  236. continue;
  237.       }
  238.       frame_buffer = NULL;
  239.       ourtime = m_byte_stream->start_next_frame(&frame_buffer, 
  240. &frame_len,
  241. &ud);
  242.       /*
  243.        * If we're decoding video, see if we're playing - if so, check
  244.        * if we've fallen significantly behind the audio
  245.        */
  246.       if (is_video() &&
  247.   (m_parent->get_session_state() == SESSION_PLAYING)) {
  248. uint64_t current_time = m_parent->get_playing_time();
  249. if (current_time >= ourtime) {
  250. #ifdef DEBUG_DECODE
  251.   media_message(LOG_INFO, "Candidate for skip decode %llu our %llu", 
  252.        current_time, ourtime);
  253. #endif
  254.   // If the bytestream can skip ahead, let's do so
  255.   if (m_byte_stream->can_skip_frame() != 0) {
  256.     int ret;
  257.     int hassync;
  258.     int count;
  259.     current_time += 200; 
  260.     count = 0;
  261.     // Skip up to the current time + 200 msec
  262.     do {
  263.       ret = m_byte_stream->skip_next_frame(&ourtime, &hassync,
  264.    &frame_buffer, &frame_len);
  265.       decode_skipped_frames++;
  266.     } while (ret != 0 &&
  267.      !m_byte_stream->eof() && 
  268.      current_time > ourtime);
  269.     if (m_byte_stream->eof() || ret == 0) continue;
  270. #if 1
  271.     media_message(LOG_INFO, "Skipped ahead %llu  to %llu", 
  272.   current_time - 200, ourtime);
  273. #endif
  274.     /*
  275.      * Ooh - fun - try to match to the next sync value - if not, 
  276.      * 15 frames
  277.      */
  278.     do {
  279.       ret = m_byte_stream->skip_next_frame(&ourtime, &hassync,
  280.    &frame_buffer, &frame_len);
  281.       if (hassync < 0) {
  282. uint64_t diff = ourtime - current_time;
  283. if (diff > (2 * C_LLU)) {
  284.   hassync = 1;
  285. }
  286.       }
  287.       decode_skipped_frames++;
  288.       count++;
  289.     } while (ret != 0 &&
  290.      hassync <= 0 &&
  291.      count < 30 &&
  292.      !m_byte_stream->eof());
  293.     if (m_byte_stream->eof() || ret == 0) continue;
  294. #ifdef DEBUG_DECODE
  295.     media_message(LOG_INFO, "Matched ahead - count %d, sync %d time %llu",
  296.  count, hassync, ourtime);
  297. #endif
  298.   }
  299. }
  300.       }
  301. #ifdef DEBUG_DECODE
  302.       media_message(LOG_DEBUG, "Decoding %c frame " LLU, 
  303.     m_is_video ? 'v' : 'a', ourtime);
  304. #endif
  305.       if (frame_buffer != NULL && frame_len != 0) {
  306. int sync_frame;
  307. ret = m_plugin->c_decode_frame(m_plugin_data,
  308.        ourtime,
  309.        m_streaming != 0,
  310.        &sync_frame,
  311.        frame_buffer, 
  312.        frame_len,
  313.        ud);
  314. #ifdef DEBUG_DECODE
  315. media_message(LOG_DEBUG, "Decoding %c frame return %d", 
  316.       m_is_video ? 'v' : 'a', ret);
  317. #endif
  318. if (ret > 0) {
  319.   frames_decoded++;
  320.   m_byte_stream->used_bytes_for_frame(ret);
  321.   bytes_decoded += ret;
  322.   last_div = ourtime % 1000;
  323.   if ((ourtime / 1000) > current_second) {
  324.     if (frames_decoded_last_sec != 0) {
  325. #if 0
  326.       media_message(LOG_DEBUG, "%s - Second "LLU", frames %d bytes "LLU,
  327.     m_is_video ? "video" : "audio", 
  328.     current_second,
  329.     frames_decoded_last_sec,
  330.     bytes_decoded_last_sec);
  331. #endif
  332.     }
  333.     current_second = ourtime / 1000;
  334.     total_secs++;
  335.     frames_decoded_last_sec = 1;
  336.     bytes_decoded_last_sec = ret;
  337.   } else {
  338.     frames_decoded_last_sec++;
  339.     bytes_decoded_last_sec += ret;
  340.   }
  341. } else {
  342.   m_byte_stream->used_bytes_for_frame(frame_len);
  343. }
  344.       }
  345.     }
  346.     // calculate frame rate for session
  347.   }
  348.   if (m_is_video)
  349.     media_message(LOG_NOTICE, "Video decoder skipped %u frames", 
  350.   decode_skipped_frames);
  351.   if (total_secs != 0) {
  352.     double fps, bps;
  353.     double secs;
  354.     secs = last_div;
  355.     secs /= 1000.0;
  356.     secs += total_secs;
  357.     fps = frames_decoded;
  358.     fps /= secs;
  359.     bps = 
  360. #ifdef _WIN32
  361. (int64_t)
  362. #endif
  363. bytes_decoded;
  364.     bps *= 8.0 / secs;
  365.     media_message(LOG_NOTICE, "%s - bytes "LLU", seconds %g, fps %g bps "LLU,
  366.   m_is_video ? "video" : "audio", 
  367.   bytes_decoded, secs, 
  368.   fps, bytes_decoded * 8 / total_secs);
  369.   }
  370.   if (m_plugin) {
  371.     m_plugin->c_close(m_plugin_data);
  372.     m_plugin_data = NULL;
  373.   }
  374.   return (0);
  375. }
  376. /* end file player_media_decode.cpp */