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

📄 player_media_decode.cpp

📁 网络MPEG4IP流媒体开发源代码
💻 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 *//* * player_media_decode.cpp * decode task thread for a CPlayerMedia */#include "systems.h"#include "player_session.h"#include "player_media.h"#include "player_sdp.h"#include "player_util.h"#include "media_utils.h"#include "audio.h"#include "video.h"#include "rtp_bytestream.h"#include "codec_plugin_private.h"//#define DEBUG_DECODE 1//#define DEBUG_DECODE_MSGS 1/* * start_decoding - API function to call for telling the decoding * task it can start */void CPlayerMedia::start_decoding (void){  m_decode_msg_queue.send_message(MSG_START_DECODING, 				  NULL, 				  0, 				  m_decode_thread_sem);}void CPlayerMedia::bytestream_primed (void){  if (m_decode_thread_waiting != 0) {    m_decode_thread_waiting = 0;    SDL_SemPost(m_decode_thread_sem);  }}void CPlayerMedia::wait_on_bytestream (void){  m_decode_thread_waiting = 1;#ifdef DEBUG_DECODE  if (m_media_info)    media_message(LOG_INFO, "decode thread %s waiting", m_media_info->media);  else    media_message(LOG_INFO, "decode thread waiting");#endif  SDL_SemWait(m_decode_thread_sem);  m_decode_thread_waiting = 0;} /* * parse_decode_message - handle messages to the decode task */void CPlayerMedia::parse_decode_message (int &thread_stop, int &decoding){  CMsg *newmsg;  if ((newmsg = m_decode_msg_queue.get_message()) != NULL) {#ifdef DEBUG_DECODE_MSGS    media_message(LOG_DEBUG, "decode thread message %d",newmsg->get_value());#endif    switch (newmsg->get_value()) {    case MSG_STOP_THREAD:      thread_stop = 1;      break;    case MSG_PAUSE_SESSION:      decoding = 0;      if (m_video_sync != NULL) {	m_video_sync->flush_decode_buffers();      }      if (m_audio_sync != NULL) {	m_audio_sync->flush_decode_buffers();      }      break;    case MSG_START_DECODING:      if (m_video_sync != NULL) {	m_video_sync->flush_decode_buffers();      }      if (m_audio_sync != NULL) {	m_audio_sync->flush_decode_buffers();      }      decoding = 1;      break;    }    delete newmsg;  }}/* * Main decode thread. */int CPlayerMedia::decode_thread (void) {  //  uint32_t msec_per_frame = 0;  int ret = 0;  int thread_stop = 0, decoding = 0;  uint32_t decode_skipped_frames = 0;  uint64_t ourtime;      // Tell bytestream we're starting the next frame - they'll give us      // the time.  uint8_t *frame_buffer;  uint32_t frame_len;  void *ud = NULL;    uint32_t frames_decoded;  uint64_t bytes_decoded;  uint32_t frames_decoded_last_sec;  uint64_t bytes_decoded_last_sec;  uint64_t current_second;  uint32_t total_secs;  uint32_t last_div = 0;  total_secs = 0;  frames_decoded = 0;  bytes_decoded = 0;  frames_decoded_last_sec = 0;  bytes_decoded_last_sec = 0;  current_second = 0;  while (thread_stop == 0) {    // waiting here for decoding or thread stop    ret = SDL_SemWait(m_decode_thread_sem);#ifdef DEBUG_DECODE    media_message(LOG_DEBUG, "%s Decode thread awake",		  is_video() ? "video" : "audio");#endif    parse_decode_message(thread_stop, decoding);    if (decoding == 1) {      // We've been told to start decoding - if we don't have a codec,       // create one      if (is_video()) {	if (m_video_sync == NULL) {	  m_video_sync = m_parent->set_up_video_sync();	}	m_video_sync->set_wait_sem(m_decode_thread_sem);      } else {	if (m_audio_sync == NULL) {	  m_audio_sync = m_parent->set_up_audio_sync();	}	m_audio_sync->set_wait_sem(m_decode_thread_sem);      }      if (m_plugin == NULL) {	if (is_video()) {	  m_plugin = check_for_video_codec(NULL,					   m_media_fmt,					   -1,					   -1,					   m_user_data,					   m_user_data_size);	  if (m_plugin != NULL) {	    m_plugin_data = (m_plugin->vc_create)(NULL, // must figure from sdp						  -1,						  -1,						  m_media_fmt,						  m_video_info,						  m_user_data,						  m_user_data_size,						  get_video_vft(),						  m_video_sync);	    if (m_plugin_data == NULL) {	      m_plugin = NULL;	    } else {	      media_message(LOG_DEBUG, "Starting %s codec from decode thread",			    m_plugin->c_name);	    }	  }	} else {	  m_plugin = check_for_audio_codec(NULL,					   m_media_fmt,					   -1, 					   -1, 					   m_user_data,					   m_user_data_size);	  if (m_plugin != NULL) {	    m_plugin_data = (m_plugin->ac_create)(NULL, 						  -1,						  -1,						  m_media_fmt,						  m_audio_info,						  m_user_data,						  m_user_data_size,						  get_audio_vft(),						  m_audio_sync);	    if (m_plugin_data == NULL) {	      m_plugin = NULL;	    } else {	      media_message(LOG_DEBUG, "Starting %s codec from decode thread",			    m_plugin->c_name);	    }	  }	}      }      if (m_plugin != NULL) {	m_plugin->c_do_pause(m_plugin_data);      } else {	while (thread_stop == 0 && decoding) {	  SDL_Delay(100);	  if (m_rtp_byte_stream) {	    m_rtp_byte_stream->flush_rtp_packets();	  }	  parse_decode_message(thread_stop, decoding);	}      }    }    /*     * this is our main decode loop     */#ifdef DEBUG_DECODE    media_message(LOG_DEBUG, "%s Into decode loop",		  is_video() ? "video" : "audio");#endif    frames_decoded_last_sec = 0;    bytes_decoded_last_sec = 0;    current_second = 0;    while ((thread_stop == 0) && decoding) {      parse_decode_message(thread_stop, decoding);      if (thread_stop != 0)	continue;      if (decoding == 0) {	m_plugin->c_do_pause(m_plugin_data);	continue;      }      if (m_byte_stream->eof()) {	media_message(LOG_INFO, "%s hit eof", m_is_video ? "video" : "audio");	if (m_audio_sync) m_audio_sync->set_eof();	if (m_video_sync) m_video_sync->set_eof();	decoding = 0;	continue;      }      if (m_byte_stream->have_no_data()) {	// Indicate that we're waiting, and wait for a message from RTP	// task.	wait_on_bytestream();	continue;      }      frame_buffer = NULL;      ourtime = m_byte_stream->start_next_frame(&frame_buffer, 						&frame_len,						&ud);      /*       * If we're decoding video, see if we're playing - if so, check       * if we've fallen significantly behind the audio       */      if (is_video() &&	  (m_parent->get_session_state() == SESSION_PLAYING)) {	uint64_t current_time = m_parent->get_playing_time();	if (current_time >= ourtime) {#if 1	  media_message(LOG_INFO, "Candidate for skip decode %llu our %llu", 			       current_time, ourtime);#endif	  // If the bytestream can skip ahead, let's do so	  if (m_byte_stream->can_skip_frame() != 0) {	    int ret;	    int hassync;	    int count;	    current_time += 200; 	    count = 0;	    // Skip up to the current time + 200 msec	    ud = NULL;	    do {	      if (ud != NULL) free(ud);	      ret = m_byte_stream->skip_next_frame(&ourtime, &hassync,						   &frame_buffer, &frame_len,						   &ud);	      decode_skipped_frames++;	    } while (ret != 0 &&		     !m_byte_stream->eof() && 		     current_time > ourtime);	    if (m_byte_stream->eof() || ret == 0) continue;#if 1	    media_message(LOG_INFO, "Skipped ahead %llu  to %llu", 			  current_time - 200, ourtime);#endif	    /*	     * Ooh - fun - try to match to the next sync value - if not, 	     * 15 frames	     */	    do {	      if (ud != NULL) free(ud);	      ret = m_byte_stream->skip_next_frame(&ourtime, &hassync,						   &frame_buffer, &frame_len,						   &ud);	      if (hassync < 0) {		uint64_t diff = ourtime - current_time;		if (diff > (2 * C_LLU)) {		  hassync = 1;		}	      }	      decode_skipped_frames++;	      count++;	    } while (ret != 0 &&		     hassync <= 0 &&		     count < 30 &&		     !m_byte_stream->eof());	    if (m_byte_stream->eof() || ret == 0) continue;#ifdef DEBUG_DECODE	    media_message(LOG_INFO, "Matched ahead - count %d, sync %d time %llu",				 count, hassync, ourtime);#endif	  }	}      }#ifdef DEBUG_DECODE      media_message(LOG_DEBUG, "Decoding %c frame " LLU, 		    m_is_video ? 'v' : 'a', ourtime);#endif      if (frame_buffer != NULL && frame_len != 0) {	int sync_frame;	ret = m_plugin->c_decode_frame(m_plugin_data,				       ourtime,				       m_streaming != 0,				       &sync_frame,				       frame_buffer, 				       frame_len,				       ud);#ifdef DEBUG_DECODE	media_message(LOG_DEBUG, "Decoding %c frame return %d", 		      m_is_video ? 'v' : 'a', ret);#endif	if (ret > 0) {	  frames_decoded++;	  m_byte_stream->used_bytes_for_frame(ret);	  bytes_decoded += ret;	  last_div = ourtime % 1000;	  if ((ourtime / 1000) > current_second) {	    if (frames_decoded_last_sec != 0) {#if 0	      media_message(LOG_DEBUG, "%s - Second "LLU", frames %d bytes "LLU,			    m_is_video ? "video" : "audio", 			    current_second,			    frames_decoded_last_sec,			    bytes_decoded_last_sec);#endif	    }	    current_second = ourtime / 1000;	    total_secs++;	    frames_decoded_last_sec = 1;	    bytes_decoded_last_sec = ret;	  } else {	    frames_decoded_last_sec++;	    bytes_decoded_last_sec += ret;	  }	} else {	  m_byte_stream->used_bytes_for_frame(frame_len);	}      }    }    // calculate frame rate for session  }  if (m_is_video)    media_message(LOG_NOTICE, "Video decoder skipped %u frames", 		  decode_skipped_frames);  if (total_secs != 0) {    double fps, bps;    double secs;    secs = last_div;    secs /= 1000.0;    secs += total_secs;    fps = frames_decoded;    fps /= secs;    bps = UINT64_TO_DOUBLE(bytes_decoded);    bps *= 8.0 / secs;    media_message(LOG_NOTICE, "%s - bytes "LLU", seconds %g, fps %g bps "LLU,		  m_is_video ? "video" : "audio", 		  bytes_decoded, secs, 		  fps, bytes_decoded * 8 / total_secs);  }  if (m_plugin) {    m_plugin->c_close(m_plugin_data);    m_plugin_data = NULL;  }  return (0);}/* end file player_media_decode.cpp */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -