00001 #include <map>
00002 #include <iostream>
00003 using namespace std;
00004
00005 #include "mythcontext.h"
00006 #include "videoout_null.h"
00007 #include "videodisplayprofile.h"
00008
00009 const int kNumBuffers = 31;
00010 const int kNeedFreeFrames = 1;
00011 const int kPrebufferFramesNormal = 12;
00012 const int kPrebufferFramesSmall = 4;
00013 const int kKeepPrebuffer = 2;
00014
00015 VideoOutputNull::VideoOutputNull(void) :
00016 VideoOutput(), global_lock(true)
00017 {
00018 VERBOSE(VB_PLAYBACK, "VideoOutputNull()");
00019 memset(&av_pause_frame, 0, sizeof(av_pause_frame));
00020 }
00021
00022 VideoOutputNull::~VideoOutputNull()
00023 {
00024 VERBOSE(VB_PLAYBACK, "~VideoOutputNull()");
00025 QMutexLocker locker(&global_lock);
00026
00027 vbuffers.LockFrame(&av_pause_frame, "DeletePauseFrame");
00028 if (av_pause_frame.buf)
00029 {
00030 delete [] av_pause_frame.buf;
00031 memset(&av_pause_frame, 0, sizeof(av_pause_frame));
00032 }
00033 vbuffers.UnlockFrame(&av_pause_frame, "DeletePauseFrame");
00034
00035 vbuffers.DeleteBuffers();
00036 }
00037
00038
00039 void VideoOutputNull::Zoom(ZoomDirection direction)
00040 {
00041 QMutexLocker locker(&global_lock);
00042 VideoOutput::Zoom(direction);
00043 MoveResize();
00044 }
00045
00046 void VideoOutputNull::CreatePauseFrame(void)
00047 {
00048 vbuffers.LockFrame(&av_pause_frame, "CreatePauseFrame");
00049
00050 if (av_pause_frame.buf)
00051 {
00052 delete [] av_pause_frame.buf;
00053 av_pause_frame.buf = NULL;
00054 }
00055
00056 init(&av_pause_frame, FMT_YV12,
00057 new unsigned char[vbuffers.GetScratchFrame()->size + 128],
00058 vbuffers.GetScratchFrame()->width,
00059 vbuffers.GetScratchFrame()->height,
00060 vbuffers.GetScratchFrame()->bpp,
00061 vbuffers.GetScratchFrame()->size);
00062
00063 av_pause_frame.frameNumber = vbuffers.GetScratchFrame()->frameNumber;
00064
00065 clear(&av_pause_frame, GUID_I420_PLANAR);
00066
00067 vbuffers.UnlockFrame(&av_pause_frame, "CreatePauseFrame");
00068 }
00069
00070 bool VideoOutputNull::InputChanged(const QSize &input_size,
00071 float aspect,
00072 MythCodecID av_codec_id,
00073 void *codec_private)
00074 {
00075 VERBOSE(VB_PLAYBACK,
00076 QString("InputChanged(WxH = %1x%2, aspect = %3)")
00077 .arg(input_size.width())
00078 .arg(input_size.height()).arg(aspect));
00079
00080 QMutexLocker locker(&global_lock);
00081
00082 bool res_changed = input_size != video_disp_dim;
00083
00084 VideoOutput::InputChanged(input_size, aspect, av_codec_id, codec_private);
00085
00086 if (!res_changed)
00087 {
00088 vbuffers.Clear(GUID_I420_PLANAR);
00089 MoveResize();
00090 return true;
00091 }
00092
00093 vbuffers.DiscardFrames(true);
00094 vbuffers.DeleteBuffers();
00095
00096 MoveResize();
00097
00098 if (!vbuffers.CreateBuffers(video_dim.width(), video_dim.height()))
00099 {
00100 VERBOSE(VB_IMPORTANT, "VideoOutputNull::InputChanged(): "
00101 "Failed to recreate buffers");
00102 errored = true;
00103 }
00104 CreatePauseFrame();
00105
00106 db_vdisp_profile->SetVideoRenderer("null");
00107
00108 return true;
00109 }
00110
00111 int VideoOutputNull::GetRefreshRate(void)
00112 {
00113 return 0;
00114 }
00115
00116 bool VideoOutputNull::Init(int width, int height, float aspect,
00117 WId winid, int winx, int winy, int winw,
00118 int winh, WId embedid)
00119 {
00120 if ((width <= 0) || (height <= 0))
00121 return false;
00122
00123 QMutexLocker locker(&global_lock);
00124
00125 VideoOutput::Init(width, height, aspect, winid,
00126 winx, winy, winw, winh, embedid);
00127
00128 vbuffers.Init(kNumBuffers, true, kNeedFreeFrames,
00129 kPrebufferFramesNormal, kPrebufferFramesSmall,
00130 kKeepPrebuffer);
00131
00132 if (!vbuffers.CreateBuffers(video_dim.width(), video_dim.height()))
00133 return false;
00134
00135 CreatePauseFrame();
00136
00137 db_vdisp_profile->SetVideoRenderer("null");
00138
00139 MoveResize();
00140
00141 return true;
00142 }
00143
00144 void VideoOutputNull::EmbedInWidget(WId wid, int x, int y, int w, int h)
00145 {
00146 QMutexLocker locker(&global_lock);
00147 if (!embedding)
00148 VideoOutput::EmbedInWidget(wid, x, y, w, h);
00149 }
00150
00151 void VideoOutputNull::StopEmbedding(void)
00152 {
00153 QMutexLocker locker(&global_lock);
00154 if (embedding)
00155 VideoOutput::StopEmbedding();
00156 }
00157
00158 void VideoOutputNull::PrepareFrame(VideoFrame *buffer, FrameScanType t)
00159 {
00160 (void)t;
00161
00162 if (!buffer)
00163 buffer = vbuffers.GetScratchFrame();
00164
00165 vbuffers.LockFrame(buffer, "PrepareFrame");
00166 framesPlayed = buffer->frameNumber + 1;
00167 vbuffers.UnlockFrame(buffer, "PrepareFrame");
00168 }
00169
00170 void VideoOutputNull::Show(FrameScanType )
00171 {
00172 }
00173
00174 void VideoOutputNull::DrawUnusedRects(bool)
00175 {
00176 }
00177
00178 void VideoOutputNull::UpdatePauseFrame(void)
00179 {
00180 QMutexLocker locker(&global_lock);
00181
00182
00183 vbuffers.LockFrame(&av_pause_frame, "UpdatePauseFrame -- pause");
00184
00185 vbuffers.begin_lock(kVideoBuffer_used);
00186 VideoFrame *used_frame = NULL;
00187 if (vbuffers.size(kVideoBuffer_used) > 0)
00188 {
00189 used_frame = vbuffers.head(kVideoBuffer_used);
00190 if (!vbuffers.TryLockFrame(used_frame, "UpdatePauseFrame -- used"))
00191 used_frame = NULL;
00192 }
00193 if (used_frame)
00194 {
00195 CopyFrame(&av_pause_frame, used_frame);
00196 vbuffers.UnlockFrame(used_frame, "UpdatePauseFrame -- used");
00197 }
00198 vbuffers.end_lock();
00199
00200 if (!used_frame &&
00201 vbuffers.TryLockFrame(vbuffers.GetScratchFrame(),
00202 "UpdatePauseFrame -- scratch"))
00203 {
00204 vbuffers.GetScratchFrame()->frameNumber = framesPlayed - 1;
00205 CopyFrame(&av_pause_frame, vbuffers.GetScratchFrame());
00206 vbuffers.UnlockFrame(vbuffers.GetScratchFrame(),
00207 "UpdatePauseFrame -- scratch");
00208 }
00209 vbuffers.UnlockFrame(&av_pause_frame, "UpdatePauseFrame - used");
00210 }
00211
00212 void VideoOutputNull::ProcessFrame(VideoFrame *frame, OSD *osd,
00213 FilterChain *filterList,
00214 NuppelVideoPlayer *pipPlayer)
00215 {
00216 (void)frame;
00217 (void)osd;
00218 (void)filterList;
00219 (void)pipPlayer;
00220 }