summaryrefslogtreecommitdiff
path: root/osd.c
diff options
context:
space:
mode:
Diffstat (limited to 'osd.c')
-rw-r--r--osd.c417
1 files changed, 266 insertions, 151 deletions
diff --git a/osd.c b/osd.c
index 907171e..1fc1a22 100644
--- a/osd.c
+++ b/osd.c
@@ -1,113 +1,32 @@
+/*
+ * OSD Picture in Picture plugin for the Video Disk Recorder
+ *
+ * See the README file for copyright information and how to reach the author.
+ */
+
#include "osd.h"
+#include "quantize.h"
#include "receiver.h"
#include "config.h"
#include <vdr/ringbuffer.h>
#include <vdr/remux.h>
-const uint rgb256[256] = {
- 0xff000000, 0xff400000, 0xff800000, 0xffc00000, 0xff002000, 0xff402000,
- 0xff802000, 0xffc02000, 0xff004000, 0xff404000, 0xff804000, 0xffc04000,
- 0xff006000, 0xff406000, 0xff806000, 0xffc06000, 0xff008000, 0xff408000,
- 0xff808000, 0xffc08000, 0xff00a000, 0xff40a000, 0xff80a000, 0xffc0a000,
- 0xff00c000, 0xff40c000, 0xff80c000, 0xffc0c000, 0xff00e000, 0xff40e000,
- 0xff80e000, 0xffc0e000, 0xff000020, 0xff400020, 0xff800020, 0xffc00020,
- 0xff002020, 0xff402020, 0xff802020, 0xffc02020, 0xff004020, 0xff404020,
- 0xff804020, 0xffc04020, 0xff006020, 0xff406020, 0xff806020, 0xffc06020,
- 0xff008020, 0xff408020, 0xff808020, 0xffc08020, 0xff00a020, 0xff40a020,
- 0xff80a020, 0xffc0a020, 0xff00c020, 0xff40c020, 0xff80c020, 0xffc0c020,
- 0xff00e020, 0xff40e020, 0xff80e020, 0xffc0e020, 0xff000040, 0xff400040,
- 0xff800040, 0xffc00040, 0xff002040, 0xff402040, 0xff802040, 0xffc02040,
- 0xff004040, 0xff404040, 0xff804040, 0xffc04040, 0xff006040, 0xff406040,
- 0xff806040, 0xffc06040, 0xff008040, 0xff408040, 0xff808040, 0xffc08040,
- 0xff00a040, 0xff40a040, 0xff80a040, 0xffc0a040, 0xff00c040, 0xff40c040,
- 0xff80c040, 0xffc0c040, 0xff00e040, 0xff40e040, 0xff80e040, 0xffc0e040,
- 0xff000060, 0xff400060, 0xff800060, 0xffc00060, 0xff002060, 0xff402060,
- 0xff802060, 0xffc02060, 0xff004060, 0xff404060, 0xff804060, 0xffc04060,
- 0xff006060, 0xff406060, 0xff806060, 0xffc06060, 0xff008060, 0xff408060,
- 0xff808060, 0xffc08060, 0xff00a060, 0xff40a060, 0xff80a060, 0xffc0a060,
- 0xff00c060, 0xff40c060, 0xff80c060, 0xffc0c060, 0xff00e060, 0xff40e060,
- 0xff80e060, 0xffc0e060, 0xff000080, 0xff400080, 0xff800080, 0xffc00080,
- 0xff002080, 0xff402080, 0xff802080, 0xffc02080, 0xff004080, 0xff404080,
- 0xff804080, 0xffc04080, 0xff006080, 0xff406080, 0xff806080, 0xffc06080,
- 0xff008080, 0xff408080, 0xff808080, 0xffc08080, 0xff00a080, 0xff40a080,
- 0xff80a080, 0xffc0a080, 0xff00c080, 0xff40c080, 0xff80c080, 0xffc0c080,
- 0xff00e080, 0xff40e080, 0xff80e080, 0xffc0e080, 0xff0000a0, 0xff4000a0,
- 0xff8000a0, 0xffc000a0, 0xff0020a0, 0xff4020a0, 0xff8020a0, 0xffc020a0,
- 0xff0040a0, 0xff4040a0, 0xff8040a0, 0xffc040a0, 0xff0060a0, 0xff4060a0,
- 0xff8060a0, 0xffc060a0, 0xff0080a0, 0xff4080a0, 0xff8080a0, 0xffc080a0,
- 0xff00a0a0, 0xff40a0a0, 0xff80a0a0, 0xffc0a0a0, 0xff00c0a0, 0xff40c0a0,
- 0xff80c0a0, 0xffc0c0a0, 0xff00e0a0, 0xff40e0a0, 0xff80e0a0, 0xffc0e0a0,
- 0xff0000c0, 0xff4000c0, 0xff8000c0, 0xffc000c0, 0xff0020c0, 0xff4020c0,
- 0xff8020c0, 0xffc020c0, 0xff0040c0, 0xff4040c0, 0xff8040c0, 0xffc040c0,
- 0xff0060c0, 0xff4060c0, 0xff8060c0, 0xffc060c0, 0xff0080c0, 0xff4080c0,
- 0xff8080c0, 0xffc080c0, 0xff00a0c0, 0xff40a0c0, 0xff80a0c0, 0xffc0a0c0,
- 0xff00c0c0, 0xff40c0c0, 0xff80c0c0, 0xffc0c0c0, 0xff00e0c0, 0xff40e0c0,
- 0xff80e0c0, 0xffc0e0c0, 0xff0000e0, 0xff4000e0, 0xff8000e0, 0xffc000e0,
- 0xff0020e0, 0xff4020e0, 0xff8020e0, 0xffc020e0, 0xff0040e0, 0xff4040e0,
- 0xff8040e0, 0xffc040e0, 0xff0060e0, 0xff4060e0, 0xff8060e0, 0xffc060e0,
- 0xff0080e0, 0xff4080e0, 0xff8080e0, 0xffc080e0, 0xff00a0e0, 0xff40a0e0,
- 0xff80a0e0, 0xffc0a0e0, 0xff00c0e0, 0xff40c0e0, 0xff80c0e0, 0xffc0c0e0,
- 0xff00e0e0, 0xff40e0e0, 0xff80e0e0, 0xffc0e0e0,
-};
-
-const uint grey256[256] = {
- 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
- 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
- 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff111111, 0xff111111,
- 0xff111111, 0xff111111, 0xff111111, 0xff111111, 0xff111111, 0xff111111,
- 0xff111111, 0xff111111, 0xff111111, 0xff111111, 0xff111111, 0xff111111,
- 0xff111111, 0xff111111, 0xff222222, 0xff222222, 0xff222222, 0xff222222,
- 0xff222222, 0xff222222, 0xff222222, 0xff222222, 0xff222222, 0xff222222,
- 0xff222222, 0xff222222, 0xff222222, 0xff222222, 0xff222222, 0xff222222,
- 0xff333333, 0xff333333, 0xff333333, 0xff333333, 0xff333333, 0xff333333,
- 0xff333333, 0xff333333, 0xff333333, 0xff333333, 0xff333333, 0xff333333,
- 0xff333333, 0xff333333, 0xff333333, 0xff333333, 0xff444444, 0xff444444,
- 0xff444444, 0xff444444, 0xff444444, 0xff444444, 0xff444444, 0xff444444,
- 0xff444444, 0xff444444, 0xff444444, 0xff444444, 0xff444444, 0xff444444,
- 0xff444444, 0xff444444, 0xff555555, 0xff555555, 0xff555555, 0xff555555,
- 0xff555555, 0xff555555, 0xff555555, 0xff555555, 0xff555555, 0xff555555,
- 0xff555555, 0xff555555, 0xff555555, 0xff555555, 0xff555555, 0xff555555,
- 0xff666666, 0xff666666, 0xff666666, 0xff666666, 0xff666666, 0xff666666,
- 0xff666666, 0xff666666, 0xff666666, 0xff666666, 0xff666666, 0xff666666,
- 0xff666666, 0xff666666, 0xff666666, 0xff666666, 0xff777777, 0xff777777,
- 0xff777777, 0xff777777, 0xff777777, 0xff777777, 0xff777777, 0xff777777,
- 0xff777777, 0xff777777, 0xff777777, 0xff777777, 0xff777777, 0xff777777,
- 0xff777777, 0xff777777, 0xff888888, 0xff888888, 0xff888888, 0xff888888,
- 0xff888888, 0xff888888, 0xff888888, 0xff888888, 0xff888888, 0xff888888,
- 0xff888888, 0xff888888, 0xff888888, 0xff888888, 0xff888888, 0xff888888,
- 0xff999999, 0xff999999, 0xff999999, 0xff999999, 0xff999999, 0xff999999,
- 0xff999999, 0xff999999, 0xff999999, 0xff999999, 0xff999999, 0xff999999,
- 0xff999999, 0xff999999, 0xff999999, 0xff999999, 0xffaaaaaa, 0xffaaaaaa,
- 0xffaaaaaa, 0xffaaaaaa, 0xffaaaaaa, 0xffaaaaaa, 0xffaaaaaa, 0xffaaaaaa,
- 0xffaaaaaa, 0xffaaaaaa, 0xffaaaaaa, 0xffaaaaaa, 0xffaaaaaa, 0xffaaaaaa,
- 0xffaaaaaa, 0xffaaaaaa, 0xffbbbbbb, 0xffbbbbbb, 0xffbbbbbb, 0xffbbbbbb,
- 0xffbbbbbb, 0xffbbbbbb, 0xffbbbbbb, 0xffbbbbbb, 0xffbbbbbb, 0xffbbbbbb,
- 0xffbbbbbb, 0xffbbbbbb, 0xffbbbbbb, 0xffbbbbbb, 0xffbbbbbb, 0xffbbbbbb,
- 0xffcccccc, 0xffcccccc, 0xffcccccc, 0xffcccccc, 0xffcccccc, 0xffcccccc,
- 0xffcccccc, 0xffcccccc, 0xffcccccc, 0xffcccccc, 0xffcccccc, 0xffcccccc,
- 0xffcccccc, 0xffcccccc, 0xffcccccc, 0xffcccccc, 0xffdddddd, 0xffdddddd,
- 0xffdddddd, 0xffdddddd, 0xffdddddd, 0xffdddddd, 0xffdddddd, 0xffdddddd,
- 0xffdddddd, 0xffdddddd, 0xffdddddd, 0xffdddddd, 0xffdddddd, 0xffdddddd,
- 0xffdddddd, 0xffdddddd, 0xffeeeeee, 0xffeeeeee, 0xffeeeeee, 0xffeeeeee,
- 0xffeeeeee, 0xffeeeeee, 0xffeeeeee, 0xffeeeeee, 0xffeeeeee, 0xffeeeeee,
- 0xffeeeeee, 0xffeeeeee, 0xffeeeeee, 0xffeeeeee, 0xffeeeeee, 0xffeeeeee,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
- 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
-};
-
cOsdPipObject::cOsdPipObject(cDevice *Device, const cChannel *Channel):
cOsdObject(true) {
m_Channel = Channel;
m_Osd = NULL;
- m_ESBuffer = new cRingBufferLinear(MEGABYTE(3), 0, true);
+ m_ESBuffer = new cRingBufferFrame(MEGABYTE(3), true);
m_Active = false;
m_Ready = false;
m_Width = m_Height = -1;
m_Bitmap = NULL;
+ m_AlphaBase = 0xFF000000;
+ memset(m_Palette, 0, 1024);
+ m_PaletteStart = 0;
+
Device->SwitchChannel(m_Channel, false);
m_Receiver = new cOsdPipReceiver(m_Channel, m_ESBuffer);
Device->AttachReceiver(m_Receiver);
@@ -126,75 +45,270 @@ cOsdPipObject::~cOsdPipObject() {
delete m_Osd;
}
+int cOsdPipObject::Decode(unsigned char * data, int length) {
+ int gotPicture, len;
+
+ len = avcodec_decode_video(m_Context, m_PicDecoded, &gotPicture, data, length);
+ if (len < 0)
+ {
+ printf("Error while decoding frame\n");
+ return -1;
+ }
+ if (!gotPicture)
+ {
+ return -1;
+ }
+
+ return 0;
+}
+
+int cOsdPipObject::Resample() {
+ ImgReSampleContext * contextResample;
+
+ contextResample = img_resample_full_init(m_Width, m_Height,
+ m_Context->width, m_Context->height,
+ OsdPipSetup.CropTop, OsdPipSetup.CropBottom,
+ OsdPipSetup.CropLeft, OsdPipSetup.CropRight);
+ if (!contextResample) {
+ printf("Error initializing resample context.\n");
+ return -1;
+ }
+ avpicture_fill((AVPicture *) m_PicResample, m_BufferResample,
+ PIX_FMT_YUV420P, m_Width, m_Height);
+ img_resample(contextResample, (AVPicture *) m_PicResample, (AVPicture *) m_PicDecoded);
+ img_resample_close(contextResample);
+
+ return 0;
+}
+
+int cOsdPipObject::ConvertToRGB() {
+ avpicture_fill((AVPicture *) m_PicConvert, m_BufferConvert,
+ PIX_FMT_RGBA32, m_Width, m_Height);
+ img_convert((AVPicture *) m_PicConvert, PIX_FMT_RGBA32,
+ (AVPicture *) m_PicResample, PIX_FMT_YUV420P,
+ m_Width, m_Height);
+
+ return 0;
+}
+
+void cOsdPipObject::ProcessImage(unsigned char * data, int length) {
+ unsigned int value;
+ unsigned int * outputPalette;
+ unsigned char * outputImage;
+
+ if (OsdPipSetup.FrameMode == kFrameModeI) {
+ if (m_FrameDrop == OsdPipSetup.FrameDrop) {
+ m_FrameDrop = 0;
+ } else {
+ m_FrameDrop++;
+ return;
+ }
+ }
+
+ if (Decode(data, length) != 0)
+ return;
+
+ if (OsdPipSetup.FrameMode == kFrameModeIP ||
+ OsdPipSetup.FrameMode == kFrameModeIPB) {
+ if (m_FrameDrop == OsdPipSetup.FrameDrop) {
+ m_FrameDrop = 0;
+ } else {
+ m_FrameDrop++;
+ return;
+ }
+ }
+
+ if (!m_Ready) {
+ switch (OsdPipSetup.Size) {
+ case 0:
+ m_Width = 120;
+ m_Height = 96;
+ break;
+ case 1:
+ m_Width = 160;
+ m_Height = 128;
+ break;
+ case 2:
+ m_Width = 200;
+ m_Height = 160;
+ break;
+ case 3:
+ m_Width = 240;
+ m_Height = 192;
+ break;
+ case 4:
+ m_Width = 280;
+ m_Height = 224;
+ break;
+ case 5:
+ m_Width = 320;
+ m_Height = 256;
+ break;
+ }
+ m_Window = m_Osd->Create(OsdPipSetup.XPosition, OsdPipSetup.YPosition,
+ m_Width, m_Height, OsdPipSetup.ColorDepth == kDepthGrey16 ? 4 : 8, false);
+ m_Bitmap = new cBitmap(m_Width, m_Height,
+ OsdPipSetup.ColorDepth == kDepthGrey16 ? 4 : 8, false);
+ if (OsdPipSetup.ColorDepth == kDepthGrey128)
+ for (unsigned int i = 0; i < 256; i++) {
+ m_Palette[i] = m_AlphaBase | (i << 16) | (i << 8) | i;
+ }
+ m_Ready = true;
+ }
+
+ if (Resample() != 0)
+ return;
+
+ int size;
+ size = m_Width * m_Height;
+
+ if (OsdPipSetup.ColorDepth == kDepthGrey16) {
+ outputImage = m_PicResample->data[0];
+ m_Bitmap->Clear();
+ for (int y = 0; y < m_Height; y++) {
+ for (int x = 0; x < m_Width; x++) {
+ value = outputImage[y * m_Width + x];
+ value = value / 16;
+ value = value * 16;
+ value = m_AlphaBase | (value << 16) | (value << 8) | value;
+ m_Bitmap->SetPixel(x, y, (eDvbColor) value);
+ }
+ }
+ }
+ if (OsdPipSetup.ColorDepth == kDepthGrey128) {
+ outputImage = m_PicResample->data[0];
+ m_Bitmap->Clear();
+ for (int y = 0; y < m_Height; y++) {
+ for (int x = 0; x < m_Width; x++) {
+ m_Bitmap->SetPixel(x, y, (eDvbColor) m_Palette[outputImage[y * m_Width + x] & 0xFE]);
+ }
+ }
+ }
+ if (OsdPipSetup.ColorDepth == kDepthColor256fix ||
+ OsdPipSetup.ColorDepth == kDepthColor128var) {
+ if (ConvertToRGB() != 0)
+ return;
+
+ if (OsdPipSetup.SwapFfmpeg) {
+ unsigned int * bufPtr = (unsigned int *) m_BufferConvert;
+ 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(m_BufferConvert, size, 128);
+
+ outputPalette = quantizer->OutputPalette();
+ outputImage = quantizer->OutputImage();
+ if (OsdPipSetup.ColorDepth == kDepthColor256fix) {
+ for (int i = 0; i < 256; i++)
+ m_Palette[i] = m_AlphaBase | outputPalette[i];
+
+ m_Bitmap->Clear();
+ for (int y = 0; y < m_Height; y++) {
+ for (int x = 0; x < m_Width; x++) {
+ m_Bitmap->SetPixel(x, y, (eDvbColor) m_Palette[outputImage[y * m_Width + x]]);
+ }
+ }
+ } else {
+ for (int i = 0; i < 128; i++)
+ {
+ m_Palette[m_PaletteStart + i] = outputPalette[i];
+ m_Palette[m_PaletteStart + i] |= m_AlphaBase;
+ }
+
+ m_Bitmap->Clear();
+ for (int i = 0; i < 256; i++)
+ m_Bitmap->SetColor(i, (eDvbColor) m_Palette[i]);
+ for (int y = 0; y < m_Height; y++) {
+ for (int x = 0; x < m_Width; x++) {
+ m_Bitmap->SetIndex(x, y, m_PaletteStart + outputImage[y * m_Width + x]);
+ }
+ }
+
+ if (m_PaletteStart == 0)
+ m_PaletteStart = 128;
+ else
+ m_PaletteStart = 0;
+ }
+ }
+
+ m_Osd->Clear();
+ m_Osd->SetBitmap(OsdPipSetup.XPosition, OsdPipSetup.YPosition,
+ *m_Bitmap);
+ m_Osd->Flush();
+}
+
void cOsdPipObject::Action(void) {
m_Active = true;
isyslog("osdpip: decoder thread started (pid = %d)", getpid());
- mpeg2dec_t *handle = mpeg2_init();
- const mpeg2_info_t *info = mpeg2_info(handle);
- mpeg2_state_t state;
+ m_Codec = avcodec_find_decoder(CODEC_ID_MPEG1VIDEO);
+ if (!m_Codec)
+ {
+ printf("codec not found\n");
+ }
+ m_Context = avcodec_alloc_context();
+ if (avcodec_open(m_Context, m_Codec) < 0)
+ {
+ printf("could not open codec\n");
+ }
+ m_PicDecoded = avcodec_alloc_frame();
+ m_PicResample = avcodec_alloc_frame();
+ m_BufferResample = new unsigned char[(400 * 300 * 3) / 2]; // size for YUV 420
+ m_PicConvert = avcodec_alloc_frame();
+ m_BufferConvert = new unsigned char[400 * 300 * 4]; // size for RGBA32
+
+ 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) {
- const uchar *block;
- int recvd;
-
- state = mpeg2_parse(handle);
- switch (state) {
- case STATE_BUFFER:
- block = m_ESBuffer->Get(recvd);
- if (block && recvd > 0) {
- mpeg2_buffer(handle, (uint8_t*)block, (uint8_t*)block + recvd);
- m_ESBuffer->Del(recvd);
- } else
+ frame = m_ESBuffer->Get();
+ {
+ if (frame && frame->Count() > 0) {
+ pictureType = frame->Index();
+ if ((OsdPipSetup.FrameMode == kFrameModeI &&
+ pictureType == I_FRAME) ||
+ (OsdPipSetup.FrameMode == kFrameModeIP &&
+ (pictureType == I_FRAME || pictureType == P_FRAME)) ||
+ (OsdPipSetup.FrameMode == kFrameModeIPB)) {
+ ProcessImage(frame->Data(), frame->Count());
+ }
+ m_ESBuffer->Drop(frame);
+ } else {
+ if (frame)
+ m_ESBuffer->Drop(frame);
usleep(1);
- break;
-
- case STATE_SEQUENCE:
- if (!m_Ready) {
- m_Width = (info->sequence->width - OsdPipSetup.CropLeft
- - OsdPipSetup.CropRight) / OsdPipSetup.ZoomFactor;
- m_Height = (info->sequence->height - OsdPipSetup.CropTop
- - OsdPipSetup.CropBottom) / OsdPipSetup.ZoomFactor;
- m_Window = m_Osd->Create(OsdPipSetup.XPosition, OsdPipSetup.YPosition,
- m_Width, m_Height, OsdPipSetup.ColorDepth == 0 ? 4 : 8);
- m_Bitmap = new cBitmap(m_Width, m_Height,
- OsdPipSetup.ColorDepth == 0 ? 4 : 8);
- m_Ready = true;
}
- mpeg2_convert(handle, mpeg2convert_rgb8, NULL);
- break;
-
- case STATE_SLICE:
- case STATE_END:
- case STATE_INVALID_END:
- if (m_Ready && info->display_fbuf && (info->display_picture->flags
- & PIC_MASK_CODING_TYPE) == PIC_FLAG_CODING_TYPE_I) {
- int px = OsdPipSetup.CropLeft;
- int py = OsdPipSetup.CropRight;
- for (int x = 0; x < m_Width; ++x) {
- for (int y = 0; y < m_Height; ++y) {
- uint8_t idx = info->display_fbuf->buf[0][py
- * info->sequence->width + px];
- uint col = OsdPipSetup.ColorDepth == 0 ? grey256[idx] : rgb256[idx];
-
- m_Bitmap->SetPixel(x, y, (eDvbColor)col);
- py += OsdPipSetup.ZoomFactor;
- }
- px += OsdPipSetup.ZoomFactor;
- py = 0;
- }
- m_Osd->SetBitmap(OsdPipSetup.XPosition, OsdPipSetup.YPosition,
- *m_Bitmap);
- m_Osd->Flush();
- }
- break;
-
- default:
- break;
- }
+ }
}
+ if (OsdPipSetup.ColorDepth == kDepthColor128var ||
+ OsdPipSetup.ColorDepth == kDepthColor256fix)
+ delete quantizer;
+ delete[] m_BufferConvert;
+ free(m_PicConvert);
+ delete[] m_BufferResample;
+ free(m_PicResample);
+ avcodec_close(m_Context);
+ free(m_Context);
+ free(m_PicDecoded);
+
isyslog("osdpip: decoder thread stopped");
}
@@ -261,3 +375,4 @@ eOSState cOsdPipObject::ProcessKey(eKeys Key) {
}
return state;
}
+