gnash-commit
[Top][All Lists]
Advanced

[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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]