Example #1
0
	void	sound_stop(const function_call& fn)
	{
		sound_handler* s = get_sound_handler();
		if (s != NULL)
		{
			as_sound*	snd = cast_to<as_sound>(fn.this_ptr);
			assert(snd);
			s->stop_sound(snd->m_id);
		}
	}
Example #2
0
	// The number of milliseconds a sound has been playing. 
	// If the sound is looped, the position is reset to 0 at the beginning of each loop.
	void	get_position(const function_call& fn)
	{
		sound_handler* s = get_sound_handler();
		if (s != NULL)
		{
			as_sound*	snd = cast_to<as_sound>(fn.this_ptr);
			assert(snd);

			int ms = s->get_position(snd->m_id);
			fn.result->set_int(ms);
		}
	}
Example #3
0
	void	sprite_instance::set_play_state(play_state s)
	// Stop or play the sprite.
	{
		// pauses stream sound
		sound_handler* sound = get_sound_handler();
		if (sound)
		{
			if (m_def->m_ss_id >= 0)
			{
				sound->pause(m_def->m_ss_id, m_play_state == PLAY ? true : false);
			}
		}
		m_play_state = s;
	}
	// it is running in sound mixer thread
	bool as_netstream::decode_audio(const AVPacket& pkt, Sint16** data, int* size)
	{
		bool ok = false;
		int frame_size;
		Uint8* decoder_buf = (Uint8*) malloc((AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2);
		if (avcodec_decode_audio(m_ACodecCtx, (Sint16*) decoder_buf, &frame_size,	pkt.data, pkt.size) >= 0)
		{
			sound_handler* sh = get_sound_handler();
			if (sh)
			{
				sh->cvt(data, size, decoder_buf, frame_size, m_ACodecCtx->channels, m_ACodecCtx->sample_rate);
				ok = true;
			}
		}
		free(decoder_buf);
		return ok;
	}
Example #5
0
	void	sound_start(const function_call& fn)
	{
		sound_handler* s = get_sound_handler();
		if (s != NULL)
		{
			as_sound*	snd = cast_to<as_sound>(fn.this_ptr);
			if (snd)
			{
				int offset = 0;
				int loops = 0;
				if (fn.nargs >= 2)
				{
					offset = fn.arg(0).to_int();
					loops = fn.arg(1).to_int();
				}
				s->play_sound(snd, snd->m_id, loops);
			}
		}
	}
Example #6
0
	// public loadSound(url:String, isStreaming:Boolean) : Void
	void	sound_load(const function_call& fn)
	{
		if (fn.nargs > 1)
		{
			sound_handler* s = get_sound_handler();
			if (s != NULL)
			{
				as_sound*	snd = cast_to<as_sound>(fn.this_ptr);
				assert(snd);

				lfl_string full_url = get_full_url(fn.get_player()->get_workdir(), 
					fn.arg(0).to_string());
				int id = s->load_sound(full_url.c_str());
				if (id >= 0)
				{
					snd->clear();
					snd->m_id = id;
					snd->m_is_loaded_sound = true;
				}
			}
		}
	}
Example #7
0
	void	sound_volume(const function_call& fn)
	{
		if (fn.nargs < 1)
		{
			log_error("set volume of sound needs one argument\n");
			return;
		}
		
		int volume = fn.arg(0).to_int();

		// sanity check
		if (volume >= 0 && volume <= 100)
		{
			sound_handler* s = get_sound_handler();
			if (s != NULL)
			{
				as_sound*	snd = cast_to<as_sound>(fn.this_ptr);
				assert(snd);
				s->set_volume(snd->m_id, volume);
			}
		}
	}
	void as_netstream::play(const char* url)
	{
		switch (m_status)
		{
			default:
				break;
			case PAUSE:
				m_status = PLAY;
				m_decoder.signal();
				break;
			case STOP:
			{
				// is path relative ?
				tu_string infile = get_player()->get_workdir();
				if (strstr(url, ":") || url[0] == '/')
				{
					infile = "";
				}
				infile += url;
				m_url = infile;

				get_root()->add_listener(this);
				if (open_stream(m_url.c_str()) == true)
				{
					sound_handler* sound = get_sound_handler();
					if (sound)
					{
						sound->attach_aux_streamer(audio_streamer, this);
					}

					m_thread = new tu_thread(netstream_server, this);
				}
				break;
			}
		}
	}
	// it is running in decoder thread
	bool as_netstream::open_stream(const char* c_url)
	{
		// This registers all available file formats and codecs 
		// with the library so they will be used automatically when
		// a file with the corresponding format/codec is opened

		// Open video file
		// The last three parameters specify the file format, buffer size and format parameters;
		// by simply specifying NULL or 0 we ask libavformat to auto-detect the format 
		// and use a default buffer size

		if (av_open_input_file(&m_FormatCtx, c_url, NULL, 0, NULL) != 0)
		{
//			log_error("Couldn't open file '%s'\n", c_url);
			set_status(error, playStreamNotFound);
			return false;
		}

		// Next, we need to retrieve information about the streams contained in the file
		// This fills the streams field of the AVFormatContext with valid information
		if (av_find_stream_info(m_FormatCtx) < 0)
		{
			log_error("Couldn't find stream information from '%s'\n", c_url);
			return false;
		}

		// Find the first video & audio stream
		m_video_index = -1;
		m_audio_index = -1;
		for (int i = 0; i < m_FormatCtx->nb_streams; i++)
		{
			AVCodecContext* enc = m_FormatCtx->streams[i]->codec; 

			switch (enc->codec_type)
			{
				default:
					break;

				case CODEC_TYPE_AUDIO:

					if (m_audio_index < 0)
					{
						m_audio_index = i;
						m_audio_stream = m_FormatCtx->streams[i];
					}
					break;

				case CODEC_TYPE_VIDEO:

					if (m_video_index < 0) 
					{
						m_video_index = i;
						m_video_stream = m_FormatCtx->streams[i];
					}
					break;

				case CODEC_TYPE_DATA:
				case CODEC_TYPE_SUBTITLE:
				case CODEC_TYPE_UNKNOWN:
					break;
			}
		}

		if (m_video_index < 0)
		{
			log_error("Didn't find a video stream from '%s'\n", c_url);
			return false;
		}

		// Get a pointer to the codec context for the video stream
		m_VCodecCtx = m_FormatCtx->streams[m_video_index]->codec;

		// Find the decoder for the video stream
		AVCodec* pCodec = avcodec_find_decoder(m_VCodecCtx->codec_id);
		if (pCodec == NULL)
		{
			m_VCodecCtx = NULL;
			log_error("Decoder not found\n");
			return false;
		}

		// Open codec
		if (avcodec_open(m_VCodecCtx, pCodec) < 0)
		{
			m_VCodecCtx = NULL;
			log_error("Could not open codec\n");
			return false;
		}

		if (m_audio_index >= 0 && get_sound_handler() != NULL)
		{
			// Get a pointer to the audio codec context for the video stream
			m_ACodecCtx = m_FormatCtx->streams[m_audio_index]->codec;

			// Find the decoder for the audio stream
			AVCodec* pACodec = avcodec_find_decoder(m_ACodecCtx->codec_id);
			if (pACodec == NULL)
			{
				log_error("No available AUDIO decoder to process MPEG file: '%s'\n", c_url);
				return false;
			}

			// Open codec
			if (avcodec_open(m_ACodecCtx, pACodec) < 0)
			{
				log_error("Could not open AUDIO codec\n");
				return false;
			}
		}

		m_convert_ctx = sws_getContext(
			m_VCodecCtx->width, m_VCodecCtx->height, m_VCodecCtx->pix_fmt,
			m_VCodecCtx->width, m_VCodecCtx->height, PIX_FMT_RGBA32,
			SWS_BICUBIC, NULL, NULL, NULL);

		assert(m_convert_ctx);

		return true;
	}
	// it is running in decoder thread
	void as_netstream::run()
	{
		set_status(status, playStart);

		m_start_time = now();
		m_video_time = 0;
		
		m_status = PLAY;
		while (m_status == PLAY || m_status == PAUSE)
		{
			if (m_status == PAUSE)
			{
				double paused = now();
				m_decoder.wait();
				m_start_time += now() - paused;
				continue;
			}

			// seek request
			if (m_seek_time >= 0)
			{
				int64 timestamp = (int64) (m_seek_time * AV_TIME_BASE);
				int flags = m_seek_time > m_video_time ? 0 : AVSEEK_FLAG_BACKWARD;
				int ret = av_seek_frame(m_FormatCtx, -1, timestamp, flags);
				if (ret == 0)
				{
					m_aq.clear();
					m_vq.clear();
					m_start_time += m_video_time - m_seek_time;
					m_video_time = m_seek_time;
					set_status(status, seekNotify);
				}
				else
				{
					set_status(error, seekInvalidTime);
				}
				m_seek_time = -1;
			}

			if (get_bufferlength() < m_buffer_time)
			{
				//printf("m_buffer_length=%f, queue_size=%d\n", get_bufferlength(), m_vq.size()); 

				AVPacket pkt;
				int rc = av_read_frame(m_FormatCtx, &pkt);
				if (rc < 0)
				{
					if (m_vq.size() == 0)
					{
						break;
					}
				}
				else
				{
					if (pkt.stream_index == m_video_index)
					{
						m_vq.push(new av_packet(pkt));
					}
					else
					if (pkt.stream_index == m_audio_index)
					{
						if (get_sound_handler())
						{
							m_aq.push(new av_packet(pkt));
						}
					}
					else
					{
						continue;
					}
				}
			}

			// skip expired video frames
			double current_time = now() - m_start_time;
			while (current_time >= m_video_time)
			{
				gc_ptr<av_packet> packet;
				if (m_vq.pop(&packet))
				{
					const AVPacket& pkt = packet->get_packet();

					// update video clock with pts, if present
					if (pkt.dts > 0)
					{
						m_video_time = av_q2d(m_video_stream->time_base) * pkt.dts;
					}
					m_video_time += av_q2d(m_video_stream->codec->time_base);	// +frame_delay

					set_video_data(decode_video(pkt));
				}
				else
				{
					// no packets in queue
//					set_status("status", "NetStream.Buffer.Empty");
					break;
				}
			}

			// Don't hog the CPU.
			// Queues have filled, video frame have shown
			// now it is possible and to have a rest

			int delay = (int) (1000 * (m_video_time - current_time));
			
			// hack, adjust m_start_time after seek
			if (delay > 50)
			{
				m_start_time -= (m_video_time - current_time);
				current_time = now() - m_start_time;
				delay = (int) (1000 * (m_video_time - current_time));
			}

			assert(delay <= 50);

			if (delay > 0)
			{
				if (get_bufferlength() >= m_buffer_time)
				{
//					set_status("status", "NetStream.Buffer.Full");
					tu_timer::sleep(delay);
				}
//				printf("current_time=%f, video_time=%f, delay=%d\n", current_time, m_video_time, delay);
			}
		}

		sound_handler* sound = get_sound_handler();
		if (sound)
		{
			sound->detach_aux_streamer(this);
		}

		close_stream();

		set_status(status, playStop);
		m_status = STOP;
	}