summaryrefslogtreecommitdiff
path: root/osd.c
diff options
context:
space:
mode:
Diffstat (limited to 'osd.c')
-rw-r--r--osd.c1083
1 files changed, 587 insertions, 496 deletions
diff --git a/osd.c b/osd.c
index 2b0822f..0a7773e 100644
--- a/osd.c
+++ b/osd.c
@@ -2,8 +2,12 @@
* OSD Picture in Picture plugin for the Video Disk Recorder
*
* See the README file for copyright information and how to reach the author.
+ *
+ * Copyright (C) 2007 Martin Wache for the dithered 256 color mode
*/
+#include <stdint.h>
+
#include "osd.h"
#include "decoder.h"
#include "quantize.h"
@@ -17,537 +21,624 @@
cMutex Mutex;
cOsdPipObject::cOsdPipObject(cDevice *Device, const cChannel *Channel)
-: cOsdObject(true)
+: cOsdObject(true),
+ cThread("osdpip_osd")
{
- m_Channel = Channel;
- m_Osd = NULL;
- m_ESBuffer = new cRingBufferFrame(MEGABYTE(3), true);
-
- m_Active = false;
- m_Ready = false;
- m_Reset = true;
- m_MoveMode = false;
- m_Width = m_Height = -1;
- m_Bitmap = NULL;
- m_InfoWindow = NULL;
-
- m_AlphaBase = 0xFF000000;
- for (int i = 0; i < 256; i++)
- m_Palette[i] = 0xFD000000 | i;
- m_PaletteStart = 1;
-
- Device->SwitchChannel(m_Channel, false);
- m_Receiver = new cOsdPipReceiver(m_Channel, m_ESBuffer);
- Device->AttachReceiver(m_Receiver);
+ m_Channel = Channel;
+ m_Osd = NULL;
+ m_ESBuffer = new cRingBufferFrame(MEGABYTE(3), true);
+
+ m_Active = false;
+ m_Ready = false;
+ m_Reset = true;
+ m_MoveMode = false;
+ m_Width = m_Height = -1;
+ m_Bitmap = NULL;
+ m_InfoWindow = NULL;
+
+ m_AlphaBase = 0xFF000000;
+ for (int i = 0; i < 256; i++)
+ m_Palette[i] = m_AlphaBase | i;
+ m_PaletteStart = 1;
+
+ Device->SwitchChannel(m_Channel, false);
+ m_Receiver = new cOsdPipReceiver(m_Channel, m_ESBuffer);
+ Device->AttachReceiver(m_Receiver);
}
cOsdPipObject::~cOsdPipObject()
{
- Stop();
-
- delete m_Receiver;
- delete m_ESBuffer;
- if (m_Bitmap != NULL)
- delete m_Bitmap;
- delete m_InfoWindow;
- if (m_Osd != NULL)
- delete m_Osd;
+ Stop();
+
+ delete m_Receiver;
+ delete m_ESBuffer;
+ if (m_Bitmap != NULL)
+ delete m_Bitmap;
+ delete m_InfoWindow;
+ if (m_Osd != NULL)
+ delete m_Osd;
}
void cOsdPipObject::Stop(void)
{
- if (m_Active)
- {
- m_Active = false;
- Cancel(3);
- }
- m_ESBuffer->Clear();
+ if (m_Active)
+ {
+ m_Active = false;
+ Cancel(3);
+ }
+ m_ESBuffer->Clear();
}
void cOsdPipObject::SwapChannels(void)
{
- const cChannel *chan = cDevice::CurrentChannel() != 0
- ? Channels.GetByNumber(cDevice::CurrentChannel()) : NULL;
- if (chan) {
- Stop();
- Channels.SwitchTo(m_Channel->Number());
- cDevice *dev = cDevice::GetDevice(chan, 1);
- if (dev) {
- DELETENULL(m_Receiver);
- m_Channel = chan;
- dev->SwitchChannel(m_Channel, false);
- m_Receiver = new cOsdPipReceiver(m_Channel, m_ESBuffer);
- dev->AttachReceiver(m_Receiver);
- }
- Start();
- }
+ const cChannel *chan = cDevice::CurrentChannel() != 0
+ ? Channels.GetByNumber(cDevice::CurrentChannel()) : NULL;
+ if (chan) {
+ Stop();
+ Channels.SwitchTo(m_Channel->Number());
+#if (APIVERSNUM < 10500)
+ cDevice *dev = cDevice::GetDevice(chan, 1);
+#else
+ cDevice *dev = cDevice::GetDevice(chan, 1, false);
+#endif
+ if (dev) {
+ DELETENULL(m_Receiver);
+ m_Channel = chan;
+ dev->SwitchChannel(m_Channel, false);
+ m_Receiver = new cOsdPipReceiver(m_Channel, m_ESBuffer);
+ dev->AttachReceiver(m_Receiver);
+ }
+ Start();
+ }
+}
+
+static inline uint8_t clip(int x)
+{
+ if (x<=0)
+ return 0;
+ if (x>=255)
+ return 255;
+ return (uint8_t) x;
+}
+
+static inline uint32_t YUV_to_RGB32(int py, int pu, int pv)
+{
+ py=(((int) py)-16)*298+128;
+ pu=((int) pu)-128;
+ pv=((int) pv)-128;
+
+ int r=(409*pv);
+ int g=(-100*pu-208*pv);
+ int b=(516*pu);
+
+ //printf("%d %d %d -> %d %d %d \n", py,pu, pv,clip((py+r)>>8),clip((py+g)>>8),clip((py+b)>>8));
+ return (clip((py+r)>>8)<<16) | (clip((py+g)>>8)<<8) | clip((py+b)>>8);
}
void cOsdPipObject::ProcessImage(unsigned char * data, int length)
{
- unsigned int value;
- unsigned int * outputPalette;
- unsigned char * outputImage;
- int height;
-
- if (m_FrameDrop != -1)
- {
- if (OsdPipSetup.FrameMode == kFrameModeI)
- {
- if (m_FrameDrop == OsdPipSetup.FrameDrop)
- {
- m_FrameDrop = 0;
- }
- else
- {
- m_FrameDrop++;
- return;
- }
- }
- }
-
- if (decoder.Decode(data, length) != 0)
- return;
-
- if (m_FrameDrop != -1)
- {
- if (OsdPipSetup.FrameMode == kFrameModeIP ||
- OsdPipSetup.FrameMode == kFrameModeIPB)
- {
- if (m_FrameDrop == OsdPipSetup.FrameDrop)
- {
- m_FrameDrop = 0;
- }
- else
- {
- m_FrameDrop++;
- return;
- }
- }
- }
-
- if (!m_Ready)
- {
- if (m_Bitmap != NULL)
- delete m_Bitmap;
- m_Bitmap = NULL;
- if (m_InfoWindow != NULL)
- delete m_InfoWindow;
- m_InfoWindow = NULL;
- switch (OsdPipSetup.Size)
- {
- case 0: m_Width = 100; m_Height = 80; break;
- case 1: m_Width = 120; m_Height = 96; break;
- case 2: m_Width = 140; m_Height = 112; break;
- case 3: m_Width = 160; m_Height = 128; break;
- case 4: m_Width = 180; m_Height = 144; break;
- case 5: m_Width = 200; m_Height = 160; break;
- case 6: m_Width = 220; m_Height = 176; break;
- case 7: m_Width = 240; m_Height = 192; break;
- case 8: m_Width = 260; m_Height = 208; break;
- case 9: m_Width = 280; m_Height = 224; break;
- case 10: m_Width = 300; m_Height = 240; break;
- }
- if (OsdPipSetup.ShowInfo > 0)
- {
- int infoX = 0;
- int infoY = 0;
- int infoH = OsdPipSetup.ShowInfo * 30;
-
- switch (OsdPipSetup.InfoPosition)
- {
- case kInfoTopLeft:
- infoX = Setup.OSDLeft;
- infoY = Setup.OSDTop;
- break;
- case kInfoTopRight:
- infoX = Setup.OSDLeft + Setup.OSDWidth - OsdPipSetup.InfoWidth;
- infoY = Setup.OSDTop;
- break;
- case kInfoBottomLeft:
- infoX = Setup.OSDLeft;
- infoY = Setup.OSDTop + Setup.OSDHeight - infoH;
- break;
- case kInfoBottomRight:
- infoX = Setup.OSDLeft + Setup.OSDWidth - OsdPipSetup.InfoWidth;
- infoY = Setup.OSDTop + Setup.OSDHeight - infoH;
- break;
- }
- tArea areas[] =
- {
- { OsdPipSetup.XPosition, OsdPipSetup.YPosition, OsdPipSetup.XPosition + m_Width - 1, OsdPipSetup.YPosition + m_Height - 1, OsdPipSetup.ColorDepth == kDepthGrey16 ? 4 : 8 },
- { infoX, infoY, infoX + OsdPipSetup.InfoWidth - 1, infoY + infoH - 1, OsdPipSetup.ColorDepth == kDepthGrey16 ? 4 : 8 }
- };
- if (m_Osd->CanHandleAreas(areas, 2) == oeOk)
- m_Osd->SetAreas(areas, 2);
- else
- m_Osd->SetAreas(areas, 1);
- m_Bitmap = new cBitmap(m_Width, m_Height, OsdPipSetup.ColorDepth == kDepthGrey16 ? 4 : 8);
- m_InfoWindow = new cOsdInfoWindow(m_Osd, m_Palette, infoX, infoY);
- }
- else
- {
- tArea areas[] =
- {
- { OsdPipSetup.XPosition, OsdPipSetup.YPosition, OsdPipSetup.XPosition + m_Width - 1, OsdPipSetup.YPosition + m_Height - 1, OsdPipSetup.ColorDepth == kDepthGrey16 ? 4 : 8 }
- };
- m_Osd->SetAreas(areas, 1);
- m_Bitmap = new cBitmap(m_Width, m_Height, OsdPipSetup.ColorDepth == kDepthGrey16 ? 4 : 8);
- }
-
- Mutex.Lock();
- if (OsdPipSetup.ColorDepth == kDepthGrey256)
- {
- for (int i = 0; i < 256; i++)
- m_Palette[i] = m_AlphaBase | (i << 16) | (i << 8) | i;
- m_Palette[0] = 0xFD000000;
- m_Palette[255] = 0xFDFFFFFF;
- }
- if (OsdPipSetup.ColorDepth == kDepthColor256fix)
- {
- for (int i = 0; i < 252; i++)
- m_Palette[i + 1] = m_AlphaBase | quantizer->OutputPalette()[i];
- m_Palette[0] = 0xFD000000;
- m_Palette[255] = 0xFDFFFFFF;
- }
- if (OsdPipSetup.ColorDepth == kDepthColor128var)
- {
- m_Palette[0] = 0xFD000000;
- m_Palette[255] = 0xFDFFFFFF;
- }
- Mutex.Unlock();
- }
-
- if (decoder.AspectRatio() > 0.1)
- height = (int) ((float) m_Width / decoder.AspectRatio() * 16.0f / 15.0f + 0.5);
- else
- height = m_Height;
- if (decoder.Resample(m_Width, height) != 0)
- return;
-
- int size;
- size = m_Width * height;
-
- if (OsdPipSetup.ColorDepth == kDepthGrey16)
- {
- m_Bitmap->DrawRectangle(0, 0, m_Width - 1, (m_Height - height) / 2 - 1, m_Palette[0]);
- m_Bitmap->DrawRectangle(0, (m_Height + height) / 2, m_Width - 1, m_Height - 1, m_Palette[0]);
- outputImage = decoder.PicResample()->data[0];
- for (int y = 0; y < height; y++)
- {
- for (int x = 0; x < m_Width; x++)
- {
- value = outputImage[y * m_Width + x];
- value = value & 0xF0;
- value = m_AlphaBase | (value << 16) | (value << 8) | value;
- m_Bitmap->DrawPixel(x, y + (m_Height - height) / 2, value);
- }
- }
- }
- if (OsdPipSetup.ColorDepth == kDepthGrey256)
- {
- outputImage = decoder.PicResample()->data[0];
- m_Bitmap->DrawRectangle(0, 0, m_Width - 1, m_Height - 1, m_Palette[0]);
- for (int i = 0; i < 256; i++)
- m_Bitmap->SetColor(i, m_Palette[i]);
- for (int y = 0; y < height; y++)
- {
- for (int x = 0; x < m_Width; x++)
- {
- m_Bitmap->SetIndex(x, y + (m_Height - height) / 2, outputImage[y * m_Width + x]);
- }
- }
- }
- if (OsdPipSetup.ColorDepth == kDepthColor256fix ||
- OsdPipSetup.ColorDepth == kDepthColor128var)
- {
- if (decoder.ConvertToRGB() != 0)
- return;
-
- if (OsdPipSetup.SwapFfmpeg)
- {
- unsigned int * bufPtr = (unsigned int *) decoder.PicConvert()->data[0];
- unsigned char red, green, blue, alpha;
- for (int i = 0; i < size; i++)
- {
- value = *bufPtr;
- blue = value;
- green = value >> 8;
- red = value >> 16;
- alpha = value >> 24;
- value = (alpha << 24) | (blue << 16) | (green << 8) | red;
- *bufPtr = value;
- bufPtr++;
- }
- }
-
- quantizer->Quantize(decoder.PicConvert()->data[0], size, 127);
-
- outputPalette = quantizer->OutputPalette();
- outputImage = quantizer->OutputImage();
- if (OsdPipSetup.ColorDepth == kDepthColor256fix)
- {
- m_Bitmap->DrawRectangle(0, 0, m_Width - 1, m_Height - 1, m_Palette[0]);
- for (int i = 0; i < 256; i++)
- m_Bitmap->SetColor(i, m_Palette[i]);
- for (int y = 0; y < height; y++)
- {
- for (int x = 0; x < m_Width; x++)
- {
- m_Bitmap->SetIndex(x, y + (m_Height - height) / 2, outputImage[y * m_Width + x] + 1);
- }
- }
- }
- else
- {
- Mutex.Lock();
- for (int i = 0; i < 127; i++)
- {
- m_Palette[m_PaletteStart + i] = outputPalette[i];
- m_Palette[m_PaletteStart + i] |= m_AlphaBase;
- }
- Mutex.Unlock();
-
- m_Bitmap->DrawRectangle(0, 0, m_Width - 1, m_Height - 1, m_Palette[0]);
- for (int i = 0; i < 256; i++)
- m_Bitmap->SetColor(i, m_Palette[i]);
- for (int y = 0; y < height; y++)
- {
- for (int x = 0; x < m_Width; x++)
- {
- m_Bitmap->SetIndex(x, y + (m_Height - height) / 2, m_PaletteStart + outputImage[y * m_Width + x]);
- }
- }
-
- if (m_PaletteStart == 1)
- {
- m_PaletteStart = 128;
- m_AlphaBase = 0xFE000000;
- }
- else
- {
- m_PaletteStart = 1;
- m_AlphaBase = 0xFF000000;
- }
- }
- }
- if (!m_Ready)
- {
- if (OsdPipSetup.ShowInfo)
- {
- m_InfoWindow->SetChannel(Channels.GetByNumber(cDevice::ActualDevice()->CurrentChannel()));
- m_InfoWindow->Show();
- }
- m_Ready = true;
- }
- Mutex.Lock();
- m_Osd->DrawBitmap(OsdPipSetup.XPosition, OsdPipSetup.YPosition, *m_Bitmap);
- m_Osd->Flush();
- Mutex.Unlock();
+ unsigned int value;
+ unsigned int * outputPalette;
+ unsigned char * outputImage;
+ int height;
+
+ if (m_FrameDrop != -1)
+ {
+ if (OsdPipSetup.FrameMode == kFrameModeI)
+ {
+ if (m_FrameDrop == OsdPipSetup.FrameDrop)
+ {
+ m_FrameDrop = 0;
+ }
+ else
+ {
+ m_FrameDrop++;
+ return;
+ }
+ }
+ }
+
+ if (decoder.Decode(data, length) != 0)
+ return;
+
+ if (m_FrameDrop != -1)
+ {
+ if (OsdPipSetup.FrameMode == kFrameModeIP ||
+ OsdPipSetup.FrameMode == kFrameModeIPB)
+ {
+ if (m_FrameDrop == OsdPipSetup.FrameDrop)
+ {
+ m_FrameDrop = 0;
+ }
+ else
+ {
+ m_FrameDrop++;
+ return;
+ }
+ }
+ }
+
+ if (!m_Ready)
+ {
+ if (m_Bitmap != NULL)
+ delete m_Bitmap;
+ m_Bitmap = NULL;
+ if (m_InfoWindow != NULL)
+ delete m_InfoWindow;
+ m_InfoWindow = NULL;
+ switch (OsdPipSetup.Size)
+ {
+ case 0: m_Width = 100; m_Height = 80; break;
+ case 1: m_Width = 120; m_Height = 96; break;
+ case 2: m_Width = 140; m_Height = 112; break;
+ case 3: m_Width = 160; m_Height = 128; break;
+ case 4: m_Width = 180; m_Height = 144; break;
+ case 5: m_Width = 200; m_Height = 160; break;
+ case 6: m_Width = 220; m_Height = 176; break;
+ case 7: m_Width = 240; m_Height = 192; break;
+ case 8: m_Width = 260; m_Height = 208; break;
+ case 9: m_Width = 280; m_Height = 224; break;
+ case 10: m_Width = 300; m_Height = 240; break;
+ }
+ if (OsdPipSetup.ShowInfo > 0)
+ {
+ int infoX = 0;
+ int infoY = 0;
+ int infoH = OsdPipSetup.ShowInfo * 30;
+
+ switch (OsdPipSetup.InfoPosition)
+ {
+ case kInfoTopLeft:
+ infoX = Setup.OSDLeft;
+ infoY = Setup.OSDTop;
+ break;
+ case kInfoTopRight:
+ infoX = Setup.OSDLeft + Setup.OSDWidth - OsdPipSetup.InfoWidth;
+ infoY = Setup.OSDTop;
+ break;
+ case kInfoBottomLeft:
+ infoX = Setup.OSDLeft;
+ infoY = Setup.OSDTop + Setup.OSDHeight - infoH;
+ break;
+ case kInfoBottomRight:
+ infoX = Setup.OSDLeft + Setup.OSDWidth - OsdPipSetup.InfoWidth;
+ infoY = Setup.OSDTop + Setup.OSDHeight - infoH;
+ break;
+ }
+ tArea areas[] =
+ {
+ {
+ OsdPipSetup.XPosition,
+ OsdPipSetup.YPosition,
+ OsdPipSetup.XPosition + m_Width - 1,
+ OsdPipSetup.YPosition + m_Height - 1,
+ OsdPipSetup.ColorDepth == kDepthGrey16 ? 4 : 8
+ },
+ {
+ infoX,
+ infoY,
+ infoX + OsdPipSetup.InfoWidth - 1,
+ infoY + infoH - 1,
+ OsdPipSetup.ColorDepth == kDepthGrey16 ? 4 : 8
+ }
+ };
+ if (m_Osd->CanHandleAreas(areas, 2) == oeOk)
+ m_Osd->SetAreas(areas, 2);
+ else
+ m_Osd->SetAreas(areas, 1);
+ m_Bitmap = new cBitmap(m_Width, m_Height, OsdPipSetup.ColorDepth == kDepthGrey16 ? 4 : 8);
+ m_InfoWindow = new cOsdInfoWindow(m_Osd, m_Palette, infoX, infoY);
+ }
+ else
+ {
+ tArea areas[] =
+ {
+ {
+ OsdPipSetup.XPosition,
+ OsdPipSetup.YPosition,
+ OsdPipSetup.XPosition + m_Width - 1,
+ OsdPipSetup.YPosition + m_Height - 1,
+ OsdPipSetup.ColorDepth == kDepthGrey16 ? 4 : 8
+ }
+ };
+ m_Osd->SetAreas(areas, 1);
+ m_Bitmap = new cBitmap(m_Width, m_Height, OsdPipSetup.ColorDepth == kDepthGrey16 ? 4 : 8);
+ }
+
+ Mutex.Lock();
+ if (OsdPipSetup.ColorDepth == kDepthGrey256)
+ {
+ for (int i = 0; i < 256; i++)
+ m_Palette[i] = m_AlphaBase | (i << 16) | (i << 8) | i;
+ m_Palette[0] = m_AlphaBase | 0x00000000;
+ m_Palette[255] = m_AlphaBase | 0x00FFFFFF;
+ }
+ else if (OsdPipSetup.ColorDepth == kDepthColor256fix)
+ {
+ for (int i = 0; i < 252; i++)
+ m_Palette[i + 1] = m_AlphaBase | quantizer->OutputPalette()[i];
+ m_Palette[0] = m_AlphaBase | 0x00000000;
+ m_Palette[255] = m_AlphaBase | 0x00FFFFFF;
+ }
+ else if (OsdPipSetup.ColorDepth == kDepthColor128var)
+ {
+ m_Palette[0] = m_AlphaBase | 0x00000000;
+ m_Palette[255] = m_AlphaBase | 0x00FFFFFF;
+ }
+ else if (OsdPipSetup.ColorDepth == kDepthColor256dither)
+ {
+#define Y_STEPS 10
+#define U_STEPS 5
+#define V_STEPS 5
+ for (int y=0; y<Y_STEPS; y++)
+ for (int u=0; u<U_STEPS; u++)
+ for (int v=0; v<V_STEPS; v++)
+ m_Palette[y*U_STEPS*V_STEPS+u*V_STEPS+v+1] = m_AlphaBase
+ | YUV_to_RGB32(y*255/(Y_STEPS), u*255/(U_STEPS), v*255/(V_STEPS));
+ m_Palette[0] = m_AlphaBase | 0x00000000;
+ m_Palette[255] = m_AlphaBase | 0x00FFFFFF;
+ }
+ Mutex.Unlock();
+ }
+
+ if (decoder.AspectRatio() > 0.1)
+ height = (int) ((float) m_Width / decoder.AspectRatio() * 16.0f / 15.0f + 0.5);
+ else
+ height = m_Height;
+ if (decoder.Resample(m_Width, height) != 0)
+ return;
+
+ int size;
+ size = m_Width * height;
+
+ if (OsdPipSetup.ColorDepth == kDepthGrey16)
+ {
+ m_Bitmap->DrawRectangle(0, 0, m_Width - 1, (m_Height - height) / 2 - 1, m_Palette[0]);
+ m_Bitmap->DrawRectangle(0, (m_Height + height) / 2, m_Width - 1, m_Height - 1, m_Palette[0]);
+ outputImage = decoder.PicResample()->data[0];
+ for (int y = 0; y < height; y++)
+ {
+ for (int x = 0; x < m_Width; x++)
+ {
+ value = outputImage[y * m_Width + x];
+ value = value & 0xF0;
+ value = m_AlphaBase | (value << 16) | (value << 8) | value;
+ m_Bitmap->DrawPixel(x, y + (m_Height - height) / 2, value);
+ }
+ }
+ }
+ else if (OsdPipSetup.ColorDepth == kDepthGrey256)
+ {
+ outputImage = decoder.PicResample()->data[0];
+ m_Bitmap->DrawRectangle(0, 0, m_Width - 1, m_Height - 1, m_Palette[0]);
+ for (int i = 0; i < 256; i++)
+ m_Bitmap->SetColor(i, m_Palette[i]);
+ for (int y = 0; y < height; y++)
+ {
+ for (int x = 0; x < m_Width; x++)
+ {
+ m_Bitmap->SetIndex(x, y + (m_Height - height) / 2, outputImage[y * m_Width + x]);
+ }
+ }
+ }
+ else if (OsdPipSetup.ColorDepth == kDepthColor256dither)
+ {
+ outputImage = decoder.PicResample()->data[0];
+ uint8_t *pY=decoder.PicResample()->data[0];
+ uint8_t *pU=(uint8_t*)decoder.PicResample()->data[1];
+ uint8_t *pV=(uint8_t*)decoder.PicResample()->data[2];
+ m_Bitmap->DrawRectangle(0, 0, m_Width - 1, m_Height - 1, m_Palette[0]);
+ for (int i = 0; i < 256; i++)
+ m_Bitmap->SetColor(i, m_Palette[i]);
+ for (int y = 0; y < height; y++)
+ {
+ for (int x = 0; x < m_Width; x++)
+ {
+ int uvpos = (y>>1) * (m_Width>>1) + (x>>1);
+ static int uvdither[] =
+ {
+ 2*255/U_STEPS/4,
+ 3*255/U_STEPS/4,
+ 4*255/U_STEPS/4,
+ 1*255/U_STEPS/4
+ };
+ static int ydither[] =
+ {
+ 2*255/Y_STEPS/4,
+ 3*255/Y_STEPS/4,
+ 4*255/Y_STEPS/4,
+ 1*255/Y_STEPS/4
+ };
+ int cy=((unsigned int)pY[y*m_Width+x]);
+ int cu=((unsigned int)pU[uvpos]);
+ int cv=((unsigned int)pV[uvpos]);
+#define CLAMP(C,var) ((var)>=C##_STEPS?C##_STEPS-1:(var))
+ cy=(cy+ydither[2*(y&1)+(x&1)])*Y_STEPS/255;
+ cu=(cu+uvdither[2*(y&1)+(x&1)])*U_STEPS/255;
+ cv=(cv+uvdither[2*(y&1)+(x&1)])*V_STEPS/255;
+ int color=CLAMP(Y,cy)*(V_STEPS*U_STEPS)+CLAMP(U,cu)*(V_STEPS)+CLAMP(V,cv);
+ m_Bitmap->SetIndex(x, y + (m_Height - height) / 2, color+1);
+ }
+ }
+ }
+ else if (OsdPipSetup.ColorDepth == kDepthColor256fix ||
+ OsdPipSetup.ColorDepth == kDepthColor128var)
+ {
+ if (decoder.ConvertToRGB() != 0)
+ return;
+
+ if (OsdPipSetup.SwapFfmpeg)
+ {
+ unsigned int * bufPtr = (unsigned int *) decoder.PicConvert()->data[0];
+ unsigned char red, green, blue, alpha;
+ for (int i = 0; i < size; i++)
+ {
+ value = *bufPtr;
+ blue = value;
+ green = value >> 8;
+ red = value >> 16;
+ alpha = value >> 24;
+ value = (alpha << 24) | (blue << 16) | (green << 8) | red;
+ *bufPtr = value;
+ bufPtr++;
+ }
+ }
+
+ quantizer->Quantize(decoder.PicConvert()->data[0], size, 127);
+
+ outputPalette = quantizer->OutputPalette();
+ outputImage = quantizer->OutputImage();
+ if (OsdPipSetup.ColorDepth == kDepthColor256fix)
+ {
+ m_Bitmap->DrawRectangle(0, 0, m_Width - 1, m_Height - 1, m_Palette[0]);
+ for (int i = 0; i < 256; i++)
+ m_Bitmap->SetColor(i, m_Palette[i]);
+ for (int y = 0; y < height; y++)
+ {
+ for (int x = 0; x < m_Width; x++)
+ {
+ m_Bitmap->SetIndex(x, y + (m_Height - height) / 2, outputImage[y * m_Width + x] + 1);
+ }
+ }
+ }
+ else
+ {
+ Mutex.Lock();
+ for (int i = 0; i < 127; i++)
+ {
+ m_Palette[m_PaletteStart + i] = outputPalette[i];
+ m_Palette[m_PaletteStart + i] |= m_AlphaBase;
+ }
+ Mutex.Unlock();
+
+ m_Bitmap->DrawRectangle(0, 0, m_Width - 1, m_Height - 1, m_Palette[0]);
+ for (int i = 0; i < 256; i++)
+ m_Bitmap->SetColor(i, m_Palette[i]);
+ for (int y = 0; y < height; y++)
+ {
+ for (int x = 0; x < m_Width; x++)
+ {
+ m_Bitmap->SetIndex(x, y + (m_Height - height) / 2, m_PaletteStart + outputImage[y * m_Width + x]);
+ }
+ }
+
+ if (m_PaletteStart == 1)
+ {
+ m_PaletteStart = 128;
+ }
+ else
+ {
+ m_PaletteStart = 1;
+ }
+ }
+ }
+ if (!m_Ready)
+ {
+ if (OsdPipSetup.ShowInfo)
+ {
+ m_InfoWindow->SetChannel(Channels.GetByNumber(cDevice::ActualDevice()->CurrentChannel()));
+ m_InfoWindow->Show();
+ }
+ m_Ready = true;
+ }
+ Mutex.Lock();
+ m_Osd->DrawBitmap(OsdPipSetup.XPosition, OsdPipSetup.YPosition, *m_Bitmap, 0, 0, true);
+ m_Osd->Flush();
+ Mutex.Unlock();
}
void cOsdPipObject::Action(void)
{
- m_Active = true;
-
- isyslog("osdpip: decoder thread started (pid = %d)", getpid());
-
- decoder.Open();
-
- if (OsdPipSetup.ColorDepth == kDepthColor128var)
- quantizer = new cQuantizeWu();
- if (OsdPipSetup.ColorDepth == kDepthColor256fix)
- quantizer = new cQuantizeFixed();
-
- cFrame * frame;
- int pictureType;
- m_FrameDrop = OsdPipSetup.FrameDrop;
-
- while (m_Active)
- {
- if (m_Reset)
- {
- if (m_Osd)
- delete m_Osd;
- m_Osd = cOsdProvider::NewOsd(0, 0);
- if (!m_Osd)
- break;
- m_Ready = false;
- m_Reset = false;
- }
- if (m_FrameDrop == -1)
- {
- while ((frame = m_ESBuffer->Get()) != NULL)
- {
- if (frame->Count() > 0)
- {
- if (m_ESBuffer->Available() == frame->Count())
- break;
- if (OsdPipSetup.FrameMode == kFrameModeIP ||
- OsdPipSetup.FrameMode == kFrameModeIPB)
- {
- decoder.Decode(frame->Data(), frame->Count());
- }
- }
- m_ESBuffer->Drop(frame);
- }
- if (frame)
- {
- pictureType = frame->Index();
- ProcessImage(frame->Data(), frame->Count());
- m_ESBuffer->Drop(frame);
- }
- }
- else
- {
- frame = m_ESBuffer->Get();
- {
- if (frame && frame->Count() > 0)
- {
- pictureType = frame->Index();
- ProcessImage(frame->Data(), frame->Count());
- m_ESBuffer->Drop(frame);
- }
- else
- {
- if (frame)
- m_ESBuffer->Drop(frame);
- usleep(1);
- }
- }
- }
- }
-
- if (OsdPipSetup.ColorDepth == kDepthColor128var ||
- OsdPipSetup.ColorDepth == kDepthColor256fix)
- delete quantizer;
- decoder.Close();
-
- isyslog("osdpip: decoder thread stopped");
+ m_Active = true;
+
+ isyslog("osdpip: decoder thread started (pid = %d)", getpid());
+
+ decoder.Open();
+
+ if (OsdPipSetup.ColorDepth == kDepthColor128var)
+ quantizer = new cQuantizeWu();
+ if (OsdPipSetup.ColorDepth == kDepthColor256fix)
+ quantizer = new cQuantizeFixed();
+
+ cFrame * frame;
+ m_FrameDrop = OsdPipSetup.FrameDrop;
+
+ while (m_Active)
+ {
+ if (m_Reset)
+ {
+ if (m_Osd)
+ delete m_Osd;
+ m_Osd = cOsdProvider::NewOsd(0, 0);
+ if (!m_Osd)
+ break;
+ m_Ready = false;
+ m_Reset = false;
+ }
+ if (m_FrameDrop == -1)
+ {
+ while ((frame = m_ESBuffer->Get()) != NULL)
+ {
+ if (frame->Count() > 0)
+ {
+ if (m_ESBuffer->Available() == frame->Count())
+ break;
+ if (OsdPipSetup.FrameMode == kFrameModeIP ||
+ OsdPipSetup.FrameMode == kFrameModeIPB)
+ {
+ if (frame->Index() != B_FRAME)
+ decoder.Decode(frame->Data(), frame->Count());
+ }
+ }
+ m_ESBuffer->Drop(frame);
+ }
+ if (frame)
+ {
+ ProcessImage(frame->Data(), frame->Count());
+ m_ESBuffer->Drop(frame);
+ }
+ }
+ else
+ {
+ frame = m_ESBuffer->Get();
+ if (frame)
+ {
+ if (frame->Count() > 0)
+ {
+ ProcessImage(frame->Data(), frame->Count());
+ }
+ m_ESBuffer->Drop(frame);
+ }
+ }
+ cCondWait::SleepMs(1);
+ }
+
+ if (OsdPipSetup.ColorDepth == kDepthColor128var ||
+ OsdPipSetup.ColorDepth == kDepthColor256fix)
+ delete quantizer;
+ decoder.Close();
+
+ isyslog("osdpip: decoder thread stopped");
}
void cOsdPipObject::Show(void)
{
- Start();
+ Start();
}
eOSState cOsdPipObject::ProcessKey(eKeys Key)
{
- eOSState state = cOsdObject::ProcessKey(Key);
- if (state == osUnknown)
- {
- if (m_MoveMode)
- {
- switch (Key & ~k_Repeat)
- {
- case k0:
- Channels.SwitchTo(m_Channel->Number());
- case kBack:
- return osEnd;
- case kGreen:
- m_MoveMode = false;
- if (m_Ready && m_InfoWindow)
- {
- m_InfoWindow->SetMessage(tr("Normal mode"));
- m_InfoWindow->Show();
- }
- break;
- case kUp:
- if (OsdPipSetup.YPosition >= 10)
- OsdPipSetup.YPosition -= 10;
- m_Reset = true;
- break;
- case kLeft:
- if (OsdPipSetup.XPosition >= 10)
- OsdPipSetup.XPosition -= 10;
- m_Reset = true;
- break;
- case kRight:
- if (OsdPipSetup.XPosition + m_Width <= 720 - 10)
- OsdPipSetup.XPosition += 10;
- m_Reset = true;
- break;
- case kDown:
- if (OsdPipSetup.YPosition + m_Height <= 576 - 10)
- OsdPipSetup.YPosition += 10;
- m_Reset = true;
- break;
- }
- state = osContinue;
- }
- else
- {
- if (m_Ready && m_InfoWindow)
- state = m_InfoWindow->ProcessKey(Key);
- }
- }
- if (state == osUnknown)
- {
- switch (Key & ~k_Repeat)
- {
- case k0:
- Channels.SwitchTo(m_Channel->Number());
- case kBack:
- return osEnd;
- case kRed:
- SwapChannels();
- break;
- case kGreen:
- m_MoveMode = true;
- if (m_Ready && m_InfoWindow)
- {
- m_InfoWindow->SetMessage(tr("Move mode"));
- m_InfoWindow->Show();
- }
- break;
- case kUp:
- case kDown:
- cDevice::SwitchChannel(NORMALKEY(Key) == kUp ? 1 : -1);
- break;
- case kOk:
- if (OsdPipSetup.ShowInfo)
- {
- m_InfoWindow->Show();
- }
- break;
- default:
- return state;
- }
- state = osContinue;
- }
- return state;
+ eOSState state = cOsdObject::ProcessKey(Key);
+ if (state == osUnknown)
+ {
+ if (m_MoveMode)
+ {
+ switch (Key & ~k_Repeat)
+ {
+ case k0:
+ Channels.SwitchTo(m_Channel->Number());
+ case kBack:
+ return osEnd;
+ case kGreen:
+ m_MoveMode = false;
+ if (m_Ready && m_InfoWindow)
+ {
+ m_InfoWindow->SetMessage(tr("Normal mode"));
+ m_InfoWindow->Show();
+ }
+ break;
+ case kUp:
+ if (OsdPipSetup.YPosition >= 10)
+ OsdPipSetup.YPosition -= 10;
+ m_Reset = true;
+ break;
+ case kLeft:
+ if (OsdPipSetup.XPosition >= 10)
+ OsdPipSetup.XPosition -= 10;
+ m_Reset = true;
+ break;
+ case kRight:
+ if (OsdPipSetup.XPosition + m_Width <= 720 - 10)
+ OsdPipSetup.XPosition += 10;
+ m_Reset = true;
+ break;
+ case kDown:
+ if (OsdPipSetup.YPosition + m_Height <= 576 - 10)
+ OsdPipSetup.YPosition += 10;
+ m_Reset = true;
+ break;
+ }
+ state = osContinue;
+ }
+ else
+ {
+ if (m_Ready && m_InfoWindow)
+ state = m_InfoWindow->ProcessKey(Key);
+ }
+ }
+ if (state == osUnknown)
+ {
+ switch (Key & ~k_Repeat)
+ {
+ case kNone:
+ return osContinue;
+ case k0:
+ Channels.SwitchTo(m_Channel->Number());
+ case kBack:
+ return osEnd;
+ case kRed:
+ SwapChannels();
+ break;
+ case kGreen:
+ m_MoveMode = true;
+ if (m_Ready && m_InfoWindow)
+ {
+ m_InfoWindow->SetMessage(tr("Move mode"));
+ m_InfoWindow->Show();
+ }
+ break;
+ case kUp:
+ case kDown:
+ cDevice::SwitchChannel(NORMALKEY(Key) == kUp ? 1 : -1);
+ break;
+ case kOk:
+ if (OsdPipSetup.ShowInfo)
+ {
+ m_InfoWindow->Show();
+ }
+ break;
+ default:
+ return state;
+ }
+ state = osContinue;
+ }
+ return state;
}
void cOsdPipObject::ChannelSwitch(const cDevice * device, int channelNumber)
{
- if (device != cDevice::ActualDevice())
- return;
- if (channelNumber == 0)
- return;
- if (channelNumber != cDevice::CurrentChannel())
- return;
- if (!m_Ready)
- return;
- if (OsdPipSetup.ShowInfo)
- {
- m_InfoWindow->SetChannel(Channels.GetByNumber(channelNumber));
- m_InfoWindow->Show();
- }
-}
-
-void cOsdPipObject::OsdClear(void)
-{
- //printf("OsdClear\n");
+ if (device != cDevice::PrimaryDevice())
+ return;
+ if (channelNumber == 0)
+ return;
+ if (channelNumber != cDevice::CurrentChannel())
+ return;
+ if (!m_Ready)
+ return;
+ if (OsdPipSetup.ShowInfo)
+ {
+ m_InfoWindow->SetChannel(Channels.GetByNumber(channelNumber));
+ m_InfoWindow->Show();
+ }
}
void cOsdPipObject::OsdStatusMessage(const char * message)
{
- if (!m_Ready)
- return;
- if (OsdPipSetup.ShowInfo)
- {
- m_InfoWindow->SetMessage(message);
- m_InfoWindow->Show();
- }
+ if (!m_Ready)
+ return;
+ if (OsdPipSetup.ShowInfo)
+ {
+ m_InfoWindow->SetMessage(message);
+ m_InfoWindow->Show();
+ }
}
-