/** * Decode subtitles from LAVC */ static void video_subtitles_lavc(video_decoder_t *vd, media_buf_t *mb, AVCodecContext *ctx) { AVSubtitle sub; int size = 0, i, x, y; video_overlay_t *vo; AVPacket avpkt; av_init_packet(&avpkt); avpkt.data = mb->mb_data; avpkt.size = mb->mb_size; if(avcodec_decode_subtitle2(ctx, &sub, &size, &avpkt) < 1 || size < 1) return; if(sub.num_rects == 0) { // Flush screen vo = calloc(1, sizeof(video_overlay_t)); vo->vo_type = VO_TIMED_FLUSH; vo->vo_start = mb->mb_pts + sub.start_display_time * 1000; video_overlay_enqueue(vd, vo); return; } for(i = 0; i < sub.num_rects; i++) { AVSubtitleRect *r = sub.rects[i]; switch(r->type) { case SUBTITLE_BITMAP: vo = calloc(1, sizeof(video_overlay_t)); vo->vo_start = mb->mb_pts + sub.start_display_time * 1000; vo->vo_stop = mb->mb_pts + sub.end_display_time * 1000; vo->vo_x = r->x; vo->vo_y = r->y; vo->vo_pixmap = pixmap_create(r->w, r->h, PIX_FMT_BGR32, 1); const uint8_t *src = r->pict.data[0]; const uint32_t *clut = (uint32_t *)r->pict.data[1]; uint32_t *dst = (uint32_t *)vo->vo_pixmap->pm_pixels; for(y = 0; y < r->h; y++) { for(x = 0; x < r->w; x++) { *dst++ = clut[src[x]]; } src += r->pict.linesize[0]; } video_overlay_enqueue(vd, vo); break; case SUBTITLE_ASS: sub_ass_render(vd, r->ass, ctx->subtitle_header, ctx->subtitle_header_size); break; default: break; } } }
/** * Decode subtitles from LAVC */ static void video_subtitles_lavc(media_pipe_t *mp, media_buf_t *mb, AVCodecContext *ctx) { AVSubtitle sub; int got_sub = 0, i, x, y; video_overlay_t *vo; AVPacket avpkt; av_init_packet(&avpkt); avpkt.data = mb->mb_data; avpkt.size = mb->mb_size; if(avcodec_decode_subtitle2(ctx, &sub, &got_sub, &avpkt) < 1 || !got_sub) return; if(sub.num_rects == 0) { // Flush screen vo = calloc(1, sizeof(video_overlay_t)); vo->vo_type = VO_TIMED_FLUSH; vo->vo_start = mb->mb_pts + sub.start_display_time * 1000; video_overlay_enqueue(mp, vo); } else { for(i = 0; i < sub.num_rects; i++) { AVSubtitleRect *r = sub.rects[i]; switch(r->type) { case SUBTITLE_BITMAP: vo = calloc(1, sizeof(video_overlay_t)); vo->vo_start = mb->mb_pts + sub.start_display_time * 1000; vo->vo_stop = mb->mb_pts + sub.end_display_time * 1000; vo->vo_canvas_width = ctx->width; vo->vo_canvas_height = ctx->height; vo->vo_x = r->x; vo->vo_y = r->y; vo->vo_pixmap = pixmap_create(r->w, r->h, PIXMAP_BGR32, 0); if(vo->vo_pixmap == NULL) { free(vo); break; } const uint8_t *src = r->pict.data[0]; const uint32_t *clut = (uint32_t *)r->pict.data[1]; for(y = 0; y < r->h; y++) { uint32_t *dst = (uint32_t *)(vo->vo_pixmap->pm_pixels + y * vo->vo_pixmap->pm_linesize); for(x = 0; x < r->w; x++) *dst++ = clut[src[x]]; src += r->pict.linesize[0]; } video_overlay_enqueue(mp, vo); break; case SUBTITLE_ASS: sub_ass_render(mp, r->ass, ctx->subtitle_header, ctx->subtitle_header_size, mb->mb_font_context); break; default: break; } } } avsubtitle_free(&sub); }