Skip to content

Instantly share code, notes, and snippets.

@izacus
Created July 19, 2014 20:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save izacus/26a624df7b5536191c84 to your computer and use it in GitHub Desktop.
Save izacus/26a624df7b5536191c84 to your computer and use it in GitHub Desktop.
AVSubtitle with indexed color conversion to AVFrame
// Colorspace conversion macro definitions from ffplay
#define RGBA_IN(r, g, b, a, s)\
{\
unsigned int v = ((const uint32_t *)(s))[0];\
a = (v >> 24) & 0xff;\
r = (v >> 16) & 0xff;\
g = (v >> 8) & 0xff;\
b = v & 0xff;\
}
AVFrame* sub_to_frame(AVSubtitle* sub, int width, int height)
{
if (sub->num_rects == 0)
return nullptr;
AVPicture rgba_picture;
avpicture_alloc(&rgba_picture, AV_PIX_FMT_RGBA, SUB_WINDOW_WIDTH, SUB_WINDOW_HEIGHT);
memset(rgba_picture.data[0], 0, SUB_WINDOW_WIDTH * SUB_WINDOW_HEIGHT * 4);
// Copy subtitle before conversion
int r, g, b, a;
for (unsigned int i = 0; i < sub->num_rects; i ++)
{
for (int j = 0; j < sub->rects[i]->nb_colors; j++)
{
AVSubtitleRect* rect = sub->rects[i];
RGBA_IN(r, g, b, a, (uint32_t*)rect->pict.data[1] + j);
// Blend rectangle to frame
for (int y = rect->y; y < rect->y + rect->h; y++)
{
uint8_t* pd = rgba_picture.data[0] + (y * rgba_picture.linesize[0]) + (rect->x * 4);
uint8_t* rd = rect->pict.data[0] + ((y - rect->y) * rect->pict.linesize[0]);
for (int k = 0; k < rect->w; k++)
{
RGBA_IN(r, g, b, a, (uint32_t*)rect->pict.data[1] + rd[0]);
pd[0] = r;
pd[1] = g;
pd[2] = b;
pd[3] = a;
pd += 4;
rd ++;
}
}
}
}
AVFrame* sub_frame = avcodec_alloc_frame();
avpicture_alloc((AVPicture*)sub_frame, AV_PIX_FMT_YUVA420P, width, height);
sub_rgba_to_yuva_ctx = sws_getCachedContext(sub_rgba_to_yuva_ctx, SUB_WINDOW_WIDTH, SUB_WINDOW_HEIGHT, AV_PIX_FMT_RGBA,
width, height, AV_PIX_FMT_YUVA420P,
SWS_LANCZOS, NULL, NULL, NULL);
sws_scale(sub_rgba_to_yuva_ctx, (const uint8_t* const*)rgba_picture.data, rgba_picture.linesize, 0, SUB_WINDOW_HEIGHT, sub_frame->data, sub_frame->linesize);
sub_frame->width = width;
sub_frame->height= height;
sub_frame->format = AV_PIX_FMT_YUVA420P;
avpicture_free(&rgba_picture);
return sub_frame;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment