Welcome to mirror list, hosted at ThFree Co, Russian Federation.

SubRenderIntf.h « include - github.com/mpc-hc/mpc-hc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: d248795a9519bb8ef843a6e2f605b4602f5d431d (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
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
// ***************************************************************
//  SubRenderIntf.h           version: 1.0.8  -  date: 2014-03-06
//  -------------------------------------------------------------
//  Copyright (C) 2011-2014, BSD license
// ***************************************************************

// 2014-03-06 1.0.8 added ISubRenderConsumer2::Clear() interface/method
// 2014-03-05 1.0.7 auto-loading is now the provider's own responsibility
// 2013-07-01 1.0.6 added support for TV level subtitle transport
// 2013-06-05 1.0.5 added support for BT.2020 matrix
// 2012-12-04 1.0.4 changed auto-loading to supports multiple sub renderers
// 2012-10-15 1.0.3 (1) added some comments about interface management
//                  (2) added "context" parameter to "Request/DeliverFrame"
// 2012-09-11 1.0.2 (1) modified "yuvMatrix" fields to match Aegisub ("None")
//                  (2) added a clarification about LPWSTR property case
// 2012-08-30 1.0.1 (1) added mandatory consumer field "arAdjustedVideoSize"
//                  (2) added "subtitle color correction" info text
//                  (3) added mandatory provider field "yuvMatrix"
//                  (4) modified optional consumer field "yuvMatrix"
// 2011-12-20 1.0.0 initial release

// ---------------------------------------------------------------------------
// introduction
// ---------------------------------------------------------------------------

// This header defines a set of interfaces which a subtitle renderer can
// export to make its services available. The purpose of these interfaces is
// to allow a more flexible communication between subtitle renderer and
// subtitle consumer (e.g. video renderer) than DirectShow allows.

// A typical DirectShow subtitle renderer using these interfaces would have
// a subtitle input pin, but no video input pin and no output pins.

// ---------------------------------------------------------------------------
// basic interface principle
// ---------------------------------------------------------------------------

// (1) The subtitle consumer exports the interface "ISubRenderConsumer" and
//     waits for a subtitle renderer to connect.

// (2) The first time the graph is paused or started the subtitle renderer
//     searches through the DirectShow graph and looks for filters which
//     expose the "ISubRenderConsumer" interface.

// (3) If there are multiple subtitle consumers in the graph, the subtitle
//     renderer needs to decide which one to service. This should be done by
//     picking the consumer with the highest merit. There's a "GetMerit()"
//     method in the "ISubRenderConsumer" interface for this purpose.

// (4) Once the subtitle renderer has found a consumer it wants to service,
//     it calls "ISubRenderConsumer.Connect()", providing the consumer with
//     the "ISubRenderProvider" interface, which allows the consumer to
//     configure the subtitle renderer and to fetch rendered subtitles.

// ---------------------------------------------------------------------------
// subtitle color correction
// ---------------------------------------------------------------------------

// Today we have a number of different subtitle formats which define colors
// in different color spaces. E.g. SRT subtitles are usually considered to be
// native RGB, while DVD and Blu-Ray bitmap subtitles are native YCbCr.

// The most difficult to handle format is ASS. ASS subtitle colors are defined
// as RGB values. However, the historically most commonly used ASS renderer
// (VSFilter) and the most commonly used ASS authoring software (Aegisub) both
// render subtitles by drawing them directly onto the YCbCr video. Furthermore
// up until very recently Aegisub always used to convert all videos to RGB by
// using the BT.601 matrix. Practically that means that almost every ASS
// subtitle file out there which is color matched to the video, requires
// rendering in the same way, with hard coded BT.601 matrix, in order to ensure
// that subtitle and video colors match exactly.

// The subtitle interface defined in this header file passes subtitles from
// the subtitle provider to the consumer in RGB format. Since some subtitle
// formats are native YCbCr and due to the ASS color problem mentioned above,
// it may be necessary to perform color correction to guarantee that the
// rendered subtitle colors match perfectly to the video colors.

// When rendering native YCbCr subtitles (DVD and Blu-Ray bitmap subtitles),
// the subtitle renderer should try to use the correct YCbCr -> RGB matrix.
// The subtitle renderer may either use the "yuvMatrix" information field
// which the subtitle consumer may optionally provide. Or alternatively the
// subtitle renderer can auto guess the correct matrix based on subtitle
// resolution. The subtitle renderer informs the consumer about the matrix
// that was used for subtitle YCbCr -> RGB conversion by setting the
// "yuvMatrix" information field.

// When rendering native RGB subtitles (e.g. SRT), the subtitle renderer
// should render the subtitles untouched, and set the "yuvMatrix" information
// field to "None".

// When rendering ASS subtitles, the subtitle renderer should render the
// subtitles in untouched RGB. If the ASS subtitle file has a "yuvMatrix"
// header field, the subtitle renderer has to forward this field to the
// subtitle consumer. If the ASS subtitle file does not have a "yuvMatrix"
// header field, the subtitle renderer should set the "yuvMatrix" field to
// "TV.601".

// Subtitle consumers should read the subtitle renderer's "yuvMatrix" field.
// If it is set to anything other than "None", the subtitle consumer should
// double check whether the subtitle matrix matches the video matrix. If the
// matrixes differ, the consumer should perform the necessary color correction
// to make sure that subtitle and video colors match perfectly.

// ---------------------------------------------------------------------------
// subtitle levels
// ---------------------------------------------------------------------------

// Subtitles are by default transported as premultiplied RGBA pixels with
// PC levels (black = 0; white = 255). All consumers and providers are
// required to support this format.

// Optionally, the consumer can signal (see "supportedLevels" info field)
// that it supports TV levels, too. If it does (and only then), the provider
// can optionally output subtitles in TV levels. If it does, it has to set
// the info field "outputLevels" to "TV".

// ---------------------------------------------------------------------------
// subtitle repositioning
// ---------------------------------------------------------------------------

// In certain situations a user might have specific wishes for subtitle
// positioning. E.g. a 4:3 TV owner may want to have subtitles rendered into
// the big black bars on his TV, when watching 16:9 content. Or a CIH front
// projection owner may want to have subtitles rendered into the active video
// area instead of the black bars of the Cinemascope movie.

// Now some subtitle sources (e.g. many fan made ASS subtitles for Anime) are
// designed to be positioned very exactly. Other subtitle formats (e.g. SRT)
// don't care about positioning at all. The consumer doesn't really know
// which formats can be repostioned and which can't. So this interface allows
// the consumer to express a wish for subtitle positioning. The subtitle
// renderer can then decide whether it can (and wants to) honor this wish.

// If the consumer wants subtitles to be moved, he sets "subtitleTargetRect"
// to a different value (can be bigger or smaller) than "videoOutputRect".

// Example 1: anamorphic 16:9 DVD playback, 4:3 computer monitor
// consumer sets:
// - displayModeSize,     1024x768
// - originalVideoSize,   720x480
// - arAdjustedVideoSize, 853x480
// - videoOutputRect,     0x96x1024x672
// - subtitleTargetRect,  0x0x1024x768                   <-  move request
// subtitle renderer provides:
// - ISubRender.GetVideoOutputRect() -> 0x0x720x480
// - ISubRender.GetClipRect()        -> 0x-80x720x560    <-  request granted

// Example 2: anamorphic 16:9 DVD playback, CIH front projection
// consumer sets:
// - displayModeSize,     1920x1080
// - originalVideoSize,   720x480
// - arAdjustedVideoSize, 853x480
// - videoOutputRect,     0x0x1920x1080
// - subtitleTargetRect,  0x140x1920x940                 <-  move request
// subtitle renderer provides:
// - ISubRender.GetVideoOutputRect() -> 0x0x720x480
// - ISubRender.GetClipRect()        -> 0x62x720x418     <-  request granted

// Example 3: reencoded Anime, ASS subtitles, CIH front projection
// consumer sets:
// - displayModeSize,     1920x1080
// - originalVideoSize,   853x480
// - arAdjustedVideoSize, 853x480
// - videoOutputRect,     0x0x1920x1080
// - subtitleTargetRect,  0x140x1920x940                 <-  move request
// subtitle renderer provides:
// - ISubRender.GetVideoOutputRect() -> 0x0x1920x1080
// - ISubRender.GetClipRect()        -> 0x0x1920x1080    <-  request denied

// ---------------------------------------------------------------------------

#ifndef __SubtitleInterface__
#define __SubtitleInterface__

interface ISubRenderConsumer;
interface ISubRenderProvider;
interface ISubRenderFrame;

// ---------------------------------------------------------------------------
// ISubRenderOptions
// ---------------------------------------------------------------------------

// Base interface for both ISubRenderConsumer and ISubRenderProvider.

[uuid("7CFD3728-235E-4430-9A2D-9F25F426BD70")]
interface ISubRenderOptions : public IUnknown
{
  // Allows one party to get information from the other party.
  // The memory for strings and binary data is allocated by the callee
  // by using LocalAlloc. It is the caller's responsibility to release the
  // memory by calling LocalFree.
  // Field names and LPWSTR values should be read case insensitive.
  STDMETHOD(GetBool     )(LPCSTR field, bool      *value) = 0;
  STDMETHOD(GetInt      )(LPCSTR field, int       *value) = 0;
  STDMETHOD(GetSize     )(LPCSTR field, SIZE      *value) = 0;
  STDMETHOD(GetRect     )(LPCSTR field, RECT      *value) = 0;
  STDMETHOD(GetUlonglong)(LPCSTR field, ULONGLONG *value) = 0;
  STDMETHOD(GetDouble   )(LPCSTR field, double    *value) = 0;
  STDMETHOD(GetString   )(LPCSTR field, LPWSTR    *value, int *chars) = 0;
  STDMETHOD(GetBin      )(LPCSTR field, LPVOID    *value, int *size ) = 0;

  // Allows one party to configure or send information to the other party.
  // The callee should copy the strings/binary data, if needed.
  // Field names and LPWSTR values should be set with the exact case listed
  // in this header (just to be safe).
  STDMETHOD(SetBool     )(LPCSTR field, bool      value) = 0;
  STDMETHOD(SetInt      )(LPCSTR field, int       value) = 0;
  STDMETHOD(SetSize     )(LPCSTR field, SIZE      value) = 0;
  STDMETHOD(SetRect     )(LPCSTR field, RECT      value) = 0;
  STDMETHOD(SetUlonglong)(LPCSTR field, ULONGLONG value) = 0;
  STDMETHOD(SetDouble   )(LPCSTR field, double    value) = 0;
  STDMETHOD(SetString   )(LPCSTR field, LPWSTR    value, int chars) = 0;
  STDMETHOD(SetBin      )(LPCSTR field, LPVOID    value, int size ) = 0;

  // "field" must be zero terminated

  // mandatory fields for consumers:
  // "name",                LPWSTR,    info,   read only,  get name / description of the consumer
  // "version",             LPWSTR,    info,   read only,  get version number of the consumer
  // "originalVideoSize",   SIZE,      info,   read only,  size of the video before scaling and AR adjustments
  // "arAdjustedVideoSize", SIZE,      info,   read only,  size of the video after AR adjustments
  // "videoOutputRect",     RECT,      info,   read only,  final pos/size of the video after all scaling operations
  // "subtitleTargetRect",  RECT,      info,   read only,  consumer wish for where to place the subtitles
  // "frameRate",           ULONGLONG, info,   read only,  frame rate of the video after deinterlacing (REFERENCE_TIME)
  // "refreshRate",         double,    info,   read only,  display refresh rate (0, if unknown)

  // mandatory fields for providers:
  // "name",                LPWSTR,    info,   read only,  get name / description of the provider
  // "version",             LPWSTR,    info,   read only,  get version number of the provider
  // "yuvMatrix",           LPWSTR,    info,   read only,  RGB Subtitles: "None" (fullrange); YCbCr Subtitles: "Levels.Matrix", Levels: TV|PC, Matrix: 601|709|240M|FCC|2020
  // "combineBitmaps",      bool,      option, write/read, must the provider combine all bitmaps into one? (default: false)

  // optional fields for consumers:
  // "displayModeSize",     SIZE,      info,   read only,  display mode width/height
  // "yuvMatrix",           LPWSTR,    info,   read only,  RGB Video: "None" (fullrange); YCbCr Video: "Levels.Matrix", Levels: TV|PC, Matrix: 601|709|240M|FCC|2020
  // "supportedLevels",     int,       info,   read only,  0: PC only (default); 1: PC+TV, no preference; 2: PC+TV, PC preferred; 3: PC+TV, TV preferred

  // optional fields for providers:
  // "outputLevels",        LPWSTR,    info,   read only,  are subtitles rendered/output in RGB "PC" (default) or "TV" levels?
};

// ---------------------------------------------------------------------------
// ISubRenderConsumer
// ---------------------------------------------------------------------------

// This interface is exposed by every subtitle consumer.

[uuid("9DF90966-FE9F-4F0E-881E-DAF8A572D900")]
interface ISubRenderConsumer : public ISubRenderOptions
{
  // Called by the subtitle renderer to ask the merit of the consumer.
  // Recommended merits:
  // - Subtitle Manager     0x00080000
  // - Video Renderer       0x00040000
  // - Video Post Processor 0x00020000
  // - Video Decoder        0x00010000
  STDMETHOD(GetMerit)(ULONG *merit) = 0;

  // Called by the subtitle renderer to init the provider <-> consumer
  // connection. The subtitle renderer provides an "ISubRenderProvider"
  // interface for the consumer to store and use. The consumer should
  // call "AddRef()" to make sure that the interface instance stays alive
  // as long as needed.
  STDMETHOD(Connect)(ISubRenderProvider *subtitleRenderer) = 0;

  // Called by the subtitle renderer to close the connection. The
  // consumer should react by immediately "Release()"ing the stored
  // "ISubRenderProvider" instance.
  STDMETHOD(Disconnect)(void) = 0;

  // Called by the subtitle renderer to deliver a rendered subtitle frame
  // to the consumer. The renderer may only deliver frames which were
  // requested before by the consumer.
  // The frames will be delivered in the same order as they were requested.
  // The deliverance can occur in different threads than the request, though.
  // The subtitle renderer can deliver a "NULL" subtitle frame to indicate
  // that the specified frame has no visible subtitles. The subtitle renderer
  // can also reuse the same "ISubRenderFrame" instance for multiple video
  // frames, if the subtitles didn't change.
  // The consumer should "AddRef()" the "ISubRenderFrame", if the consumer
  // wants to use it after returning from "DeliverFrame()". If the consumer
  // does that, it also needs to call "Release()" later when the
  // "ISubRenderFrame" instance is no longer needed.
  // The subtitle renderer should not require the "ISubRenderFrame" instance
  // to be released immediately. The consumer may store it for buffering/queue
  // purposes. All properties of the "ISubRenderFrame" instance must return
  // the correct results until it is released by the consumer.
  STDMETHOD(DeliverFrame)(REFERENCE_TIME start, REFERENCE_TIME stop, LPVOID context, ISubRenderFrame *subtitleFrame) = 0;
};

[uuid("1A1737C8-2BF8-4BEA-97EA-3AB4FA8F7AC9")]
interface ISubRenderConsumer2 : public ISubRenderConsumer
{
  // Called by the subtitle renderer e.g. when the user switches to a
  // different subtitle track. The consumer should immediately release
  // all stored subtitle frames and request them anew from the subtitle
  // renderer.
  STDMETHOD(Clear)(REFERENCE_TIME clearNewerThan = 0) = 0;
};

// ---------------------------------------------------------------------------
// ISubRenderProvider
// ---------------------------------------------------------------------------

// The subtitle renderer provides the consumer with this interface, when
// calling the "ISubRenderConsumer.Connect()" method.

[uuid("20752113-C883-455A-BA7B-ABA4E9115CA8")]
interface ISubRenderProvider : public ISubRenderOptions
{
  // Called by the consumer to request a rendered subtitle frame.
  // The subtitle renderer will deliver the frame when it is completed, by
  // calling "ISubRenderConsumer.DeliverFrame()".
  // The subtitle renderer must pass the "context" parameter to the
  // consumer when calling "DeliverFrame()".
  // Depending on the internal thread design of the subtitle renderer,
  // "RequestFrame()" can return at once, with delivery being performed
  // asynchronously in a different thread. Alternatively, "RequestFrame()"
  // may also block until the frame was delivered. The consumer should not
  // depend on either threading model, but leave this decision to the
  // subtitle renderer.
  STDMETHOD(RequestFrame)(REFERENCE_TIME start, REFERENCE_TIME stop, LPVOID context) = 0;

  // Called by the consumer to close the connection. The subtitle renderer
  // should react by immediately "Release()"ing any stored
  // "ISubRenderConsumer" interface instances pointing to this specific
  // consumer.
  STDMETHOD(Disconnect)(void) = 0;
};

// ---------------------------------------------------------------------------
// ISubRenderFrame
// ---------------------------------------------------------------------------

// This interface is the reply to a consumer's frame render request.

[uuid("81746AB5-9407-4B43-A014-1FAAC340F973")]
interface ISubRenderFrame : public IUnknown
{
  // "GetOutputRect()" specifies for which video rect the subtitles were
  // rendered. If the subtitle renderer doesn't scale the subtitles at all,
  // which is the recommended method for bitmap (DVD/PGS) subtitles formats,
  // GetOutputRect() should return "0, 0, originalVideoSize". If the subtitle
  // renderer scales the subtitles, which is the recommend method for text
  // (SRT, ASS) subtitle formats, GetOutputRect() should aim to match the
  // consumer's "videoOutputRect". In any case, the consumer can look at
  // GetOutputRect() to see if (and how) the rendered subtitles need to be
  // scaled before blending them onto the video image.
  STDMETHOD(GetOutputRect)(RECT *outputRect) = 0;

  // "GetClipRect()" specifies how the consumer should clip the rendered
  // subtitles, before blending them onto the video image. Usually,
  // GetClipRect() should be identical to "GetVideoOutputRect()", unless the
  // subtitle renderer repositioned the subtitles (see the top of this header
  // for more information about repositioning).
  STDMETHOD(GetClipRect)(RECT *clipRect) = 0;

  // How many separate bitmaps does this subtitle frame consist of?
  // The subtitle renderer should combine small subtitle elements which are
  // positioned near to each other, in order to optimize performance.
  // Ideally, if there are e.g. two subtitle lines, one at the top and one
  // at the bottom of the frame, the subtitle renderer should output two
  // bitmaps per frame.
  STDMETHOD(GetBitmapCount)(int *count) = 0;

  // Returns the premultiplied RGBA pixel data for the specified bitmap.
  // The ID is guaranteed to change if the content of the bitmap has changed.
  // The ID can stay identical if only the position changes.
  // Reusing the same ID for unchanged bitmaps can improve performance.
  // Subtitle bitmaps may move in and out of the video frame rectangle, so
  // the position of the subtitle bitmaps can become negative. The consumer
  // is required to do proper clipping if the subtitle bitmap is partially
  // outside the video rectangle.
  // The memory pointed to by "pixels" is only valid until the next
  // "GetBitmap" call, or until the "ISubRenderFrame" instance is released.
  STDMETHOD(GetBitmap)(int index, ULONGLONG *id, POINT *position, SIZE *size, LPCVOID *pixels, int *pitch) = 0;
};

// ===========================================================================

#endif // __SubtitelInterface__