00001 #include <map>
00002 #include <iostream>
00003 using namespace std;
00004
00005 #include "mythlogging.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 void VideoOutputNull::GetRenderOptions(render_opts &opts,
00016 QStringList &cpudeints)
00017 {
00018 opts.renderers->append("null");
00019 opts.deints->insert("null", cpudeints);
00020 (*opts.osds)["null"].append("softblend");
00021 (*opts.safe_renderers)["dummy"].append("null");
00022 (*opts.safe_renderers)["nuppel"].append("null");
00023 if (opts.decoders->contains("ffmpeg"))
00024 (*opts.safe_renderers)["ffmpeg"].append("null");
00025 if (opts.decoders->contains("crystalhd"))
00026 (*opts.safe_renderers)["crystalhd"].append("null");
00027
00028 opts.priorities->insert("null", 10);
00029 }
00030
00031 VideoOutputNull::VideoOutputNull() :
00032 VideoOutput(), global_lock(QMutex::Recursive)
00033 {
00034 LOG(VB_PLAYBACK, LOG_INFO, "VideoOutputNull()");
00035 memset(&av_pause_frame, 0, sizeof(av_pause_frame));
00036 }
00037
00038 VideoOutputNull::~VideoOutputNull()
00039 {
00040 LOG(VB_PLAYBACK, LOG_INFO, "~VideoOutputNull()");
00041 QMutexLocker locker(&global_lock);
00042
00043 if (av_pause_frame.buf)
00044 {
00045 delete [] av_pause_frame.buf;
00046 memset(&av_pause_frame, 0, sizeof(av_pause_frame));
00047 }
00048
00049 vbuffers.DeleteBuffers();
00050 }
00051
00052
00053 void VideoOutputNull::Zoom(ZoomDirection direction)
00054 {
00055 QMutexLocker locker(&global_lock);
00056 VideoOutput::Zoom(direction);
00057 MoveResize();
00058 }
00059
00060 void VideoOutputNull::CreatePauseFrame(void)
00061 {
00062 if (av_pause_frame.buf)
00063 {
00064 delete [] av_pause_frame.buf;
00065 av_pause_frame.buf = NULL;
00066 }
00067
00068 init(&av_pause_frame, FMT_YV12,
00069 new unsigned char[vbuffers.GetScratchFrame()->size + 128],
00070 vbuffers.GetScratchFrame()->width,
00071 vbuffers.GetScratchFrame()->height,
00072 vbuffers.GetScratchFrame()->size);
00073
00074 av_pause_frame.frameNumber = vbuffers.GetScratchFrame()->frameNumber;
00075
00076 clear(&av_pause_frame);
00077 }
00078
00079 bool VideoOutputNull::InputChanged(const QSize &input_size,
00080 float aspect,
00081 MythCodecID av_codec_id,
00082 void *codec_private,
00083 bool &aspect_only)
00084 {
00085 LOG(VB_PLAYBACK, LOG_INFO,
00086 QString("InputChanged(WxH = %1x%2, aspect = %3)")
00087 .arg(input_size.width())
00088 .arg(input_size.height()).arg(aspect));
00089
00090 if (!codec_is_std(av_codec_id))
00091 {
00092 LOG(VB_GENERAL, LOG_ERR, QString("VideoOutputNull::InputChanged(): "
00093 "new video codec is not supported."));
00094 errorState = kError_Unknown;
00095 return false;
00096 }
00097
00098 QMutexLocker locker(&global_lock);
00099
00100 if (input_size == window.GetActualVideoDim())
00101 {
00102 vbuffers.Clear();
00103 MoveResize();
00104 return true;
00105 }
00106
00107 VideoOutput::InputChanged(input_size, aspect, av_codec_id, codec_private,
00108 aspect_only);
00109 vbuffers.DeleteBuffers();
00110
00111 MoveResize();
00112
00113 const QSize video_dim = window.GetVideoDim();
00114
00115 bool ok = vbuffers.CreateBuffers(FMT_YV12, video_dim.width(),
00116 video_dim.height());
00117 if (!ok)
00118 {
00119 LOG(VB_GENERAL, LOG_ERR, "VideoOutputNull::InputChanged(): "
00120 "Failed to recreate buffers");
00121 errorState = kError_Unknown;
00122 }
00123 else
00124 {
00125 CreatePauseFrame();
00126 }
00127
00128 if (db_vdisp_profile)
00129 db_vdisp_profile->SetVideoRenderer("null");
00130
00131 return ok;
00132 }
00133
00134 bool VideoOutputNull::Init(int width, int height, float aspect, WId winid,
00135 const QRect &win_rect, MythCodecID codec_id)
00136 {
00137 if ((width <= 0) || (height <= 0))
00138 return false;
00139
00140 if (!codec_is_std(codec_id))
00141 {
00142 LOG(VB_GENERAL, LOG_ERR,
00143 QString("Cannot create VideoOutputNull for codec %1")
00144 .arg(toString(codec_id)));
00145 return false;
00146 }
00147
00148 QMutexLocker locker(&global_lock);
00149
00150 VideoOutput::Init(width, height, aspect, winid, win_rect, codec_id);
00151
00152 vbuffers.Init(kNumBuffers, true, kNeedFreeFrames,
00153 kPrebufferFramesNormal, kPrebufferFramesSmall,
00154 kKeepPrebuffer);
00155
00156 const QSize video_dim = window.GetVideoDim();
00157
00158 if (!vbuffers.CreateBuffers(FMT_YV12, video_dim.width(), video_dim.height()))
00159 return false;
00160
00161 CreatePauseFrame();
00162
00163 if (db_vdisp_profile)
00164 db_vdisp_profile->SetVideoRenderer("null");
00165
00166 MoveResize();
00167
00168 return true;
00169 }
00170
00171 void VideoOutputNull::EmbedInWidget(const QRect &rect)
00172 {
00173 QMutexLocker locker(&global_lock);
00174 if (!window.IsEmbedding())
00175 VideoOutput::EmbedInWidget(rect);
00176 }
00177
00178 void VideoOutputNull::StopEmbedding(void)
00179 {
00180 QMutexLocker locker(&global_lock);
00181 if (window.IsEmbedding())
00182 VideoOutput::StopEmbedding();
00183 }
00184
00185 void VideoOutputNull::PrepareFrame(VideoFrame *buffer, FrameScanType t,
00186 OSD *osd)
00187 {
00188 (void)osd;
00189 (void)t;
00190
00191 if (!buffer)
00192 buffer = vbuffers.GetScratchFrame();
00193
00194 framesPlayed = buffer->frameNumber + 1;
00195 }
00196
00197 void VideoOutputNull::Show(FrameScanType )
00198 {
00199 }
00200
00201 void VideoOutputNull::DrawUnusedRects(bool)
00202 {
00203 }
00204
00205 void VideoOutputNull::UpdatePauseFrame(int64_t &disp_timecode)
00206 {
00207 QMutexLocker locker(&global_lock);
00208
00209
00210 vbuffers.begin_lock(kVideoBuffer_used);
00211 VideoFrame *used_frame = NULL;
00212 if (vbuffers.size(kVideoBuffer_used) > 0)
00213 used_frame = vbuffers.head(kVideoBuffer_used);
00214
00215 if (used_frame)
00216 CopyFrame(&av_pause_frame, used_frame);
00217 vbuffers.end_lock();
00218
00219 if (!used_frame)
00220 {
00221 vbuffers.GetScratchFrame()->frameNumber = framesPlayed - 1;
00222 CopyFrame(&av_pause_frame, vbuffers.GetScratchFrame());
00223 }
00224
00225 disp_timecode = av_pause_frame.disp_timecode;
00226 }
00227
00228 void VideoOutputNull::ProcessFrame(VideoFrame *frame, OSD *osd,
00229 FilterChain *filterList,
00230 const PIPMap &pipPlayers,
00231 FrameScanType scan)
00232 {
00233 (void)frame;
00234 (void)osd;
00235 (void)filterList;
00236 (void)pipPlayers;
00237 (void)scan;
00238 }