CVSROOT: /sources/gnash Module name: gnash Changes by: Benjamin Wolsey <bwy> 07/11/27 08:45:33
Modified files: . : ChangeLog server/asobj : NetStreamFfmpeg.cpp NetStreamFfmpeg.h Log message: * server/asobj/NetStreamFfmpeg.{cpp,h}: mainly visual code cleanup. Also make sure allocated codec context is explicitly freed when stream is closed (fixes leak when playing FLVs). CVSWeb URLs: http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.4975&r2=1.4976 http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetStreamFfmpeg.cpp?cvsroot=gnash&r1=1.98&r2=1.99 http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetStreamFfmpeg.h?cvsroot=gnash&r1=1.52&r2=1.53 Patches: Index: ChangeLog =================================================================== RCS file: /sources/gnash/gnash/ChangeLog,v retrieving revision 1.4975 retrieving revision 1.4976 diff -u -b -r1.4975 -r1.4976 --- ChangeLog 27 Nov 2007 08:04:32 -0000 1.4975 +++ ChangeLog 27 Nov 2007 08:45:33 -0000 1.4976 @@ -1,3 +1,9 @@ +2007-11-27 Benjamin Wolsey <[EMAIL PROTECTED]> + + * server/asobj/NetStreamFfmpeg.{cpp,h}: mainly visual code cleanup. Also make + sure allocated codec context is explicitly freed when stream is closed + (fixes leak when playing FLVs). + 2007-11-27 Sandro Santilli <[EMAIL PROTECTED]> * server/as_value.h: rename allowUnloaded parameter of sprite accessor Index: server/asobj/NetStreamFfmpeg.cpp =================================================================== RCS file: /sources/gnash/gnash/server/asobj/NetStreamFfmpeg.cpp,v retrieving revision 1.98 retrieving revision 1.99 diff -u -b -r1.98 -r1.99 --- server/asobj/NetStreamFfmpeg.cpp 26 Nov 2007 21:53:00 -0000 1.98 +++ server/asobj/NetStreamFfmpeg.cpp 27 Nov 2007 08:45:33 -0000 1.99 @@ -17,7 +17,7 @@ // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // -/* $Id: NetStreamFfmpeg.cpp,v 1.98 2007/11/26 21:53:00 strk Exp $ */ +/* $Id: NetStreamFfmpeg.cpp,v 1.99 2007/11/27 08:45:33 bwy Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -52,7 +52,8 @@ //#define GNASH_DEBUG_STATUS // Used to free data in the AVPackets we create our self -static void avpacket_destruct(AVPacket* av) { +static void avpacket_destruct(AVPacket* av) +{ delete [] av->data; } @@ -99,7 +100,8 @@ if (mode == 0) pausePlayback(); else unpausePlayback(); } - if (!m_pause && !m_go) { + if (!m_pause && !m_go) + { setStatus(playStart); m_go = true; _decodeThread = new boost::thread(boost::bind(NetStreamFfmpeg::av_streamer, this)); @@ -133,13 +135,22 @@ if (m_Frame) av_free(m_Frame); m_Frame = NULL; - if (m_VCodecCtx) avcodec_close(m_VCodecCtx); + if (m_VCodecCtx) + { + avcodec_close(m_VCodecCtx); + av_free(m_VCodecCtx); + } m_VCodecCtx = NULL; - if (m_ACodecCtx) avcodec_close(m_ACodecCtx); + if (m_ACodecCtx) + { + avcodec_close(m_ACodecCtx); + av_free(m_ACodecCtx); + } m_ACodecCtx = NULL; - if (m_FormatCtx) { + if (m_FormatCtx) + { m_FormatCtx->iformat->flags = AVFMT_NOFILE; av_close_input_file(m_FormatCtx); m_FormatCtx = NULL; @@ -182,24 +193,30 @@ // ffmpeg callback function offset_t -NetStreamFfmpeg::seekMedia(void *opaque, offset_t offset, int whence){ +NetStreamFfmpeg::seekMedia(void *opaque, offset_t offset, int whence) +{ NetStreamFfmpeg* ns = static_cast<NetStreamFfmpeg*>(opaque); boost::intrusive_ptr<NetConnection> nc = ns->_netCon; // Offset is absolute new position in the file - if (whence == SEEK_SET) { + if (whence == SEEK_SET) + { nc->seek(offset); ns->inputPos = offset; // New position is offset + old position - } else if (whence == SEEK_CUR) { + } + else if (whence == SEEK_CUR) + { nc->seek(ns->inputPos + offset); ns->inputPos = ns->inputPos + offset; - // // New position is offset + end of file - } else if (whence == SEEK_END) { + // New position is offset + end of file + } + else if (whence == SEEK_END) + { // This is (most likely) a streamed file, so we can't seek to the end! // Instead we seek to 50.000 bytes... seems to work fine... nc->seek(50000); @@ -232,7 +249,8 @@ if (url.size() == 0) url += c_url; // Remove any "mp3:" prefix. Maybe should use this to mark as audio-only - if (url.compare(0, 4, std::string("mp3:")) == 0) { + if (url.compare(0, 4, std::string("mp3:")) == 0) + { url = url.substr(4); } @@ -255,19 +273,22 @@ { AVCodec* codec = avcodec_find_decoder(codec_id); - if (!codec) { + if (!codec) + { log_error(_("libavcodec couldn't find decoder")); return NULL; } AVCodecContext * context = avcodec_alloc_context(); - if (!context) { + if (!context) + { log_error(_("libavcodec couldn't allocate context")); return NULL; } int rv = avcodec_open(context, codec); - if (rv < 0) { + if (rv < 0) + { avcodec_close(context); log_error(_("libavcodec failed to initialize codec")); return NULL; @@ -286,14 +307,16 @@ { // Get video info from the parser std::auto_ptr<FLVVideoInfo> videoInfo( parser->getVideoInfo() ); - if (!videoInfo.get()) { + if (!videoInfo.get()) + { return NULL; } enum CodecID codec_id; // Find the decoder and init the parser - switch(videoInfo->codec) { + switch(videoInfo->codec) + { case media::VIDEO_CODEC_H263: codec_id = CODEC_ID_FLV1; break; @@ -320,13 +343,15 @@ { // Get audio info from the parser std::auto_ptr<FLVAudioInfo> audioInfo( parser->getAudioInfo() ); - if (!audioInfo.get()) { + if (!audioInfo.get()) + { return NULL; } enum CodecID codec_id; - switch(audioInfo->codec) { + switch(audioInfo->codec) + { case media::AUDIO_CODEC_RAW: codec_id = CODEC_ID_PCM_U16LE; break; @@ -361,7 +386,8 @@ probe_data.buf = buffer.get(); probe_data.buf_size = 2048; - if (ns->readPacket(ns, probe_data.buf, probe_data.buf_size) < 1){ + if (ns->readPacket(ns, probe_data.buf, probe_data.buf_size) < 1) + { log_error(_("Gnash could not read from movie url")); return NULL; } @@ -377,7 +403,8 @@ assert(nc); // Pass stuff from/to the NetConnection object. - if ( !nc->openConnection(url) ) { + if ( !nc->openConnection(url) ) + { log_error(_("Gnash could not open movie: %s"), url.c_str()); setStatus(streamNotFound); return false; @@ -388,15 +415,18 @@ // Check if the file is a FLV, in which case we use our own parser char head[4] = {0, 0, 0, 0}; - if (nc->read(head, 3) < 3) { + if (nc->read(head, 3) < 3) + { setStatus(streamNotFound); return false; } nc->seek(0); - if (std::string(head) == "FLV") { + if (std::string(head) == "FLV") + { m_isFLV = true; - if (!m_parser.get()) { + if (!m_parser.get()) + { m_parser = nc->getConnectedParser(); if (! m_parser.get() ) { @@ -411,16 +441,19 @@ avcodec_register_all(); m_VCodecCtx = initFlvVideo(m_parser.get()); - if (!m_VCodecCtx) { + if (!m_VCodecCtx) + { log_msg(_("Failed to initialize FLV video codec")); } m_ACodecCtx = initFlvAudio(m_parser.get()); - if (!m_ACodecCtx) { + if (!m_ACodecCtx) + { log_msg(_("Failed to initialize FLV audio codec")); } - if (!m_ACodecCtx && !m_VCodecCtx) { + if (!m_ACodecCtx && !m_VCodecCtx) + { return false; } @@ -443,7 +476,8 @@ av_register_all(); AVInputFormat* inputFmt = probeStream(this); - if (!inputFmt) { + if (!inputFmt) + { log_error(_("Couldn't determine stream input format from URL %s"), url.c_str()); return false; } @@ -459,7 +493,8 @@ m_FormatCtx = av_alloc_format_context(); // Open the stream. the 4th argument is the filename, which we ignore. - if(av_open_input_stream(&m_FormatCtx, &ByteIOCxt, "", inputFmt, NULL) < 0){ + if(av_open_input_stream(&m_FormatCtx, &ByteIOCxt, "", inputFmt, NULL) < 0) + { log_error(_("Couldn't open file '%s' for decoding"), url.c_str()); setStatus(streamNotFound); return false; @@ -537,9 +572,12 @@ m_Frame = avcodec_alloc_frame(); // Determine required buffer size and allocate buffer - if (m_videoFrameFormat == render::YUV) { + if (m_videoFrameFormat == render::YUV) + { m_imageframe = new image::yuv(m_VCodecCtx->width, m_VCodecCtx->height); - } else if (m_videoFrameFormat == render::RGB) { + } + else if (m_videoFrameFormat == render::RGB) + { m_imageframe = new image::rgb(m_VCodecCtx->width, m_VCodecCtx->height); } @@ -551,7 +589,7 @@ // Find the decoder for the audio stream AVCodec* pACodec = avcodec_find_decoder(m_ACodecCtx->codec_id); - if(pACodec == NULL) + if (pACodec == NULL) { log_error(_("No available audio decoder %d to process MPEG file: '%s'"), m_ACodecCtx->codec_id, url.c_str()); @@ -624,7 +662,8 @@ { // We need to restart the audio media::sound_handler* s = get_sound_handler(); - if (s) { + if (s) + { s->attach_aux_streamer(audio_streamer, ns); } } @@ -646,9 +685,11 @@ log_debug("Decoding iteration. bufferTime=%lu, bufferLen=%lu", ns->bufferTime(), ns->bufferLength()); #endif - if (ns->m_isFLV) { + if (ns->m_isFLV) + { // If queues are full then don't bother filling it - if ((ns->m_VCodecCtx && ns->m_qvideo.size() < 20) || (ns->m_ACodecCtx && ns->m_qaudio.size() < 20)) { + if ((ns->m_VCodecCtx && ns->m_qvideo.size() < 20) || (ns->m_ACodecCtx && ns->m_qaudio.size() < 20)) + { // If we have problems with decoding - break if (!ns->decodeFLVFrame() && ns->m_start_onbuffer == false && ns->m_qvideo.size() == 0 && ns->m_qaudio.size() == 0) @@ -658,7 +699,9 @@ } } - } else { + } + else + { // If we have problems with decoding - break if (ns->decodeMediaFrame() == false && ns->m_start_onbuffer == false && ns->m_qvideo.size() == 0 && ns->m_qaudio.size() == 0) @@ -721,13 +764,17 @@ bool NetStreamFfmpeg::decodeFLVFrame() { FLVFrame* frame = NULL; - if (m_qvideo.size() < m_qaudio.size() && m_VCodecCtx) { + if (m_qvideo.size() < m_qaudio.size() && m_VCodecCtx) + { frame = m_parser->nextVideoFrame(); - } else if (m_ACodecCtx) { + } + else if (m_ACodecCtx) + { frame = m_parser->nextAudioFrame(); } - if (frame == NULL) { + if (frame == NULL) + { if (_netCon->loadCompleted()) { #ifdef GNASH_DEBUG_THREADS @@ -735,7 +782,9 @@ #endif // Stop! //m_go = false; - } else { + } + else + { pausePlayback(); setStatus(bufferEmpty); m_start_onbuffer = true; @@ -751,10 +800,13 @@ // FIXME: is this the right value for packet.dts? packet->pts = packet->dts = static_cast<int64_t>(frame->timestamp); - if (frame->tag == 9) { + if (frame->tag == 9) + { packet->stream_index = 0; return decodeVideo(packet); - } else { + } + else + { packet->stream_index = 1; return decodeAudio(packet); } @@ -780,7 +832,8 @@ bool stereo = m_ACodecCtx->channels > 1 ? true : false; int samples = stereo ? frame_size >> 2 : frame_size >> 1; - if (_resampler.init(m_ACodecCtx)){ + if (_resampler.init(m_ACodecCtx)) + { // Resampling is needed. uint8_t* output = new uint8_t[bufsize]; @@ -818,8 +871,14 @@ // update video clock for next frame uint32_t frame_delay; - if (!m_isFLV) frame_delay = static_cast<uint32_t>((as_double(m_audio_stream->time_base) * packet->dts) * 1000.0); - else frame_delay = m_parser->audioFrameDelay(); + if (!m_isFLV) + { + frame_delay = static_cast<uint32_t>((as_double(m_audio_stream->time_base) * packet->dts) * 1000.0); + } + else + { + frame_delay = m_parser->audioFrameDelay(); + } m_last_audio_timestamp += frame_delay; @@ -839,30 +898,44 @@ { boost::scoped_array<uint8_t> buffer; - if (m_imageframe == NULL) { - if (m_videoFrameFormat == render::YUV) { + if (m_imageframe == NULL) + { + if (m_videoFrameFormat == render::YUV) + { m_imageframe = new image::yuv(m_VCodecCtx->width, m_VCodecCtx->height); - } else if (m_videoFrameFormat == render::RGB) { + } + else if (m_videoFrameFormat == render::RGB) + { m_imageframe = new image::rgb(m_VCodecCtx->width, m_VCodecCtx->height); } } - if (m_videoFrameFormat == render::NONE) { // NullGui? + if (m_videoFrameFormat == render::NONE) + { + // NullGui? return false; - } else if (m_videoFrameFormat == render::YUV && m_VCodecCtx->pix_fmt != PIX_FMT_YUV420P) { + } + else if (m_videoFrameFormat == render::YUV && m_VCodecCtx->pix_fmt != PIX_FMT_YUV420P) + { abort(); // TODO //img_convert((AVPicture*) pFrameYUV, PIX_FMT_YUV420P, (AVPicture*) pFrame, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height); // Don't use depreceted img_convert, use sws_scale - } else if (m_videoFrameFormat == render::RGB && m_VCodecCtx->pix_fmt != PIX_FMT_RGB24) { + } + else if (m_videoFrameFormat == render::RGB && m_VCodecCtx->pix_fmt != PIX_FMT_RGB24) + { buffer.reset(media::VideoDecoderFfmpeg::convertRGB24(m_VCodecCtx, m_Frame)); } raw_mediadata_t* video = new raw_mediadata_t; - if (m_videoFrameFormat == render::YUV) { + + if (m_videoFrameFormat == render::YUV) + { video->m_data = new uint8_t[static_cast<image::yuv*>(m_imageframe)->size()]; - } else if (m_videoFrameFormat == render::RGB) { + } + else if (m_videoFrameFormat == render::RGB) + { image::rgb* tmp = static_cast<image::rgb*>(m_imageframe); video->m_data = new uint8_t[m_imageframe->size()]; // tmp->m_pitch * tmp->m_height]; } @@ -898,7 +971,8 @@ m_last_video_timestamp += frame_delay; - if (m_videoFrameFormat == render::YUV) { + if (m_videoFrameFormat == render::YUV) + { image::yuv* yuvframe = static_cast<image::yuv*>(m_imageframe); int copied = 0; uint8_t* ptr = video->m_data; @@ -918,7 +992,9 @@ } } video->m_size = copied; - } else if (m_videoFrameFormat == render::RGB) { + } + else if (m_videoFrameFormat == render::RGB) + { uint8_t* srcptr = m_Frame->data[0]; uint8_t* srcend = m_Frame->data[0] + m_Frame->linesize[0] * m_VCodecCtx->height; @@ -958,8 +1034,7 @@ m_unqueued_data = m_qaudio.push(m_unqueued_data) ? NULL : m_unqueued_data; } } - else - if (m_unqueued_data->m_stream_index == m_video_index) + else if (m_unqueued_data->m_stream_index == m_video_index) { m_unqueued_data = m_qvideo.push(m_unqueued_data) ? NULL : m_unqueued_data; } @@ -1012,9 +1087,12 @@ // Seek to new position if (m_isFLV) { - if (m_parser.get()) { + if (m_parser.get()) + { newpos = m_parser->seek(pos); - } else { + } + else + { newpos = 0; } } @@ -1022,10 +1100,11 @@ { AVStream* videostream = m_FormatCtx->streams[m_video_index]; - timebase = static_cast<double>(videostream->time_base.num / videostream->time_base.den); + timebase = as_double(videostream->time_base); newpos = static_cast<long>(pos / timebase); - if (av_seek_frame(m_FormatCtx, m_video_index, newpos, 0) < 0) { + if (av_seek_frame(m_FormatCtx, m_video_index, newpos, 0) < 0) + { log_error(_("%s: seeking failed"), __FUNCTION__); return; } @@ -1107,9 +1186,12 @@ // Caclulate the current time uint32_t current_clock; - if (m_ACodecCtx && get_sound_handler()) { + if (m_ACodecCtx && get_sound_handler()) + { current_clock = m_current_timestamp; - } else { + } + else + { current_clock = tu_timer::get_ticks() - m_start_clock; m_current_timestamp = current_clock; } @@ -1121,10 +1203,13 @@ if (current_clock >= video_clock) { boost::mutex::scoped_lock lock(image_mutex); - if (m_videoFrameFormat == render::YUV) { + if (m_videoFrameFormat == render::YUV) + { // XXX m_imageframe might be a byte aligned buffer, while video is not! static_cast<image::yuv*>(m_imageframe)->update(video->m_data); - } else if (m_videoFrameFormat == render::RGB) { + } + else if (m_videoFrameFormat == render::RGB) + { image::rgb* imgframe = static_cast<image::rgb*>(m_imageframe); rgbcopy(imgframe, video, m_VCodecCtx->width * 3); @@ -1137,7 +1222,9 @@ // A frame is ready for pickup m_newFrameReady = true; - } else { + } + else + { // The timestamp on the first frame in the queue is greater // than the current time, so no need to do anything. return; @@ -1183,12 +1270,18 @@ NetStreamFfmpeg::time() { - if (m_FormatCtx && m_FormatCtx->nb_streams > 0) { - double time = (double)m_FormatCtx->streams[0]->time_base.num / (double)m_FormatCtx->streams[0]->time_base.den * (double)m_FormatCtx->streams[0]->cur_dts; + if (m_FormatCtx && m_FormatCtx->nb_streams > 0) + { + double time = as_double(m_FormatCtx->streams[0]->time_base) * (double)m_FormatCtx->streams[0]->cur_dts; return static_cast<int32_t>(time); - } else if (m_isFLV) { + } + else if + (m_isFLV) + { return m_current_timestamp; - } else { + } + else + { return 0; } } @@ -1214,9 +1307,12 @@ m_pause = false; - if (m_current_timestamp == 0) { + if (m_current_timestamp == 0) + { m_start_clock = tu_timer::get_ticks(); - } else { + } + else + { // Add the paused time to the start time so that the playhead doesn't // noticed that we have been paused m_start_clock += tu_timer::get_ticks() - m_time_of_pause; Index: server/asobj/NetStreamFfmpeg.h =================================================================== RCS file: /sources/gnash/gnash/server/asobj/NetStreamFfmpeg.h,v retrieving revision 1.52 retrieving revision 1.53 diff -u -b -r1.52 -r1.53 --- server/asobj/NetStreamFfmpeg.h 26 Nov 2007 21:53:59 -0000 1.52 +++ server/asobj/NetStreamFfmpeg.h 27 Nov 2007 08:45:33 -0000 1.53 @@ -15,7 +15,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -/* $Id: NetStreamFfmpeg.h,v 1.52 2007/11/26 21:53:59 strk Exp $ */ +/* $Id: NetStreamFfmpeg.h,v 1.53 2007/11/27 08:45:33 bwy Exp $ */ #ifndef __NETSTREAMFFMPEG_H__ #define __NETSTREAMFFMPEG_H__ @@ -289,7 +289,8 @@ /// A C++ wrapper around ffmpeg's AVPacket structure // /// Used in decodeVideo() and decodeAudio(). - /// Use PktPointer.get (as with auto_ptr) to access. + // + /// Use Pkt.get() to access. /// class AvPkt { _______________________________________________ Gnash-commit mailing list Gnash-commit@gnu.org http://lists.gnu.org/mailman/listinfo/gnash-commit