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
|
#include <assert.h>
#include <stdlib.h>
#include <SDL2/SDL_surface.h>
#include "kitchensink/kiterror.h"
#include "kitchensink/internal/utils/kitlog.h"
#include "kitchensink/internal/subtitle/kitatlas.h"
#include "kitchensink/internal/subtitle/kitsubtitlepacket.h"
#include "kitchensink/internal/subtitle/renderers/kitsubimage.h"
static void ren_render_image_cb(Kit_SubtitleRenderer *ren, void *sub_src, double start_pts, double end_pts) {
assert(ren != NULL);
assert(sub_src != NULL);
AVSubtitle *sub = sub_src;
SDL_Surface *dst = NULL, *src = NULL;
// If this subtitle has no rects, we still need to clear screen from old subs
if(sub->num_rects == 0) {
Kit_WriteDecoderOutput(
ren->dec, Kit_CreateSubtitlePacket(true, start_pts, end_pts, 0, 0, NULL));
return;
}
// Convert subtitle images from paletted to RGBA8888
for(int n = 0; n < sub->num_rects; n++) {
AVSubtitleRect *r = sub->rects[n];
if(r->type != SUBTITLE_BITMAP)
continue;
src = SDL_CreateRGBSurfaceWithFormatFrom(
r->data[0], r->w, r->h, 8, r->linesize[0], SDL_PIXELFORMAT_INDEX8);
SDL_SetPaletteColors(src->format->palette, (SDL_Color*)r->data[1], 0, 256);
dst = SDL_CreateRGBSurfaceWithFormat(
0, r->w, r->h, 32, SDL_PIXELFORMAT_RGBA32);
// Blit source to target and free source surface.
SDL_BlitSurface(src, NULL, dst, NULL);
// Create a new packet and write it to output buffer
Kit_WriteDecoderOutput(
ren->dec, Kit_CreateSubtitlePacket(false, start_pts, end_pts, r->x, r->y, dst));
// Free surfaces
SDL_FreeSurface(src);
SDL_FreeSurface(dst);
}
}
static int ren_get_data_cb(Kit_SubtitleRenderer *ren, Kit_TextureAtlas *atlas, double current_pts) {
// Read any new packets to atlas
Kit_SubtitlePacket *packet = NULL;
// Clean dead packets
while((packet = Kit_PeekDecoderOutput(ren->dec)) != NULL) {
if(packet->pts_end < current_pts) {
Kit_AdvanceDecoderOutput(ren->dec);
Kit_FreeSubtitlePacket(packet);
continue;
}
if(packet->pts_start < current_pts) {
if(packet->clear) {
Kit_ClearAtlasContent(atlas);
}
if(packet->surface != NULL) {
SDL_Rect target;
target.x = packet->x;
target.y = packet->y;
target.w = packet->surface->w;
target.h = packet->surface->h;
Kit_AddAtlasItem(atlas, packet->surface, &target);
}
Kit_AdvanceDecoderOutput(ren->dec);
Kit_FreeSubtitlePacket(packet);
ren->dec->clock_pos = current_pts;
continue;
}
break;
}
return 0;
}
Kit_SubtitleRenderer* Kit_CreateImageSubtitleRenderer(Kit_Decoder *dec, int w, int h) {
assert(dec != NULL);
assert(w >= 0);
assert(h >= 0);
// Allocate a new renderer
Kit_SubtitleRenderer *ren = Kit_CreateSubtitleRenderer(dec);
if(ren == NULL) {
return NULL;
}
// Only renderer required, no other data.
ren->ren_render = ren_render_image_cb;
ren->ren_get_data = ren_get_data_cb;
ren->ren_close = NULL;
ren->userdata = NULL;
return ren;
}
|