[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] gnash/server/asobj LocalConnection.cpp LocalCon...
From: |
Vitaly Alexeev |
Subject: |
[Gnash-commit] gnash/server/asobj LocalConnection.cpp LocalCon... |
Date: |
Fri, 27 Oct 2006 14:29:49 +0000 |
CVSROOT: /sources/gnash
Module name: gnash
Changes by: Vitaly Alexeev <alexeev> 06/10/27 14:29:49
Modified files:
server/asobj : LocalConnection.cpp LocalConnection.h
NetStream.cpp NetStream.h
Log message:
videostream implementation
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/LocalConnection.cpp?cvsroot=gnash&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/LocalConnection.h?cvsroot=gnash&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetStream.cpp?cvsroot=gnash&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetStream.h?cvsroot=gnash&r1=1.3&r2=1.4
Patches:
Index: LocalConnection.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/LocalConnection.cpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- LocalConnection.cpp 22 Oct 2006 01:00:54 -0000 1.3
+++ LocalConnection.cpp 27 Oct 2006 14:29:49 -0000 1.4
@@ -63,7 +63,9 @@
void
LocalConnection::close()
{
+#ifndef NETWORK_CONN
closeMem();
+#endif
}
/// \brief Prepares the LocalConnection object to receive commands from a
@@ -75,9 +77,11 @@
bool
LocalConnection::connect(const char *name)
{
+#ifndef NETWORK_CONN
if (attach(name, true) == false) {
return false;
}
+#endif
_name = name;
return true;
@@ -122,11 +126,12 @@
localconnection_obj->set_member("domain", &localconnection_domain);
localconnection_obj->set_member("send", &localconnection_send);
//#ifdef ENABLE_TESTING
+#ifndef NETWORK_CONN
localconnection_obj->set_member("getname", &shm_getname);
localconnection_obj->set_member("getsize", &shm_getsize);
localconnection_obj->set_member("getallocated", &shm_getallocated);
localconnection_obj->set_member("exists", &shm_exists);
-//#endif
+#endif
fn.result->set_as_object(localconnection_obj);
}
Index: LocalConnection.h
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/LocalConnection.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- LocalConnection.h 22 Oct 2006 01:00:54 -0000 1.4
+++ LocalConnection.h 27 Oct 2006 14:29:49 -0000 1.5
@@ -55,7 +55,12 @@
namespace gnash {
+#ifdef NETWORK_CONN
+class LocalConnection {
+#else
class LocalConnection : public Shm {
+#endif
+
public:
LocalConnection();
~LocalConnection();
Index: NetStream.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetStream.cpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- NetStream.cpp 22 Jul 2006 23:47:56 -0000 1.1
+++ NetStream.cpp 27 Oct 2006 14:29:49 -0000 1.2
@@ -44,31 +44,412 @@
#include "NetStream.h"
#include "fn_call.h"
+#include "streamProvider.h"
+#include "render.h"
+#include "movie_root.h"
+
+#if defined(_WIN32) || defined(WIN32)
+ #include <Windows.h> // for sleep()
+#endif
+
namespace gnash {
-NetStream::NetStream() {
+
+namespace globals { // gnash::globals
+
+ /// global StreamProvider
+ extern StreamProvider streamProvider;
+
+} // namespace gnash::global
+
+
+NetStream::NetStream():
+ m_video_index(-1),
+ m_audio_index(-1),
+ m_time_remainder(0),
+ m_VCodecCtx(NULL),
+ m_ACodecCtx(NULL),
+ m_FormatCtx(NULL),
+ m_AudioStreams(0),
+ m_go(false),
+// m_thread(NULL),
+ m_frame_time(0.0f),
+ m_yuv(NULL),
+ m_Frame(NULL)
+{
}
-NetStream::~NetStream() {
+NetStream::~NetStream()
+{
+ close();
}
+void NetStream::close()
+{
+ // terminate thread
+ m_go = false;
+// if (m_thread) SDL_WaitThread(m_thread, NULL);
+// m_thread = NULL;
+
+ sound_handler* s = get_sound_handler();
+ if (s)
+ {
+// s->stop_streamer();
+ }
+
+ if (m_Frame) av_free(m_Frame);
+ m_Frame = NULL;
+
+ if (m_VCodecCtx) avcodec_close(m_VCodecCtx);
+ m_VCodecCtx = NULL;
+
+ if (m_ACodecCtx) avcodec_close(m_ACodecCtx);
+ m_ACodecCtx = NULL;
+
+ if (m_FormatCtx) av_close_input_file(m_FormatCtx);
+ m_FormatCtx = NULL;
+
+ render::delete_YUV_video(m_yuv);
+ m_yuv = NULL;
+
+ while (m_qvideo.size() > 0)
+ {
+ delete m_qvideo.front();
+ m_qvideo.pop();
+ }
+
+ while (m_qaudio.size() > 0)
+ {
+ delete m_qaudio.front();
+ m_qaudio.pop();
+ }
+
+}
void
-NetStream::close()
+NetStream::play(const char* c_url)
{
- log_msg("%s:unimplemented \n", __FUNCTION__);
+/* URL url(c_url);
+
+ tu_file* in = globals::streamProvider.getStream(url);
+ if (in == NULL)
+ {
+ log_error("failed to open '%s'; can't create movie.\n", c_url);
+ return;
+ }
+ else if (in->get_error())
+ {
+ log_error("streamProvider opener can't open '%s'\n", c_url);
+ return;
+ }
+*/
+
+ // 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
+
+ if (m_FormatCtx)
+ {
+ return;
+ }
+
+ av_register_all();
+
+ // 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)
+ {
+ printf("Couldn't open file\n");
+ return;
+ }
+
+ // 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)
+ {
+ printf("Couldn't find stream information\n");
+ return;
+ }
+ m_FormatCtx->pb.eof_reached = 0;
+
+ av_read_play(m_FormatCtx);
+
+ // 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)
+ {
+ case CODEC_TYPE_AUDIO:
+ if (m_audio_index < 0)
+ {
+ m_audio_index = i;
+ }
+ break;
+
+ case CODEC_TYPE_VIDEO:
+ if (m_video_index < 0)
+ {
+ m_video_index = i;
+ }
+ break;
+ }
+ }
+
+ if (m_video_index < 0)
+ {
+ printf("Didn't find a video stream\n");
+ return;
+ }
+
+ // 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)
+ {
+ printf("Codec not found\n");
+ return;
+ }
+
+ // Open codec
+ if (avcodec_open(m_VCodecCtx, pCodec) < 0)
+ {
+ printf("Could not open codec\n");
+ }
+
+ // Allocate a frame to store the decoded frame in
+ m_Frame = avcodec_alloc_frame();
+
+ // Determine required buffer size and allocate buffer
+ m_yuv = render::create_YUV_video(m_VCodecCtx->width,
m_VCodecCtx->height);
+// avpicture_get_size(PIX_FMT_YUV420P, m_VCodecCtx->width,
m_VCodecCtx->height));
+
+ if (m_audio_index >= 0)
+ {
+
+ //Find the number of audio streams (channels)
+ for (int i=0; i < m_FormatCtx->nb_streams; i++)
+ {
+ if (m_FormatCtx->streams[i]->codec->codec_type ==
CODEC_TYPE_AUDIO)
+ {
+ m_AudioStreams++;
+ }
+ }
+
+ // 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)
+ {
+ printf("No available AUDIO codec to process MPEG file: %s", "aqwedqw");
+ }
+
+ // Open codec
+ if(avcodec_open(m_ACodecCtx, pACodec) < 0)
+ {
+ printf("Could not open AUDIO codec");// Could not open
codec
+ }
+
+// int samplerate = m_ACodecCtx->sample_rate;
+
+ sound_handler* s = get_sound_handler();
+ if (s)
+ {
+// s->start_streamer(this);
+ }
+ }
+
+ m_frame_time = (float)m_VCodecCtx->time_base.num /
(float)m_VCodecCtx->time_base.den;
+
+// m_thread = SDL_CreateThread(NetStream::av_streamer, this);
+ pthread_create(&m_thread, NULL, NetStream::av_streamer, this);
}
-void
-NetStream::pause()
+// decoder thread
+void* NetStream::av_streamer(void* arg)
{
- log_msg("%s:unimplemented \n", __FUNCTION__);
+ NetStream* ns = static_cast<NetStream*>(arg);
+ raw_videodata_t* unqueued_data = NULL;
+
+ ns->m_go = true;
+ uint32 last_ticks = 0;
+ while (ns->m_go)
+ {
+ uint32_t ticks = tu_timer::get_ticks();
+ int delta_ticks = ticks - last_ticks;
+ last_ticks = ticks;
+ float delta_t = delta_ticks / 1000.0f;
+
+ unqueued_data = ns->read_frame(unqueued_data);
+ ns->advance(delta_t);
+
+ // Don't hog the CPU.
+ if (unqueued_data)
+ {
+ //SDL_Delay(25);
+ Sleep(25);
+ }
+ }
+ ns->m_go = false;
+
+ pthread_cancel(pthread_self());
+ pthread_testcancel();
+
+ return 0;
}
-void
-NetStream::play()
+// audio callback is running in sound handler thread
+void NetStream::audio_streamer(Uint8 *stream, int len)
{
- log_msg("%s:unimplemented \n", __FUNCTION__);
+ while (len > 0 && m_qaudio.size() > 0)
+ {
+ raw_videodata_t* samples = m_qaudio.front();
+ if (len >= samples->m_size)
+ {
+ int n = samples->m_size;
+ memcpy(stream, samples->m_ptr, n);
+ stream += n;
+ samples->m_ptr += n;
+ len -= n;
+ samples->m_size -= n;
+ m_qaudio.pop();
+ delete samples;
+ }
+ else
+ {
+ int n = len;
+ memcpy(stream, samples->m_ptr, n);
+ stream += n;
+ samples->m_ptr += n;
+ len -= n;
+ samples->m_size -= n;
+ }
+ }
+}
+
+void NetStream::advance(float delta_time)
+{
+ m_time_remainder += delta_time;
+ if (m_time_remainder >= m_frame_time)
+ {
+ m_time_remainder -= m_frame_time;
+ if (m_qvideo.size() > 0)
+ {
+ raw_videodata_t* video = m_qvideo.front();
+ m_yuv->update(video->m_data);
+ m_qvideo.pop();
+ delete video;
+ }
+ m_time_remainder = fmod(m_time_remainder, m_frame_time);
+ }
+}
+
+raw_videodata_t* NetStream::read_frame(raw_videodata_t* unqueued_data)
+{
+ raw_videodata_t* ret = NULL;
+ if (unqueued_data)
+ {
+ if (unqueued_data->m_stream_index == m_audio_index)
+ {
+ sound_handler* s = get_sound_handler();
+ if (s)
+ {
+// ret = m_qaudio.push(unqueued_data) ? NULL :
unqueued_data;
+ }
+ }
+ else
+ {
+ ret = m_qvideo.push(unqueued_data) ? NULL :
unqueued_data;
+ }
+
+ return ret;
+ }
+
+ AVPacket packet;
+ if (av_read_frame(m_FormatCtx, &packet) >= 0)
+ {
+ if (packet.stream_index == m_audio_index)
+ {
+ int frame_size;
+ uint8_t* ptr = (uint8_t*)
malloc((AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2);
+ if (avcodec_decode_audio(m_ACodecCtx, (int16_t *)ptr,
&frame_size, packet.data, packet.size) >= 0)
+ {
+ sound_handler* s = get_sound_handler();
+ if (s)
+ {
+ int16_t* adjusted_data = 0;
+ int n = 0;
+
+// bool stereo = pACodecCtx->channels == 1
? false : true;
+// s->convert_raw_data(&adjusted_data, &n,
ptr, frame_size >> 1, 2, m_ACodecCtx->sample_rate, false);
+
+ raw_videodata_t* samples = new raw_videodata_t;
+ samples->m_data = (uint8_t*)
adjusted_data;
+ samples->m_ptr = samples->m_data;
+ samples->m_size = n;
+ samples->m_stream_index = m_audio_index;
+
+// ret = m_qaudio.push(samples) ? NULL :
samples;
+ }
+ }
+ free(ptr);
+ }
+ else
+ if (packet.stream_index == m_video_index)
+ {
+ int got = 0;
+ avcodec_decode_video(m_VCodecCtx, m_Frame, &got, packet.data,
packet.size);
+ if (got)
+ {
+ if (m_VCodecCtx->pix_fmt != PIX_FMT_YUV420P)
+ {
+// img_convert((AVPicture*) pFrameYUV,
PIX_FMT_YUV420P, (AVPicture*) pFrame, pCodecCtx->pix_fmt, pCodecCtx->width,
pCodecCtx->height);
+ assert(0); // TODO
+ }
+
+ raw_videodata_t* video = new raw_videodata_t;
+ video->m_data = (uint8_t*)
malloc(m_yuv->size());
+ video->m_ptr = video->m_data;
+ video->m_stream_index = m_video_index;
+
+ int copied = 0;
+ uint8_t* ptr = video->m_data;
+ for (int i = 0; i < 3 ; i++)
+ {
+ int shift = (i == 0 ? 0 : 1);
+ uint8_t* yuv_factor = m_Frame->data[i];
+ int h = m_VCodecCtx->height >> shift;
+ int w = m_VCodecCtx->width >> shift;
+ for (int j = 0; j < h; j++)
+ {
+ copied += w;
+ assert(copied <= m_yuv->size());
+ memcpy(ptr, yuv_factor, w);
+ yuv_factor +=
m_Frame->linesize[i];
+ ptr += w;
+ }
+ }
+ video->m_size = copied;
+ ret = m_qvideo.push(video) ? NULL : video;
+ }
+ }
+ av_free_packet(&packet);
+ }
+
+ return ret;
+}
+
+YUV_video* NetStream::get_video()
+{
+ return m_yuv;
}
void
@@ -82,6 +463,7 @@
{
log_msg("%s:unimplemented \n", __FUNCTION__);
}
+
void
netstream_new(const fn_call& fn)
{
@@ -93,17 +475,40 @@
netstream_obj->set_member("seek", &netstream_seek);
netstream_obj->set_member("setbuffertime", &netstream_setbuffertime);
+// netstream_obj->add_ref();
+// movie_root* mr = (movie_root*) get_current_root();
+// mr->add_net_stream(netstream_obj);
+
fn.result->set_as_object(netstream_obj);
}
-void netstream_close(const fn_call& /*fn*/) {
- log_msg("%s:unimplemented \n", __FUNCTION__);
+
+void netstream_close(const fn_call& fn)
+{
+ assert(dynamic_cast<netstream_as_object*>(fn.this_ptr));
+ netstream_as_object* ns =
static_cast<netstream_as_object*>(fn.this_ptr);
+ ns->obj.close();
}
+
void netstream_pause(const fn_call& /*fn*/) {
log_msg("%s:unimplemented \n", __FUNCTION__);
}
-void netstream_play(const fn_call& /*fn*/) {
- log_msg("%s:unimplemented \n", __FUNCTION__);
+
+void netstream_play(const fn_call& fn)
+{
+ assert(dynamic_cast<netstream_as_object*>(fn.this_ptr));
+ netstream_as_object* ns =
static_cast<netstream_as_object*>(fn.this_ptr);
+
+ if (fn.nargs < 1)
+ {
+ log_error("NetStream play needs args\n");
+ return;
+ }
+
+ // start gstreamer
+ ns->obj.play(fn.arg(0).to_string());
+
}
+
void netstream_seek(const fn_call& /*fn*/) {
log_msg("%s:unimplemented \n", __FUNCTION__);
}
Index: NetStream.h
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetStream.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- NetStream.h 26 Aug 2006 13:09:53 -0000 1.3
+++ NetStream.h 27 Oct 2006 14:29:49 -0000 1.4
@@ -43,19 +43,140 @@
#include "config.h"
#endif
+#include <queue>
+#include <pthread.h>
#include "impl.h"
+#include "video_stream_instance.h"
+#include "ffmpeg/avformat.h"
namespace gnash {
+struct raw_videodata_t
+{
+ raw_videodata_t():
+ m_stream_index(-1),
+ m_size(0),
+ m_data(NULL),
+ m_ptr(NULL)
+ {
+ };
+
+ ~raw_videodata_t()
+ {
+ if (m_data)
+ {
+ delete m_data;
+ }
+ };
+
+ int m_stream_index;
+ uint32_t m_size;
+ uint8_t* m_data;
+ uint8_t* m_ptr;
+};
+
+template<class T>
+class multithread_queue
+{
+ public:
+
+ multithread_queue()
+ {
+ pthread_mutex_init(&m_mutex, NULL);
+ };
+
+ ~multithread_queue()
+ {
+ while (m_queue.size() > 0)
+ {
+ T x = m_queue.front();
+ m_queue.pop();
+ delete x;
+ }
+
+ pthread_mutex_destroy(&m_mutex);
+ }
+
+ size_t size()
+ {
+ lock();
+ size_t n = m_queue.size();
+ unlock();
+ return n;
+ }
+
+ bool push(T member)
+ {
+ bool rc = false;
+ lock();
+ if (m_queue.size() < 10) // hack
+ {
+ m_queue.push(member);
+ rc = true;
+ }
+ unlock();
+ return rc;
+ }
+
+ T front()
+ {
+ lock();
+ T member = NULL;
+ if (m_queue.size() > 0)
+ {
+ member = m_queue.front();
+ }
+ unlock();
+ return member;
+ }
+
+ void pop()
+ {
+ lock();
+ if (m_queue.size() > 0)
+ {
+ m_queue.pop();
+ }
+ unlock();
+ }
+
+ private:
+
+ inline void lock()
+ {
+ pthread_mutex_lock(&m_mutex);
+ }
+
+ inline void unlock()
+ {
+ pthread_mutex_unlock(&m_mutex);
+ }
+
+ pthread_mutex_t m_mutex;
+ std::queue < T > m_queue;
+};
+
class NetStream {
public:
NetStream();
~NetStream();
void close();
void pause();
- void play();
+ void play(const char* source);
void seek();
void setBufferTime();
+
+ void advance(float delta_time);
+ raw_videodata_t* read_frame(raw_videodata_t* vd);
+ YUV_video* get_video();
+ void audio_streamer(Uint8 *stream, int len);
+ bool playing()
+ {
+ return m_go;
+ }
+
+ static void* av_streamer(void* arg);
+
private:
bool _bufferLength;
bool _bufferTime;
@@ -64,6 +185,23 @@
bool _currentFps;
bool _onStatus;
bool _time;
+
+ AVFormatContext *m_FormatCtx;
+ AVCodecContext* m_VCodecCtx; // video
+ AVCodecContext *m_ACodecCtx; // audio
+ AVFrame* m_Frame;
+ YUV_video* m_yuv;
+
+ pthread_t m_thread;
+ int m_video_index;
+ int m_audio_index;
+ int m_AudioStreams;
+ multithread_queue <raw_videodata_t*> m_qaudio;
+ multithread_queue <raw_videodata_t*> m_qvideo;
+ volatile bool m_go;
+
+ float m_time_remainder;
+ float m_frame_time;
};
class netstream_as_object : public as_object
- [Gnash-commit] gnash/server/asobj LocalConnection.cpp LocalCon...,
Vitaly Alexeev <=