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

📄 player_media_decode.cpp

📁 完整的RTP RTSP代码库
💻 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-2005.  All Rights Reserved. *  * Contributor(s):  *              Bill May        wmay@cisco.com *//* * player_media_decode.cpp * decode task thread for a CPlayerMedia */#include "mpeg4ip.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"#include "our_config_file.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, 				  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_sync != NULL) {	m_sync->flush_decode_buffers();      }      if (m_rtp_byte_stream != NULL) {	m_rtp_byte_stream->flush_rtp_packets();      }      break;    case MSG_START_DECODING:      if (m_sync != NULL) {	m_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;  frame_timestamp_t ourtime, lasttime;      // 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 start_decode_time = 0;  uint64_t last_decode_time = 0;  bool have_start_time = false;  bool have_frame_ts = false;  bool found_out_of_range_ts = false;  uint64_t bytes_decoded;  lasttime.msec_timestamp = 0;  frames_decoded = 0;  bytes_decoded = 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",		  get_name());#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      m_sync->set_wait_sem(m_decode_thread_sem);      if (m_plugin == NULL) {	switch (m_sync_type) {	case VIDEO_SYNC:	  create_video_plugin(NULL, 			      STREAM_TYPE_RTP,			      NULL,			      -1,			      -1,			      m_media_fmt,			      NULL,			      m_user_data,			      m_user_data_size);	  break;	case AUDIO_SYNC:	  create_audio_plugin(NULL,			      STREAM_TYPE_RTP,			      NULL,			      -1, 			      -1, 			      m_media_fmt,			      NULL,			      m_user_data,			      m_user_data_size);	  break;	case TIMED_TEXT_SYNC:	  create_text_plugin(NULL,			     STREAM_TYPE_RTP, 			     NULL, 			     m_media_fmt, 			     m_user_data, 			     m_user_data_size);	  break;	}	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", get_name());#endif    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);	have_frame_ts = false;	continue;      }      if (m_byte_stream->eof()) {	media_message(LOG_INFO, "%s hit eof", get_name());	if (m_sync) m_sync->set_eof();	decoding = 0;	continue;      }      if (m_byte_stream->have_frame() == false) {	// Indicate that we're waiting, and wait for a message from RTP	// task.	wait_on_bytestream();	continue;      }      frame_buffer = NULL;      bool have_frame;      memset(&ourtime, 0, sizeof(ourtime));      have_frame = m_byte_stream->start_next_frame(&frame_buffer, 						   &frame_len,						   &ourtime,						   &ud);      if (have_frame == false) continue;      /*       * If we're decoding video, see if we're playing - if so, check       * if we've fallen significantly behind the audio       */      if (get_sync_type() == VIDEO_SYNC &&	  (m_parent->get_session_state() == SESSION_PLAYING) &&	  have_frame_ts) {	//media_message(LOG_DEBUG, "video decode "U64, ourtime.msec_timestamp);	int64_t ts_diff = ourtime.msec_timestamp - lasttime.msec_timestamp;	if (ts_diff > TO_D64(1000) ||	    ts_diff < TO_D64(-1000)) {	  // out of range timestamp - we'll want to not skip here	  uint64_t current_time = m_parent->get_playing_time();	  ts_diff = ourtime.msec_timestamp - current_time;	  if (ts_diff > TO_D64(0) && ts_diff < TO_D64(5000)) {	    // fall through	  } else {	  found_out_of_range_ts = true;	  media_message(LOG_INFO, "found out of range ts "U64" last "U64" "D64,			ourtime.msec_timestamp, 			lasttime.msec_timestamp,			ts_diff);	  }	} else {	  uint64_t current_time = m_parent->get_playing_time();	  if (found_out_of_range_ts) {	    ts_diff = current_time - ourtime.msec_timestamp;	    if (ts_diff > TO_D64(0) && ts_diff < TO_D64(5000)) {	      found_out_of_range_ts = false;	      media_message(LOG_INFO, 			    "ts back in playing range "U64" "D64,			    ourtime.msec_timestamp, ts_diff);	    }	  } else {	    // regular time	    if (current_time >= ourtime.msec_timestamp) {	      media_message(LOG_INFO, 			    "Candidate for skip decode "U64" our "U64, 			    current_time, ourtime.msec_timestamp);	      // 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);		  frame_buffer = NULL;		  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.msec_timestamp);		if (m_byte_stream->eof() || ret == 0) continue;		media_message(LOG_INFO, "Skipped ahead "U64 " to "U64, 			      current_time - 200, ourtime.msec_timestamp);		/*		 * 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.msec_timestamp - current_time;		    if (diff > TO_U64(200)) {		      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 "U64,			      count, hassync, ourtime.msec_timestamp);#endif	      }	    }	  } // end regular time	}      }      lasttime = ourtime;      have_frame_ts = true;#ifdef DEBUG_DECODE      media_message(LOG_DEBUG, "Decoding %s frame " U64, get_name(),		    ourtime.msec_timestamp);#endif      if (frame_buffer != NULL && frame_len != 0) {	int sync_frame;	ret = m_plugin->c_decode_frame(m_plugin_data,				       &ourtime,				       m_streaming,				       &sync_frame,				       frame_buffer, 				       frame_len,				       ud);#ifdef DEBUG_DECODE	media_message(LOG_DEBUG, "Decoding %s frame return %d", 		      get_name(), ret);#endif	if (ret > 0) {	  frames_decoded++;	  if (have_start_time == false) {	    have_start_time = true;	    start_decode_time = ourtime.msec_timestamp;	  }	  last_decode_time = ourtime.msec_timestamp;	  m_byte_stream->used_bytes_for_frame(ret);	  bytes_decoded += ret;	} else {	  m_byte_stream->used_bytes_for_frame(frame_len);	}      }    }    // calculate frame rate for session  }  if (is_audio() == false)    media_message(LOG_NOTICE, "Video decoder skipped %u frames", 		  decode_skipped_frames);  if (last_decode_time > start_decode_time) {    double fps, bps;    double secs;    uint64_t total_time = last_decode_time - start_decode_time;    secs = UINT64_TO_DOUBLE(total_time);    secs /= 1000.0;#if 0    media_message(LOG_DEBUG, "last time "U64" first "U64, 		  last_decode_time, start_decode_time);#endif    fps = frames_decoded;    fps /= secs;    bps = UINT64_TO_DOUBLE(bytes_decoded);    bps *= 8.0 / secs;    media_message(LOG_NOTICE, "%s - bytes "U64", seconds %g, fps %g bps %g",		  get_name(),		  bytes_decoded, secs, 		  fps, bps);  }  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 + -