[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] gnash/server/asobj NetStream.cpp NetStream.h
From: |
Vitaly Alexeev |
Subject: |
[Gnash-commit] gnash/server/asobj NetStream.cpp NetStream.h |
Date: |
Fri, 03 Nov 2006 15:09:25 +0000 |
CVSROOT: /sources/gnash
Module name: gnash
Changes by: Vitaly Alexeev <alexeev> 06/11/03 15:09:25
Modified files:
server/asobj : NetStream.cpp NetStream.h
Log message:
* server\asobj\NetStream.h, cpp: updated video timing
* testsuite\sample\player.swf: 4 video simultaneously
* win32\gnash\gnash.vcproj: added new files
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetStream.cpp?cvsroot=gnash&r1=1.11&r2=1.12
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetStream.h?cvsroot=gnash&r1=1.9&r2=1.10
Patches:
Index: NetStream.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetStream.cpp,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -b -r1.11 -r1.12
--- NetStream.cpp 1 Nov 2006 16:16:12 -0000 1.11
+++ NetStream.cpp 3 Nov 2006 15:09:25 -0000 1.12
@@ -18,7 +18,7 @@
//
//
-/* $Id: NetStream.cpp,v 1.11 2006/11/01 16:16:12 alexeev Exp $ */
+/* $Id: NetStream.cpp,v 1.12 2006/11/03 15:09:25 alexeev Exp $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -39,13 +39,8 @@
#include "unistd.h" // for sleep()
#endif
-#ifndef __GNUC__
- #define fmod std::fmod
-#endif
-
namespace gnash {
-
namespace globals { // gnash::globals
/// global StreamProvider
@@ -57,17 +52,15 @@
NetStream::NetStream():
m_video_index(-1),
m_audio_index(-1),
- m_time_remainder(0),
#ifdef USE_FFMPEG
m_VCodecCtx(NULL),
m_ACodecCtx(NULL),
m_FormatCtx(NULL),
m_Frame(NULL),
#endif
- m_AudioStreams(0),
m_go(false),
- m_frame_time(0.0f),
- m_yuv(NULL)
+ m_yuv(NULL),
+ m_video_clock(0)
{
}
@@ -81,12 +74,17 @@
// terminate thread
m_go = false;
+ // wait till thread is complete before main continues
+ pthread_join(m_thread, NULL);
+
sound_handler* s = get_sound_handler();
if (s)
{
s->detach_aux_streamer((void*) this);
}
+
#ifdef USE_FFMPEG
+
if (m_Frame) av_free(m_Frame);
m_Frame = NULL;
@@ -98,7 +96,9 @@
if (m_FormatCtx) av_close_input_file(m_FormatCtx);
m_FormatCtx = NULL;
+
#endif
+
render::delete_YUV_video(m_yuv);
m_yuv = NULL;
@@ -138,6 +138,7 @@
// 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
+
#ifdef USE_FFMPEG
// Is it already playing ?
@@ -154,7 +155,7 @@
// 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");
+ log_error("Couldn't open file '%s'", c_url);
return -1;
}
@@ -162,7 +163,7 @@
// 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");
+ log_error("Couldn't find stream information from '%s'", c_url);
return -1;
}
m_FormatCtx->pb.eof_reached = 0;
@@ -181,6 +182,7 @@
if (m_audio_index < 0)
{
m_audio_index = i;
+ m_audio_stream =
m_FormatCtx->streams[i]; //vv
}
break;
@@ -188,6 +190,7 @@
if (m_video_index < 0)
{
m_video_index = i;
+ m_video_stream =
m_FormatCtx->streams[i]; //vv
}
break;
}
@@ -195,7 +198,7 @@
if (m_video_index < 0)
{
- printf("Didn't find a video stream\n");
+ log_error("Didn't find a video stream from '%s'", c_url);
return -1;
}
@@ -206,14 +209,14 @@
AVCodec* pCodec = avcodec_find_decoder(m_VCodecCtx->codec_id);
if (pCodec == NULL)
{
- printf("Codec not found\n");
+ log_error("Decoder not found");
return -1;
}
// Open codec
if (avcodec_open(m_VCodecCtx, pCodec) < 0)
{
- printf("Could not open codec\n");
+ log_error("Could not open codec");
}
// Allocate a frame to store the decoded frame in
@@ -222,18 +225,10 @@
// Determine required buffer size and allocate buffer
m_yuv = render::create_YUV_video(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)
+ sound_handler* s = get_sound_handler();
+ if (m_audio_index >= 0 && s != NULL)
{
- m_AudioStreams++;
- }
- }
-
// Get a pointer to the audio codec context for the video stream
m_ACodecCtx = m_FormatCtx->streams[m_audio_index]->codec;
@@ -241,25 +236,21 @@
AVCodec* pACodec = avcodec_find_decoder(m_ACodecCtx->codec_id);
if(pACodec == NULL)
{
- printf("No available AUDIO codec to process MPEG file: %s", "aqwedqw");
+ log_error("No available AUDIO decoder to process MPEG file: '%s'",
c_url);
+ return -1;
}
// Open codec
- if(avcodec_open(m_ACodecCtx, pACodec) < 0)
+ if (avcodec_open(m_ACodecCtx, pACodec) < 0)
{
- printf("Could not open AUDIO codec");// Could not open
codec
+ log_error("Could not open AUDIO codec");
+ return -1;
}
-// int samplerate = m_ACodecCtx->sample_rate;
-
- sound_handler* s = get_sound_handler();
- if (s)
- {
s->attach_aux_streamer(audio_streamer, (void*) this);
- }
+
}
- m_frame_time = (float)m_VCodecCtx->time_base.num /
(float)m_VCodecCtx->time_base.den;
#endif
pthread_create(&m_thread, NULL, NetStream::av_streamer, this);
@@ -272,32 +263,43 @@
{
NetStream* ns = static_cast<NetStream*>(arg);
raw_videodata_t* unqueued_data = NULL;
+ raw_videodata_t* video = NULL;
+ ns->m_video_clock = 0;
+
+ int delay = 0;
+ double start_clock = tu_timer::ticks_to_seconds(tu_timer::get_ticks());
ns->m_go = true;
- uint32_t 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);
+ if (ns->m_qvideo.size() > 0)
+ {
+ video = ns->m_qvideo.front();
+ double clock =
tu_timer::ticks_to_seconds(tu_timer::get_ticks()) - start_clock;
+ double video_clock = video->m_pts;
+
+ if (clock >= video_clock)
+ {
+ ns->m_yuv->update(video->m_data);
+ ns->m_qvideo.pop();
+ delete video;
+ delay = 0;
+ }
+ else
+ {
+ delay = int(1000 * (video_clock - clock));
+ }
+ }
// Don't hog the CPU.
// Queues have filled, video frame have shown
// now it is possible and to have a rest
- if (unqueued_data)
+ if (unqueued_data && delay > 0)
{
- sleep(10);
+ sleep(delay);
}
}
- ns->m_go = false;
-
- pthread_cancel(pthread_self());
- pthread_testcancel();
-
return 0;
}
@@ -309,47 +311,22 @@
while (len > 0 && ns->m_qaudio.size() > 0)
{
raw_videodata_t* samples = ns->m_qaudio.front();
- if (len >= samples->m_size)
- {
- int n = samples->m_size;
+
+ int n = imin(samples->m_size, len);
memcpy(stream, samples->m_ptr, n);
stream += n;
samples->m_ptr += n;
- len -= n;
samples->m_size -= n;
- ns->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)
+ if (samples->m_size == 0)
{
- raw_videodata_t* video = m_qvideo.front();
- m_yuv->update(video->m_data);
- m_qvideo.pop();
- delete video;
+ ns->m_qaudio.pop();
+ delete samples;
}
- 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;
@@ -370,7 +347,9 @@
return ret;
}
+
#ifdef USE_FFMPEG
+
AVPacket packet;
if (av_read_frame(m_FormatCtx, &packet) >= 0)
{
@@ -383,16 +362,22 @@
sound_handler* s = get_sound_handler();
if (s)
{
+
int16_t* adjusted_data = 0;
int n = 0;
- s->convert_raw_data(&adjusted_data, &n,
ptr, frame_size >> 1, 2, m_ACodecCtx->sample_rate, false);
+ bool stereo = m_ACodecCtx->channels > 1
? true : false;
+ s->convert_raw_data(&adjusted_data, &n,
ptr, frame_size >> 1, 2, m_ACodecCtx->sample_rate, stereo);
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;
+// samples->m_pts = m_audio_clock;
+// n = 2 * m_audio_stream->codec->channels;
+// m_audio_clock += (double) frame_size /
(double)(n * m_audio_stream->codec->sample_rate);
+
ret = m_qaudio.push(samples) ? NULL :
samples;
}
}
@@ -416,6 +401,30 @@
video->m_ptr = video->m_data;
video->m_stream_index = m_video_index;
+ // set presentation timestamp
+ if (packet.dts != AV_NOPTS_VALUE)
+ {
+ video->m_pts =
as_double(m_video_stream->time_base) * packet.dts;
+ }
+
+ if (video->m_pts != 0)
+ {
+ // update video clock with pts, if
present
+ m_video_clock = video->m_pts;
+ }
+ else
+ {
+ video->m_pts = m_video_clock;
+ }
+
+ // update video clock for next frame
+ double frame_delay =
as_double(m_video_stream->codec->time_base);
+
+ // for MPEG2, the frame can be repeated, so we
update the clock accordingly
+ frame_delay += m_Frame->repeat_pict *
(frame_delay * 0.5);
+
+ m_video_clock += frame_delay;
+
int copied = 0;
uint8_t* ptr = video->m_data;
for (int i = 0; i < 3 ; i++)
@@ -439,7 +448,9 @@
}
av_free_packet(&packet);
}
+
#endif
+
return ret;
}
Index: NetStream.h
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetStream.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -b -r1.9 -r1.10
--- NetStream.h 1 Nov 2006 16:16:12 -0000 1.9
+++ NetStream.h 3 Nov 2006 15:09:25 -0000 1.10
@@ -18,7 +18,7 @@
//
//
-/* $Id: NetStream.h,v 1.9 2006/11/01 16:16:12 alexeev Exp $ */
+/* $Id: NetStream.h,v 1.10 2006/11/03 15:09:25 alexeev Exp $ */
#ifndef __NETSTREAM_H__
#define __NETSTREAM_H__
@@ -43,7 +43,8 @@
m_stream_index(-1),
m_size(0),
m_data(NULL),
- m_ptr(NULL)
+ m_ptr(NULL),
+ m_pts(0)
{
};
@@ -59,6 +60,7 @@
uint32_t m_size;
uint8_t* m_data;
uint8_t* m_ptr;
+ double m_pts; // presentation timestamp in sec
};
template<class T>
@@ -95,7 +97,7 @@
{
bool rc = false;
lock();
- if (m_queue.size() < 10) // hack
+ if (m_queue.size() < 40) // hack
{
m_queue.push(member);
rc = true;
@@ -152,14 +154,19 @@
void seek();
void setBufferTime();
- void advance(float delta_time);
raw_videodata_t* read_frame(raw_videodata_t* vd);
YUV_video* get_video();
- bool playing()
+
+ inline bool playing()
{
return m_go;
}
+ inline double as_double(AVRational time)
+ {
+ return time.num / (double) time.den;
+ }
+
static void* av_streamer(void* arg);
static void audio_streamer(void *udata, uint8 *stream, int len);
@@ -173,8 +180,16 @@
bool _time;
#ifdef USE_FFMPEG
AVFormatContext *m_FormatCtx;
- AVCodecContext* m_VCodecCtx; // video
- AVCodecContext *m_ACodecCtx; // audio
+
+ // video
+ AVCodecContext* m_VCodecCtx;
+ AVStream* m_video_stream;
+ double m_video_clock;
+
+ // audio
+ AVCodecContext *m_ACodecCtx;
+ AVStream* m_audio_stream;
+
AVFrame* m_Frame;
#endif
YUV_video* m_yuv;
@@ -182,13 +197,9 @@
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