00001
00002 #include <cstdio>
00003 #include <cstdlib>
00004 #include <cstring>
00005 #include <cmath>
00006 #include <ctime>
00007 #include <cerrno>
00008
00009
00010 #include <signal.h>
00011 #include <fcntl.h>
00012 #include <sys/time.h>
00013 #include <unistd.h>
00014 #include <sys/ipc.h>
00015 #include <sys/shm.h>
00016 #include <sys/ioctl.h>
00017 #include <sys/mman.h>
00018 #include <sys/poll.h>
00019 #include <sys/param.h>
00020
00021
00022 #include <linux/fb.h>
00023
00024
00025 #include <map>
00026 #include <iostream>
00027 using namespace std;
00028
00029 #include "videodev_myth.h"
00030 #include "videodev2_myth.h"
00031
00032 #include "videoout_ivtv.h"
00033 extern "C" {
00034 #include <inttypes.h>
00035 #include "ivtv_myth.h"
00036 }
00037
00038 #include "libmyth/mythcontext.h"
00039
00040 #include "NuppelVideoPlayer.h"
00041 extern "C" {
00042 #include "../libavcodec/avcodec.h"
00043 }
00044 #include "yuv2rgb.h"
00045 #include "osd.h"
00046 #include "osdsurface.h"
00047 #include "videodisplayprofile.h"
00048
00049 #define LOC QString("IVD: ")
00050 #define LOC_ERR QString("IVD Error: ")
00051
00052
00053
00054
00055
00056
00057 #define VIDEO_CMD_PLAY (0)
00058 #define VIDEO_CMD_STOP (1)
00059 #define VIDEO_CMD_FREEZE (2)
00060 #define VIDEO_CMD_CONTINUE (3)
00061
00062
00063 #define VIDEO_CMD_FREEZE_TO_BLACK (1 << 0)
00064
00065
00066 #define VIDEO_CMD_STOP_TO_BLACK (1 << 0)
00067 #define VIDEO_CMD_STOP_IMMEDIATELY (1 << 1)
00068
00069 #define VIDEO_GET_FRAME_COUNT _IOR('o', 58, __u64)
00070 #define VIDEO_COMMAND _IOWR('o', 59, struct video_command)
00071
00072
00073
00074 struct video_command {
00075 __u32 cmd;
00076 __u32 flags;
00077 union {
00078 struct {
00079 __u64 pts;
00080 } stop;
00081
00082 struct {
00083 __u32 speed;
00084 __u32 format;
00085 } play;
00086
00087 struct {
00088 __u32 data[16];
00089 } raw;
00090 };
00091 };
00092
00093 class VideoOutputIvtvPriv
00094 {
00095 public:
00096 VideoOutputIvtvPriv()
00097 {
00098 bzero(&ivtvfb_var, sizeof(ivtvfb_var));
00099 bzero(&ivtvfb_var_old, sizeof(ivtvfb_var_old));
00100 }
00101
00102 struct fb_var_screeninfo ivtvfb_var;
00103 struct fb_var_screeninfo ivtvfb_var_old;
00104 };
00105
00106
00107
00108
00109
00110
00111 #define IVTVFB_IOC_DMA_FRAME _IOW ('V', BASE_VIDIOC_PRIVATE+0, struct ivtvfb_ioctl_dma_host_to_ivtv_args)
00112
00117 VideoOutputIvtv::VideoOutputIvtv(void) :
00118 videofd(-1), fbfd(-1),
00119 fps(30000.0f/1001.0f), videoDevice("/dev/video16"),
00120 driver_version(0),
00121 has_v4l2_api(false), has_pause_bug(false),
00122
00123 mapped_offset(0), mapped_memlen(0),
00124 mapped_mem(NULL), pixels(NULL),
00125
00126 stride(0),
00127
00128 lastcleared(false), pipon(false),
00129 osdon(false),
00130 osdbuffer(NULL), osdbuf_aligned(NULL),
00131 osdbufsize(0), osdbuf_revision(0xfffffff),
00132
00133 last_speed(1.0f),
00134 internal_offset(0), frame_at_speed_change(0),
00135
00136 last_normal(true), last_mask(0x2),
00137
00138 alphaState(kAlpha_Solid), old_fb_ioctl(true),
00139 fb_dma_ioctl(IVTVFB_IOCTL_PREP_FRAME),
00140 color_key(false), decoder_flush(true),
00141 paused(false)
00142 {
00143 priv = new VideoOutputIvtvPriv();
00144 }
00145
00146 VideoOutputIvtv::~VideoOutputIvtv()
00147 {
00148 Close();
00149
00150 if (osdbuffer)
00151 {
00152 delete [] osdbuffer;
00153 osdbuffer = NULL;
00154 }
00155
00156 if (priv)
00157 {
00158 delete priv;
00159 priv = NULL;
00160 }
00161 }
00162
00163 void VideoOutputIvtv::ClearOSD(void)
00164 {
00165 if (fbfd < 0)
00166 {
00167 VERBOSE(VB_IMPORTANT, LOC_ERR + "ClearOSD() -- no framebuffer!");
00168 return;
00169 }
00170
00171 VERBOSE(VB_PLAYBACK, LOC + "ClearOSD");
00172
00173 struct ivtvfb_ioctl_dma_host_to_ivtv_args prep;
00174 bzero(&prep, sizeof(prep));
00175
00176 bzero(osdbuf_aligned, osdbufsize);
00177 prep.source = osdbuf_aligned;
00178 prep.dest_offset = 0;
00179
00180 if (old_fb_ioctl)
00181 {
00182 struct ivtv_osd_coords osdcoords;
00183 bzero(&osdcoords, sizeof(osdcoords));
00184
00185 if (ioctl(fbfd, IVTVFB_IOCTL_GET_ACTIVE_BUFFER, &osdcoords) < 0)
00186 {
00187 VERBOSE(VB_IMPORTANT, LOC_ERR +
00188 "Failed to get active buffer for ClearOSD()" + ENO);
00189 return;
00190 }
00191 prep.count = osdcoords.max_offset;
00192 }
00193 else
00194 {
00195 prep.count = priv->ivtvfb_var.xres_virtual *
00196 priv->ivtvfb_var.yres * (priv->ivtvfb_var.bits_per_pixel / 8);
00197 }
00198
00199 if (!old_fb_ioctl)
00200 ioctl(fbfd, FBIOPAN_DISPLAY, &priv->ivtvfb_var);
00201
00202 int ret = ioctl(fbfd, fb_dma_ioctl, &prep);
00203 if (ret < 0)
00204 {
00205 if (errno == EINVAL && fb_dma_ioctl != IVTVFB_IOC_DMA_FRAME)
00206 {
00207 fb_dma_ioctl = IVTVFB_IOC_DMA_FRAME;
00208 ret = ioctl(fbfd, fb_dma_ioctl, &prep);
00209 }
00210 if (ret < 0)
00211 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to prepare frame" + ENO);
00212 }
00213 }
00214
00215 void VideoOutputIvtv::SetColorKey(int state, int color)
00216 {
00217 if (has_v4l2_api)
00218 {
00219 struct v4l2_format alpha_state;
00220 struct v4l2_framebuffer framebuffer_state;
00221
00222 ioctl(videofd, VIDIOC_G_FBUF, &framebuffer_state);
00223 alpha_state.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY;
00224 ioctl(videofd, VIDIOC_G_FMT, &alpha_state);
00225
00226 if (state)
00227 {
00228 framebuffer_state.flags |= V4L2_FBUF_FLAG_CHROMAKEY;
00229 alpha_state.fmt.win.chromakey = color;
00230 }
00231 else
00232 {
00233 framebuffer_state.flags &= ~V4L2_FBUF_FLAG_CHROMAKEY;
00234 }
00235
00236 ioctl(videofd, VIDIOC_S_FBUF, &framebuffer_state);
00237 ioctl(videofd, VIDIOC_S_FMT, &alpha_state);
00238 }
00239 else if (color_key)
00240 {
00241 struct ivtvfb_ioctl_colorkey ivtvfb_colorkey;
00242
00243 ivtvfb_colorkey.state = state;
00244 ivtvfb_colorkey.colorKey = color;
00245 ioctl(fbfd,IVTVFB_IOCTL_SET_COLORKEY, &ivtvfb_colorkey);
00246 }
00247 }
00248
00249 void VideoOutputIvtv::SetAlpha(eAlphaState newAlphaState)
00250 {
00251 if (alphaState == newAlphaState)
00252 return;
00253
00254 #if 0
00255 if (newAlphaState == kAlpha_Local)
00256 VERBOSE(VB_PLAYBACK, LOC + "SetAlpha(Local)");
00257 if (newAlphaState == kAlpha_Clear)
00258 VERBOSE(VB_PLAYBACK, LOC + "SetAlpha(Clear)");
00259 if (newAlphaState == kAlpha_Solid)
00260 VERBOSE(VB_PLAYBACK, LOC + "SetAlpha(Solid)");
00261 if (newAlphaState == kAlpha_Embedded)
00262 VERBOSE(VB_PLAYBACK, LOC + "SetAlpha(Embedded)");
00263 #endif
00264
00265 struct ivtvfb_ioctl_state_info fbstate;
00266 bzero(&fbstate, sizeof(fbstate));
00267
00268 if (has_v4l2_api)
00269 {
00270 struct v4l2_format alpha_state;
00271 struct v4l2_framebuffer framebuffer_state;
00272
00273 ioctl(videofd, VIDIOC_G_FBUF, &framebuffer_state);
00274 alpha_state.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY;
00275 ioctl(videofd, VIDIOC_G_FMT, &alpha_state);
00276
00277 if (newAlphaState == kAlpha_Local)
00278 {
00279 framebuffer_state.flags &= ~V4L2_FBUF_FLAG_GLOBAL_ALPHA;
00280 framebuffer_state.flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
00281 }
00282 else
00283 {
00284 framebuffer_state.flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA;
00285 framebuffer_state.flags &= ~V4L2_FBUF_FLAG_LOCAL_ALPHA;
00286 }
00287
00288 if (newAlphaState == kAlpha_Solid)
00289 alpha_state.fmt.win.global_alpha = 255;
00290 else if (newAlphaState == kAlpha_Clear)
00291 alpha_state.fmt.win.global_alpha = 0;
00292 else if (newAlphaState == kAlpha_Embedded)
00293 alpha_state.fmt.win.global_alpha =
00294 gContext->GetNumSetting("PVR350EPGAlphaValue", 164);
00295
00296 if (ioctl(videofd, VIDIOC_S_FBUF, &framebuffer_state) < 0)
00297 VERBOSE(VB_IMPORTANT, LOC_ERR +
00298 "Failed to set ivtv alpha mode" + ENO);
00299 if (ioctl(videofd, VIDIOC_S_FMT, &alpha_state) < 0)
00300 VERBOSE(VB_IMPORTANT, LOC_ERR +
00301 "Failed to set ivtv alpha values." + ENO);
00302 }
00303 else
00304 {
00305 if (ioctl(fbfd, IVTVFB_IOCTL_GET_STATE, &fbstate) < 0)
00306 {
00307 VERBOSE(VB_IMPORTANT,
00308 LOC_ERR + "Failed to query alpha state" + ENO);
00309 }
00310
00311 if (newAlphaState == kAlpha_Local)
00312 {
00313 fbstate.status &= ~IVTVFB_STATUS_GLOBAL_ALPHA;
00314 fbstate.status |= IVTVFB_STATUS_LOCAL_ALPHA;
00315 }
00316 else
00317 {
00318 fbstate.status |= IVTVFB_STATUS_GLOBAL_ALPHA;
00319 fbstate.status &= ~IVTVFB_STATUS_LOCAL_ALPHA;
00320 }
00321
00322 if (newAlphaState == kAlpha_Solid)
00323 fbstate.alpha = 255;
00324 else if (newAlphaState == kAlpha_Clear)
00325 fbstate.alpha = 0;
00326 else if (newAlphaState == kAlpha_Embedded)
00327 fbstate.alpha =
00328 gContext->GetNumSetting("PVR350EPGAlphaValue", 164);
00329
00330 if (ioctl(fbfd, IVTVFB_IOCTL_SET_STATE, &fbstate) < 0)
00331 {
00332 VERBOSE(VB_IMPORTANT, LOC_ERR +
00333 "Failed to set ivtv alpha state." + ENO);
00334 }
00335 }
00336
00337
00338 if (!old_fb_ioctl)
00339 {
00340 struct fb_var_screeninfo *tmpfb_var = NULL;
00341
00342 if (newAlphaState == kAlpha_Embedded)
00343 {
00344
00345 tmpfb_var = &priv->ivtvfb_var_old;
00346 }
00347 else if (newAlphaState != kAlpha_Embedded &&
00348 alphaState == kAlpha_Embedded)
00349 {
00350
00351 tmpfb_var = &priv->ivtvfb_var;
00352 }
00353
00354
00355 if (tmpfb_var)
00356 {
00357 if ((priv->ivtvfb_var_old.bits_per_pixel != 32) &&
00358 (priv->ivtvfb_var_old.bits_per_pixel != 8))
00359 {
00360
00361 ioctl(fbfd, FBIOBLANK, VESA_VSYNC_SUSPEND);
00362 tmpfb_var->activate = FB_ACTIVATE_NOW;
00363 if (ioctl(fbfd, FBIOPUT_VSCREENINFO, tmpfb_var) < 0)
00364 {
00365 VERBOSE(VB_IMPORTANT, LOC_ERR +
00366 "Failed to switch framebuffer "
00367 "settings for EPG" + ENO);
00368 }
00369
00370
00371 ioctl(fbfd, FBIOBLANK, VESA_NO_BLANKING);
00372 }
00373
00374
00375 priv->ivtvfb_var.xoffset = 0;
00376 priv->ivtvfb_var.yoffset = 0;
00377 ioctl(fbfd, FBIOPAN_DISPLAY, &priv->ivtvfb_var);
00378 }
00379 }
00380
00381 alphaState = newAlphaState;
00382 }
00383
00384 bool VideoOutputIvtv::InputChanged(const QSize &input_size,
00385 float aspect,
00386 MythCodecID av_codec_id,
00387 void *codec_private)
00388 {
00389 VERBOSE(VB_PLAYBACK, LOC + "InputChanged() -- begin");
00390 VideoOutput::InputChanged(input_size, aspect, av_codec_id, codec_private);
00391 MoveResize();
00392 VERBOSE(VB_PLAYBACK, LOC + "InputChanged() -- end");
00393 return true;
00394 }
00395
00396 int VideoOutputIvtv::GetRefreshRate(void)
00397 {
00398 return 0;
00399 }
00400
00401 int VideoOutputIvtv::ValidVideoFrames(void) const
00402 {
00403 return 131;
00404 }
00405
00406 bool VideoOutputIvtv::Init(int width, int height, float aspect,
00407 WId winid, int winx, int winy, int winw,
00408 int winh, WId embedid)
00409 {
00410 VERBOSE(VB_PLAYBACK, LOC + "Init() -- begin");
00411
00412 db_vdisp_profile->SetVideoRenderer("ivtv");
00413
00414 allowpreviewepg = true;
00415
00416 videoDevice = gContext->GetSetting("PVR350VideoDev");
00417
00418 VideoOutput::Init(width, height, aspect, winid, winx, winy, winw, winh,
00419 embedid);
00420
00421 osdbufsize = video_dim.width() * video_dim.height() * 4;
00422
00423 MoveResize();
00424
00425 Open();
00426
00427 if (videofd < 0)
00428 return false;
00429
00430 if (fbfd < 0)
00431 {
00432 int fbno = 0;
00433
00434 if (has_v4l2_api)
00435 {
00436 struct v4l2_framebuffer fbuf;
00437
00438 ioctl(videofd, VIDIOC_G_FBUF, &fbuf);
00439 for (fbno = 0; fbno < 10; fbno++)
00440 {
00441 struct fb_fix_screeninfo si;
00442 char buf[10];
00443
00444 sprintf(buf, "/dev/fb%d", fbno);
00445 fbfd = open(buf, O_RDWR);
00446 if (fbfd < 0)
00447 continue;
00448 ioctl(fbfd, FBIOGET_FSCREENINFO, &si);
00449 if (si.smem_start == (unsigned long)fbuf.base)
00450 break;
00451 close(fbfd);
00452 fbfd = -1;
00453 }
00454 if (fbfd < 0)
00455 {
00456 VERBOSE(VB_IMPORTANT, LOC_ERR +
00457 "Failed to locate framebuffer" +
00458 "\n\t\t\tDid you load the ivtv-fb "
00459 "Linux kernel module?");
00460 return false;
00461 }
00462 }
00463 else
00464 {
00465 if (ioctl(videofd, IVTV_IOC_GET_FB, &fbno) < 0)
00466 {
00467 VERBOSE(VB_IMPORTANT, LOC_ERR +
00468 "Framebuffer number query failed." + ENO +
00469 "\n\t\t\tDid you load the ivtv-fb "
00470 "Linux kernel module?");
00471 return false;
00472 }
00473
00474 if (fbno < 0)
00475 {
00476 VERBOSE(VB_IMPORTANT, LOC_ERR +
00477 "Failed to determine framebuffer number." +
00478 "\n\t\t\tDid you load the ivtv-fb "
00479 "Linux kernel module?");
00480 return false;
00481 }
00482
00483 QString fbdev = QString("/dev/fb%1").arg(fbno);
00484 fbfd = open(fbdev.ascii(), O_RDWR);
00485
00486 if (fbfd < 0)
00487 {
00488 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to open framebuffer " +
00489 QString("'%1'").arg(fbdev) + ENO +
00490 "\n\t\t\tThis is needed for the OSD.");
00491 return false;
00492 }
00493 }
00494
00495 struct ivtvfb_ioctl_get_frame_buffer igfb;
00496 bzero(&igfb, sizeof(igfb));
00497
00498 if (ioctl(fbfd, IVTVFB_IOCTL_GET_FRAME_BUFFER, &igfb) < 0)
00499 {
00500 if (errno == EINVAL)
00501 {
00502 struct fb_fix_screeninfo ivtvfb_fix;
00503 if (ioctl(fbfd, FBIOGET_FSCREENINFO, &ivtvfb_fix) < 0)
00504 {
00505 VERBOSE(VB_IMPORTANT, LOC_ERR +
00506 "Getting frame buffer" + ENO);
00507 }
00508 else
00509 {
00510 old_fb_ioctl = false;
00511 ioctl(fbfd, FBIOGET_VSCREENINFO, &priv->ivtvfb_var_old);
00512 }
00513 }
00514 else
00515 {
00516 VERBOSE(VB_IMPORTANT, LOC_ERR + "Getting frame buffer" + ENO);
00517 }
00518 }
00519
00520 long pagesize = sysconf(_SC_PAGE_SIZE);
00521 long pagemask = ~(pagesize-1);
00522 osdbuffer = new char[osdbufsize + pagesize];
00523 osdbuf_aligned = osdbuffer + (pagesize - 1);
00524 osdbuf_aligned = (char*) ((unsigned long)osdbuf_aligned & pagemask);
00525
00526 bzero(osdbuf_aligned, osdbufsize);
00527
00528 if (old_fb_ioctl)
00529 {
00530 struct ivtv_osd_coords osdcoords;
00531 stride = igfb.sizex * 4;
00532 bzero(&osdcoords, sizeof(osdcoords));
00533 osdcoords.lines = video_dim.height();
00534 osdcoords.offset = 0;
00535 osdcoords.pixel_stride = video_dim.width() * 2;
00536 if (ioctl(fbfd, IVTVFB_IOCTL_SET_ACTIVE_BUFFER, &osdcoords) < 0)
00537 VERBOSE(VB_IMPORTANT, LOC_ERR + "Setting active buffer" + ENO);
00538 }
00539 else
00540 {
00541 bzero (&priv->ivtvfb_var, sizeof(priv->ivtvfb_var));
00542
00543
00544 video_dim = QSize(priv->ivtvfb_var_old.xres,
00545 priv->ivtvfb_var_old.yres);
00546
00547 memcpy(&priv->ivtvfb_var, &priv->ivtvfb_var_old,
00548 sizeof priv->ivtvfb_var);
00549
00550
00551 if (priv->ivtvfb_var_old.bits_per_pixel != 32)
00552 {
00553 priv->ivtvfb_var.xres_virtual = priv->ivtvfb_var.xres;
00554 priv->ivtvfb_var.yres_virtual = priv->ivtvfb_var.yres;
00555 priv->ivtvfb_var.xoffset = 0;
00556 priv->ivtvfb_var.yoffset = 0;
00557 priv->ivtvfb_var.bits_per_pixel = 32;
00558 priv->ivtvfb_var.nonstd = 0;
00559 priv->ivtvfb_var.activate = FB_ACTIVATE_NOW;
00560
00561 if (ioctl(fbfd, FBIOPUT_VSCREENINFO, &priv->ivtvfb_var) < 0)
00562 {
00563 VERBOSE(VB_IMPORTANT, LOC_ERR +
00564 "Setting frame buffer" + ENO);
00565 }
00566 }
00567 else
00568 {
00569 priv->ivtvfb_var.xoffset = 0;
00570 priv->ivtvfb_var.yoffset = 0;
00571 ioctl(fbfd, FBIOPAN_DISPLAY, &priv->ivtvfb_var);
00572 }
00573
00574 stride = priv->ivtvfb_var.xres_virtual * 4;
00575 }
00576
00577
00578 SetColorKey (1, 0x00010001);
00579
00580 ClearOSD();
00581
00582 SetAlpha(kAlpha_Clear);
00583 }
00584
00585 VERBOSE(VB_GENERAL, "Using the PVR-350 decoder/TV-out");
00586
00587 VERBOSE(VB_PLAYBACK, LOC + "Init() -- end");
00588 return true;
00589 }
00590
00594 void VideoOutputIvtv::Close(void)
00595 {
00596 VERBOSE(VB_PLAYBACK, LOC + "Close() -- begin");
00597
00598 if (fbfd >= 0)
00599 {
00600 ClearOSD();
00601 SetAlpha(kAlpha_Solid);
00602 SetColorKey (0,0);
00603
00604 if (!old_fb_ioctl)
00605 {
00606 priv->ivtvfb_var_old.activate = FB_ACTIVATE_NOW;
00607
00608 if (ioctl(fbfd, FBIOPUT_VSCREENINFO, &priv->ivtvfb_var_old) < 0)
00609 {
00610 VERBOSE(VB_IMPORTANT, LOC_ERR +
00611 "Failed to restore framebuffer settings" + ENO);
00612 }
00613 }
00614
00615 close (fbfd);
00616 fbfd = -1;
00617 }
00618
00619 if (videofd >= 0)
00620 {
00621 Stop(true );
00622
00623 close(videofd);
00624 videofd = -1;
00625 }
00626 VERBOSE(VB_PLAYBACK, LOC + "Close() -- end");
00627 }
00628
00632 void VideoOutputIvtv::Open(void)
00633 {
00634 VERBOSE(VB_PLAYBACK, LOC + "Open() -- begin");
00635 if (videofd >= 0)
00636 {
00637 VERBOSE(VB_PLAYBACK, LOC + "Open() -- end");
00638 return;
00639 }
00640
00641 videofd = open(videoDevice.ascii(), O_WRONLY | O_NONBLOCK, 0555);
00642 if (videofd < 0)
00643 {
00644 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to open decoder device " +
00645 QString("'%1'").arg(videoDevice) + ENO);
00646 VERBOSE(VB_PLAYBACK, LOC + "Open() -- end");
00647 return;
00648 }
00649
00650 struct v4l2_capability vcap;
00651 bzero(&vcap, sizeof(vcap));
00652 if (ioctl(videofd, VIDIOC_QUERYCAP, &vcap) < 0)
00653 {
00654 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to query decoder" + ENO);
00655 }
00656 else
00657 {
00658 driver_version = vcap.version;
00659 if (driver_version >= 0x000306)
00660 color_key = true;
00661 if (driver_version >= 0x000A00)
00662 decoder_flush = false;
00663 has_v4l2_api = (driver_version >= 0x010000);
00664 has_pause_bug = (driver_version == 0x010000);
00665
00666 VERBOSE(VB_GENERAL, LOC + QString("ivtv version %1.%2.%3")
00667 .arg(driver_version >> 16)
00668 .arg((driver_version >> 8) & 0xFF)
00669 .arg(driver_version & 0xFF));
00670 }
00671 VERBOSE(VB_PLAYBACK, LOC + "Open() -- end");
00672 }
00673
00674 void VideoOutputIvtv::PrepareFrame(VideoFrame *buffer, FrameScanType t)
00675 {
00676 (void)buffer;
00677 (void)t;
00678 }
00679
00680 void VideoOutputIvtv::Show(FrameScanType)
00681 {
00682 }
00683
00684 void VideoOutputIvtv::DrawUnusedRects(bool)
00685 {
00686 }
00687
00688 void VideoOutputIvtv::UpdatePauseFrame(void)
00689 {
00690 }
00691
00692 void VideoOutputIvtv::ShowPip(VideoFrame *frame, NuppelVideoPlayer *pipplayer)
00693 {
00694 if (!pipplayer)
00695 return;
00696
00697 int pipw, piph;
00698
00699 VideoFrame *pipimage = pipplayer->GetCurrentFrame(pipw, piph);
00700
00701 if (!pipimage || !pipimage->buf || pipimage->codec != FMT_YV12)
00702 {
00703 pipplayer->ReleaseCurrentFrame(pipimage);
00704 return;
00705 }
00706
00707 int xoff;
00708 int yoff;
00709
00710 unsigned char *pipbuf = pipimage->buf;
00711
00712 if (pipw != pip_desired_display_size.width() ||
00713 piph != pip_desired_display_size.height())
00714 {
00715 DoPipResize(pipw, piph);
00716
00717 if (pip_tmp_buf && pip_scaling_context)
00718 {
00719 AVPicture img_in, img_out;
00720
00721 avpicture_fill(
00722 &img_out, (uint8_t*) pip_tmp_buf, PIX_FMT_YUV420P,
00723 pip_display_size.width(), pip_display_size.height());
00724
00725 avpicture_fill(&img_in, (uint8_t*) pipimage->buf, PIX_FMT_YUV420P,
00726 pipw, piph);
00727
00728 img_resample(pip_scaling_context, &img_out, &img_in);
00729
00730 pipw = pip_display_size.width();
00731 piph = pip_display_size.height();
00732
00733 pipbuf = pip_tmp_buf;
00734 }
00735 }
00736
00737 switch (db_pip_location)
00738 {
00739 case kPIP_END:
00740 case kPIPTopLeft:
00741 xoff = 50;
00742 yoff = 40;
00743 break;
00744 case kPIPBottomLeft:
00745 xoff = 50;
00746 yoff = frame->height - piph - 40;
00747 break;
00748 case kPIPTopRight:
00749 xoff = frame->width - pipw - 50;
00750 yoff = 40;
00751 break;
00752 case kPIPBottomRight:
00753 xoff = frame->width - pipw - 50;
00754 yoff = frame->height - piph - 40;
00755 break;
00756 }
00757
00758 unsigned char *outputbuf = new unsigned char[pipw * piph * 4];
00759 yuv2rgb_fun convert = yuv2rgb_init_mmx(32, MODE_RGB);
00760
00761 convert(outputbuf, pipbuf, pipbuf + (pipw * piph),
00762 pipbuf + (pipw * piph * 5 / 4), pipw, piph,
00763 pipw * 4, pipw, pipw / 2, 1);
00764
00765 pipplayer->ReleaseCurrentFrame(pipimage);
00766
00767 if (frame->width < 0)
00768 frame->width = video_dim.width();
00769
00770 for (int i = 0; i < piph; i++)
00771 {
00772 memcpy(frame->buf + (i + yoff) * frame->width + xoff * 4,
00773 outputbuf + i * pipw * 4, pipw * 4);
00774 }
00775
00776 delete [] outputbuf;
00777 }
00778
00779 void VideoOutputIvtv::ProcessFrame(VideoFrame *frame, OSD *osd,
00780 FilterChain *filterList,
00781 NuppelVideoPlayer *pipPlayer)
00782 {
00783 (void)filterList;
00784 (void)frame;
00785
00786 if (fbfd < 0)
00787 return;
00788
00789 if (!osd && !pipon)
00790 return;
00791
00792 if (embedding && alphaState != kAlpha_Embedded)
00793 SetAlpha(kAlpha_Embedded);
00794 else if (!embedding && alphaState == kAlpha_Embedded && lastcleared)
00795 SetAlpha(kAlpha_Clear);
00796
00797 if (embedding)
00798 return;
00799
00800 VideoFrame tmpframe;
00801 init(&tmpframe, FMT_ARGB32, (unsigned char*) osdbuf_aligned,
00802 stride, video_dim.height(), 32, stride * video_dim.height());
00803
00804 OSDSurface *surface = NULL;
00805 if (osd)
00806 surface = osd->Display();
00807
00808
00809 bool clear = (pipPlayer!=0) ^ pipon;
00810 int new_revision = osdbuf_revision;
00811 if (surface)
00812 {
00813 new_revision = surface->GetRevision();
00814 clear |= surface->GetRevision() != osdbuf_revision;
00815 }
00816
00817 bool drawanyway = false;
00818 if (clear)
00819 {
00820 bzero(tmpframe.buf, video_dim.height() * stride);
00821 drawanyway = true;
00822 }
00823
00824 if (pipPlayer)
00825 {
00826 ShowPip(&tmpframe, pipPlayer);
00827 osdbuf_revision = 0xfffffff;
00828 lastcleared = false;
00829 drawanyway = true;
00830 }
00831
00832 int ret = 0;
00833 ret = DisplayOSD(&tmpframe, osd, stride, osdbuf_revision);
00834 osdbuf_revision = new_revision;
00835
00836
00837
00838
00839 if (ret < 0 && osdon)
00840 {
00841 if (!clear || pipon)
00842 {
00843 bzero(tmpframe.buf, video_dim.height() * stride);
00844
00845 if (pipPlayer)
00846 ShowPip(&tmpframe, pipPlayer);
00847 }
00848 drawanyway |= !lastcleared || pipon;
00849 lastcleared &= !pipon;
00850 }
00851
00852
00853 osdon = (ret >= 0);
00854 pipon = (bool) pipPlayer;
00855
00856
00857 lastcleared &= !osdon;
00858
00859
00860 if (!osdon && !pipon)
00861 {
00862 if (lastcleared)
00863 return;
00864
00865 lastcleared = true;
00866 SetAlpha(kAlpha_Clear);
00867
00868 if (color_key)
00869 #ifdef WORDS_BIGENDIAN
00870 wmemset((wchar_t*) osdbuf_aligned, 0x01000100, osdbufsize/4);
00871 #else
00872 wmemset((wchar_t*) osdbuf_aligned, 0x00010001, osdbufsize/4);
00873 #endif
00874 }
00875
00876
00877 if (ret <= 0 && !drawanyway)
00878 return;
00879
00880
00881 struct ivtvfb_ioctl_dma_host_to_ivtv_args prep;
00882 bzero(&prep, sizeof(prep));
00883 prep.source = osdbuf_aligned;
00884 prep.count = video_dim.height() * stride;
00885
00886
00887 #ifdef WORDS_BIGENDIAN
00888 int b_index, i_index;
00889 unsigned int *osd_int = (unsigned int*) osdbuf_aligned;
00890 if (!lastcleared)
00891 {
00892 for (b_index = 0, i_index = 0; b_index < prep.count;
00893 b_index += 4, i_index ++)
00894 {
00895 if (osd_int[i_index])
00896 {
00897 osd_int[i_index] =
00898 ((unsigned char)osdbuf_aligned[b_index+0]) |
00899 ((unsigned char)osdbuf_aligned[b_index+1] << 8) |
00900 ((unsigned char)osdbuf_aligned[b_index+2] << 16) |
00901 ((unsigned char)osdbuf_aligned[b_index+3] << 24);
00902 }
00903 }
00904 }
00905 #endif
00906
00907 if (!old_fb_ioctl)
00908 ioctl(fbfd, FBIOPAN_DISPLAY, &priv->ivtvfb_var);
00909
00910 if (ioctl(fbfd, fb_dma_ioctl, &prep) < 0)
00911 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to process frame" + ENO);
00912
00913 if (!lastcleared)
00914 SetAlpha(kAlpha_Local);
00915 }
00916
00922 void VideoOutputIvtv::Start(int skip, int mute)
00923 {
00924 VERBOSE(VB_PLAYBACK, LOC + "Start("<<skip<<" skipped, "
00925 <<mute<<" muted) -- begin");
00926 struct ivtv_cfg_start_decode start;
00927 bzero(&start, sizeof(start));
00928 start.gop_offset = skip;
00929 start.muted_audio_frames = mute;
00930
00931 if (has_v4l2_api)
00932 {
00933 struct video_command cmd;
00934 memset(&cmd, 0, sizeof(cmd));
00935 cmd.cmd = VIDEO_CMD_PLAY;
00936 cmd.play.speed = 1000;
00937 ioctl(videofd, VIDEO_COMMAND, &cmd);
00938 paused = false;
00939 }
00940 else
00941 {
00942 while (ioctl(videofd, IVTV_IOC_START_DECODE, &start) < 0)
00943 {
00944 if (errno != EBUSY)
00945 {
00946 VERBOSE(VB_IMPORTANT, LOC_ERR +
00947 "Failed to start decoder" + ENO);
00948 break;
00949 }
00950 }
00951 }
00952 VERBOSE(VB_PLAYBACK, LOC + "Start("<<skip<<" skipped, "
00953 <<mute<<" muted) -- end");
00954 }
00955
00960 void VideoOutputIvtv::Stop(bool hide)
00961 {
00962 VERBOSE(VB_PLAYBACK, LOC + "Stop("<<hide<<") -- begin");
00963 struct ivtv_cfg_stop_decode stop;
00964 bzero(&stop, sizeof(stop));
00965 stop.hide_last = hide;
00966
00967 if (has_v4l2_api)
00968 {
00969 struct video_command cmd;
00970 memset(&cmd, 0, sizeof(cmd));
00971 cmd.cmd = VIDEO_CMD_STOP;
00972 cmd.flags = VIDEO_CMD_STOP_IMMEDIATELY;
00973 if (hide)
00974 cmd.flags |= VIDEO_CMD_STOP_TO_BLACK;
00975 if (ioctl(videofd, VIDEO_COMMAND, &cmd) < 0)
00976 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to stop decoder" + ENO);
00977 }
00978 else
00979 {
00980 while (ioctl(videofd, IVTV_IOC_STOP_DECODE, &stop) < 0)
00981 {
00982 if (errno != EBUSY)
00983 {
00984 VERBOSE(VB_IMPORTANT, LOC_ERR +
00985 "Failed to stop decoder" + ENO);
00986 break;
00987 }
00988 }
00989 }
00990
00991 frame_at_speed_change = 0;
00992 internal_offset = 0;
00993 VERBOSE(VB_PLAYBACK, LOC + "Stop("<<hide<<") -- end");
00994 }
00995
00999 void VideoOutputIvtv::Pause(void)
01000 {
01001 VERBOSE(VB_PLAYBACK, LOC + "Pause() -- begin");
01002 if (has_v4l2_api)
01003 {
01004 struct video_command cmd;
01005 memset(&cmd, 0, sizeof(cmd));
01006 cmd.cmd = VIDEO_CMD_FREEZE;
01007 ioctl(videofd, VIDEO_COMMAND, &cmd);
01008 paused = true;
01009 }
01010 else
01011 {
01012 while (ioctl(videofd, IVTV_IOC_PAUSE, 0) < 0)
01013 {
01014 if (errno != EBUSY)
01015 {
01016 VERBOSE(VB_IMPORTANT, LOC_ERR +
01017 "Failed to pause decoder" + ENO);
01018 break;
01019 }
01020 }
01021 }
01022 VERBOSE(VB_PLAYBACK, LOC + "Pause() -- end");
01023 }
01024
01030 int VideoOutputIvtv::Poll(int delay)
01031 {
01032
01033 struct pollfd polls;
01034 polls.fd = videofd;
01035 polls.events = POLLOUT;
01036 polls.revents = 0;
01037
01038 int res = poll(&polls, 1, delay);
01039
01040 if (res < 0)
01041 VERBOSE(VB_IMPORTANT, LOC_ERR + "Polling" + ENO);
01042
01043
01044 return res;
01045 }
01046
01053 uint VideoOutputIvtv::WriteBuffer(unsigned char *buf, int len)
01054 {
01055 int count = write(videofd, buf, len);
01056
01057 if (count < 0)
01058 {
01059 if (errno != EAGAIN)
01060 {
01061 VERBOSE(VB_IMPORTANT, LOC_ERR + "Writing to decoder" + ENO);
01062 return count;
01063 }
01064 count = 0;
01065 }
01066
01067 return count;
01068 }
01069
01073 long long VideoOutputIvtv::GetFirmwareFramesPlayed(void)
01074 {
01075 if (has_v4l2_api)
01076 {
01077 long long frame;
01078 if (ioctl(videofd, VIDEO_GET_FRAME_COUNT, &frame) < 0)
01079 VERBOSE(VB_IMPORTANT, LOC_ERR +
01080 "Fetching frames played from decoder" + ENO);
01081 return frame;
01082 }
01083 else
01084 {
01085 struct ivtv_ioctl_framesync frameinfo;
01086 bzero(&frameinfo, sizeof(frameinfo));
01087
01088 if (ioctl(videofd, IVTV_IOC_GET_TIMING, &frameinfo) < 0)
01089 {
01090 VERBOSE(VB_IMPORTANT, LOC_ERR +
01091 "Fetching frames played from decoder" + ENO);
01092 }
01093
01094 return frameinfo.frame;
01095 }
01096 }
01097
01105 long long VideoOutputIvtv::GetFramesPlayed(void)
01106 {
01107 long long frame = GetFirmwareFramesPlayed();
01108 float f = internal_offset + (frame - frame_at_speed_change) * last_speed;
01109 return (long long)round(f);
01110 }
01111
01115 bool VideoOutputIvtv::Play(float speed, bool normal, int mask)
01116 {
01117 VERBOSE(VB_PLAYBACK, LOC + "Play("<<speed<<", "<<normal<<", "<<mask<<")");
01118 internal_offset = GetFramesPlayed();
01119 frame_at_speed_change = GetFirmwareFramesPlayed();
01120
01121 speed = (speed >= 2.0f) ? 2.0f : speed;
01122 speed = (speed <= 0.05f) ? 1.0f : speed;
01123
01124 if (has_v4l2_api)
01125 {
01126 struct video_command cmd;
01127
01128 if (has_pause_bug && paused && speed == 1.0f)
01129 {
01130
01131 memset(&cmd, 0, sizeof(cmd));
01132 cmd.cmd = VIDEO_CMD_PLAY;
01133 cmd.play.speed = 500;
01134 ioctl(videofd, VIDEO_COMMAND, &cmd);
01135 }
01136 memset(&cmd, 0, sizeof(cmd));
01137 cmd.cmd = VIDEO_CMD_PLAY;
01138 cmd.play.speed = (__u32)(1000.0f * speed);
01139 ioctl(videofd, VIDEO_COMMAND, &cmd);
01140 paused = false;
01141 }
01142 else
01143 {
01144 struct ivtv_speed play;
01145 bzero(&play, sizeof(play));
01146 play.scale = (speed >= 2.0f) ? (int)roundf(speed) : 1;
01147 play.scale = (speed <= 0.5f) ? (int)roundf(1.0f / speed) : play.scale;
01148 play.speed = (speed > 1.0f);
01149 play.smooth = 0;
01150 play.direction = 0;
01151 play.fr_mask = mask;
01152 play.b_per_gop = 0;
01153 play.aud_mute = !normal;
01154 play.fr_field = 0;
01155 play.mute = 0;
01156
01157 while (ioctl(videofd, IVTV_IOC_S_SPEED, &play) < 0)
01158 {
01159 if (errno != EBUSY)
01160 {
01161 VERBOSE(VB_IMPORTANT, LOC_ERR +
01162 "Setting decoder's playback speed" + ENO);
01163 break;
01164 }
01165 usleep(1000);
01166 }
01167 }
01168
01169 last_speed = speed;
01170 last_normal = normal;
01171 last_mask = mask;
01172
01173 return true;
01174 }
01175
01179 void VideoOutputIvtv::Flush(void)
01180 {
01181 VERBOSE(VB_PLAYBACK, LOC + "Flush()");
01182 if (decoder_flush)
01183 {
01184 int arg = 0;
01185 if (ioctl(videofd, IVTV_IOC_DEC_FLUSH, &arg) < 0)
01186 VERBOSE(VB_IMPORTANT, LOC_ERR + "Flushing decoder" + ENO);
01187 }
01188 }
01189
01193 void VideoOutputIvtv::Step(void)
01194 {
01195 VERBOSE(VB_PLAYBACK, LOC + "Step()");
01196
01197 if (has_v4l2_api)
01198 {
01199 struct video_command cmd;
01200 memset(&cmd, 0, sizeof(cmd));
01201 cmd.cmd = VIDEO_CMD_PLAY;
01202 cmd.play.speed = 1;
01203 ioctl(videofd, VIDEO_COMMAND, &cmd);
01204 }
01205 else
01206 {
01207 int arg = 0;
01208
01209 while (ioctl(videofd, IVTV_IOC_DEC_STEP, &arg) < 0)
01210 {
01211 if (errno != EBUSY)
01212 {
01213 VERBOSE(VB_IMPORTANT, LOC_ERR + "Setting Step" + ENO);
01214 break;
01215 }
01216 usleep(1000);
01217 }
01218 }
01219 }
01220
01221 QStringList VideoOutputIvtv::GetAllowedRenderers(
01222 MythCodecID myth_codec_id, const QSize &video_dim)
01223 {
01224 QStringList list;
01225
01226 if (((kCodec_MPEG1 == myth_codec_id) ||
01227 (kCodec_MPEG2 == myth_codec_id)) &&
01228 (video_dim.width() <= 720) &&
01229 (video_dim.height() <= 576))
01230 {
01231 list += "ivtv";
01232 }
01233
01234 return list;
01235 }