summaryrefslogtreecommitdiff
path: root/gst/dvdspu/gstdvdspu.h
blob: 0432a3af9aa104ed333434f49a4fdc7da65094f8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
/* GStreamer DVD Sub-Picture Unit
 * Copyright (C) 2007 Fluendo S.A. <info@fluendo.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */
#ifndef __DVD_SPU_H__
#define __DVD_SPU_H__

#include <gst/gst.h>

G_BEGIN_DECLS

#define GST_TYPE_DVD_SPU \
  (gst_dvd_spu_get_type())
#define GST_DVD_SPU(obj) \
  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DVD_SPU,GstDVDSpu))
#define GST_DVD_SPU_CLASS(klass) \
  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DVD_SPU,GstDVDSpuClass))
#define GST_IS_DVD_SPU(obj) \
  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DVD_SPU))
#define GST_IS_DVD_SPU_CLASS(klass) \
  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DVD_SPU))

#define DVD_SPU_LOCK(s) g_mutex_lock ((s)->spu_lock);
#define DVD_SPU_UNLOCK(s) g_mutex_unlock ((s)->spu_lock);

typedef struct _GstDVDSpu      GstDVDSpu;
typedef struct _GstDVDSpuClass GstDVDSpuClass;

typedef struct SpuRect SpuRect;
typedef struct SpuPixCtrlI SpuPixCtrlI;
typedef struct SpuLineCtrlI SpuLineCtrlI;
typedef struct SpuColour SpuColour;
typedef enum SpuStateFlags SpuStateFlags;
typedef struct SpuState SpuState;
typedef struct SpuPacket SpuPacket;
typedef enum SpuCmd SpuCmd;

/* Describe the limits of a rectangle */
struct SpuRect {
  gint16 left;
  gint16 top;
  gint16 right;
  gint16 bottom;
};

/* Store a pre-multiplied colour value. The YUV fields hold the YUV values
 * multiplied by the 8-bit alpha, to save computing it while rendering */
struct SpuColour {
  guint16 Y;
  guint16 U;
  guint16 V;
  guint8 A;
};

/* Pixel Control Info from a Change Color Contrast command */
struct SpuPixCtrlI {
  gint16 left;
  guint32 palette;

  /* Pre-multiplied palette values, updated as
   * needed */
  SpuColour pal_cache[4];
};

struct SpuLineCtrlI {
  guint8 n_changes; /* 1 to 8 */
  SpuPixCtrlI pix_ctrl_i[8];

  gint16 top;
  gint16 bottom;
};

enum SpuCmd {
  SPU_CMD_FSTA_DSP     = 0x00, /* Forced Display */
  SPU_CMD_DSP          = 0x01, /* Display Start */
  SPU_CMD_STP_DSP      = 0x02, /* Display Off */
  SPU_CMD_SET_COLOR    = 0x03, /* Set the color indexes for the palette */
  SPU_CMD_SET_ALPHA    = 0x04, /* Set the alpha indexes for the palette */
  SPU_CMD_SET_DAREA    = 0x05, /* Set the display area for the SPU */
  SPU_CMD_DSPXA        = 0x06, /* Pixel data addresses */
  SPU_CMD_CHG_COLCON   = 0x07, /* Change Color & Contrast */
  SPU_CMD_END          = 0xff
};

enum SpuStateFlags {
  SPU_STATE_NONE        = 0x00,
  /* Flags cleared on a flush */
  SPU_STATE_DISPLAY     = 0x01,
  SPU_STATE_FORCED_DSP  = 0x02,
  SPU_STATE_STILL_FRAME = 0x04,
  /* Persistent flags */
  SPU_STATE_FORCED_ONLY = 0x100
};

#define SPU_STATE_FLAGS_MASK (0xff)

struct SpuState {
  GstClockTime next_ts; /* Next event TS in running time */

  GstClockTime base_ts; /* base TS for cmd blk delays in running time */
  GstBuffer *buf; /* Current SPU packet we're executing commands from */
  guint16 cur_cmd_blk; /* Offset into the buf for the current cmd block */

  SpuStateFlags flags;
  
  /* Top + Bottom field offsets in the buffer. 0 = not set */
  guint16 pix_data[2]; 
  GstBuffer *pix_buf; /* Current SPU packet the pix_data references */
  
  SpuRect disp_rect;
  SpuRect hl_rect;

  guint32 current_clut[16]; /* Colour lookup table from incoming events */

  guint8 main_idx[4]; /* Indices for current main palette */
  guint8 main_alpha[4]; /* Alpha values for main palette */

  guint8 hl_idx[4]; /* Indices for current highlight palette */
  guint8 hl_alpha[4]; /* Alpha values for highlight palette */

  /* Pre-multiplied colour palette for the main palette */
  SpuColour main_pal[4];
  gboolean main_pal_dirty;

  /* Line control info for rendering the highlight palette */
  SpuLineCtrlI hl_ctrl_i;
  gboolean hl_pal_dirty; /* Indicates that the HL palette info needs refreshing */

  /* LineCtrlI Info from a Change Color & Contrast command */
  SpuLineCtrlI *line_ctrl_i;
  gint16 n_line_ctrl_i;
  gboolean line_ctrl_i_pal_dirty; /* Indicates that the palettes for the line_ctrl_i
                                   * need recalculating */

  /* Rendering state vars below */
  guint16 *comp_bufs[3]; /* Compositing buffers for U+V & A */
  gint16 comp_last_x[2]; /* Maximum X values we rendered into the comp buffer (odd & even) */
  gint16 *comp_last_x_ptr; /* Ptr to the current comp_last_x value to be updated by the render */
  gint16 vid_width, vid_height;
  gint16 Y_stride, UV_stride;
  gint16 Y_height, UV_height;

  gint fps_n, fps_d;

  /* Current Y Position */
  gint16 cur_Y;

  /* Current offset in nibbles into the pix_data */
  guint16 cur_offsets[2];
  guint16 max_offset;

  /* current ChgColCon Line Info */
  SpuLineCtrlI *cur_chg_col;
  SpuLineCtrlI *cur_chg_col_end;

  /* Output position tracking */
  guint8  *out_Y;
  guint16 *out_U;
  guint16 *out_V;
  guint16 *out_A;
};

/* Structure used to store the queue of pending SPU packets. The start_ts is
 * stored in running time... 
 * Also used to carry in-band events so they remain serialised properly */
struct SpuPacket {
  GstClockTime event_ts;
  GstBuffer *buf;
  GstEvent *event;
};

struct _GstDVDSpu {
  GstElement element;

  GstPad *videosinkpad;
  GstPad *subpic_sinkpad;
  GstPad *srcpad;

  /* Mutex to protect state we access from different chain funcs */
  GMutex *spu_lock;

  GstSegment video_seg;
  GstSegment subp_seg;

  SpuState spu_state;

  /* GQueue of SpuBuf structures */
  GQueue *pending_spus;

  /* Accumulator for collecting partial SPU buffers until they're complete */
  GstBuffer *partial_spu;

  /* Store either a reference or a copy of the last video frame for duplication
   * during still-frame conditions */
  GstBuffer *ref_frame;

  /* Buffer to push after handling a DVD event, if any */
  GstBuffer *pending_frame;
};

struct _GstDVDSpuClass {
  GstElementClass parent_class;
};

GType gst_dvd_spu_get_type (void);

G_END_DECLS

#endif /* __DVD_SPU_H__ */