Example #1
0
static void old_avsub_to_spudec(AVSubtitleRect **rects, int num_rects,
                                double pts, double endpts)
{
    int i, xmin = INT_MAX, ymin = INT_MAX, xmax = INT_MIN, ymax = INT_MIN;
    struct spu_packet_t *packet;

    if (num_rects == 1) {
        spudec_set_paletted(vo_spudec,
                            rects[0]->pict.data[0],
                            rects[0]->pict.linesize[0],
                            rects[0]->pict.data[1],
                            rects[0]->x,
                            rects[0]->y,
                            rects[0]->w,
                            rects[0]->h,
                            pts,
                            endpts);
        return;
    }
    for (i = 0; i < num_rects; i++) {
        xmin = FFMIN(xmin, rects[i]->x);
        ymin = FFMIN(ymin, rects[i]->y);
        xmax = FFMAX(xmax, rects[i]->x + rects[i]->w);
        ymax = FFMAX(ymax, rects[i]->y + rects[i]->h);
    }
    packet = spudec_packet_create(xmin, ymin, xmax - xmin, ymax - ymin);
    if (!packet)
        return;
    spudec_packet_clear(packet);
    for (i = 0; i < num_rects; i++)
        spudec_packet_fill(packet,
                           rects[i]->pict.data[0],
                           rects[i]->pict.linesize[0],
                           rects[i]->pict.data[1],
                           rects[i]->x - xmin,
                           rects[i]->y - ymin,
                           rects[i]->w,
                           rects[i]->h);
    spudec_packet_send(vo_spudec, packet, pts, endpts);
}
Example #2
0
/**
 * Decode a subtitle packet via libavcodec.
 * \return < 0 on error, > 0 if further processing is needed
 */
int decode_avsub(struct sh_sub *sh, uint8_t **data, int *size,
                 double *pts, double *endpts)
{
    AVCodecContext *ctx = sh->context;
    enum CodecID cid = CODEC_ID_NONE;
    int new_type = 0;
    int res;
    int got_sub;
    AVSubtitle sub;
    AVPacket pkt;

    switch (sh->type) {
    case 'b':
        cid = CODEC_ID_DVB_SUBTITLE; break;
    case 'p':
        cid = CODEC_ID_HDMV_PGS_SUBTITLE; break;
    case 'x':
        cid = CODEC_ID_XSUB; break;
    }

    av_init_packet(&pkt);
    pkt.data = *data;
    pkt.size = *size;
    pkt.pts = *pts * 1000;
    if (*pts != MP_NOPTS_VALUE && *endpts != MP_NOPTS_VALUE)
        pkt.convergence_duration = (*endpts - *pts) * 1000;
    if (!ctx) {
        AVCodec *sub_codec;
        init_avcodec();
        ctx = avcodec_alloc_context3(NULL);
        sub_codec = avcodec_find_decoder(cid);
        if (!ctx || !sub_codec || avcodec_open2(ctx, sub_codec, NULL) < 0) {
            mp_msg(MSGT_SUBREADER, MSGL_FATAL,
                   "Could not open subtitle decoder\n");
            av_freep(&ctx);
            return -1;
        }
        sh->context = ctx;
    }
    res = avcodec_decode_subtitle2(ctx, &sub, &got_sub, &pkt);
    if (res < 0)
        return res;
    if (*pts != MP_NOPTS_VALUE) {
        if (sub.end_display_time > sub.start_display_time)
            *endpts = *pts + sub.end_display_time / 1000.0;
        *pts += sub.start_display_time / 1000.0;
    }
    if (got_sub && vo_spudec && sub.num_rects == 0)
        spudec_set_paletted(vo_spudec, NULL, 0, NULL, 0, 0, 0, 0, *pts, *endpts);
    if (got_sub && sub.num_rects > 0) {
        switch (sub.rects[0]->type) {
        case SUBTITLE_BITMAP:
            if (!vo_spudec)
                vo_spudec = spudec_new_scaled(NULL, ctx->width, ctx->height, NULL, 0);
            spudec_set_paletted(vo_spudec,
                                sub.rects[0]->pict.data[0],
                                sub.rects[0]->pict.linesize[0],
                                sub.rects[0]->pict.data[1],
                                sub.rects[0]->x,
                                sub.rects[0]->y,
                                sub.rects[0]->w,
                                sub.rects[0]->h,
                                *pts,
                                *endpts);
            vo_osd_changed(OSDTYPE_SPU);
            break;
        case SUBTITLE_TEXT:
            *data = strdup(sub.rects[0]->text);
            *size = strlen(*data);
            new_type = 't';
            break;
        case SUBTITLE_ASS:
            *data = strdup(sub.rects[0]->ass);
            *size = strlen(*data);
            new_type = 'a';
            break;
        }
    }
    if (got_sub)
        avsubtitle_free(&sub);
    return new_type;
}
Example #3
0
static void decode(struct sh_sub *sh, struct osd_state *osd, void *data,
                   int data_len, double pts, double duration)
{
    struct sd_lavc_priv *priv = sh->context;
    AVCodecContext *ctx = priv->avctx;
    AVSubtitle sub;
    AVPacket pkt;

    clear(priv);
    av_init_packet(&pkt);
    pkt.data = data;
    pkt.size = data_len;
    pkt.pts = pts * 1000;
    if (duration >= 0)
        pkt.convergence_duration = duration * 1000;
    int got_sub;
    int res = avcodec_decode_subtitle2(ctx, &sub, &got_sub, &pkt);
    if (res < 0 || !got_sub)
        return;
    if (pts != MP_NOPTS_VALUE) {
        if (sub.end_display_time > sub.start_display_time)
            duration = (sub.end_display_time - sub.start_display_time) / 1000.0;
        pts += sub.start_display_time / 1000.0;
    }
    double endpts = MP_NOPTS_VALUE;
    if (pts != MP_NOPTS_VALUE && duration >= 0)
        endpts = pts + duration;
    if (vo_spudec && sub.num_rects == 0)
        spudec_set_paletted(vo_spudec, NULL, 0, NULL, 0, 0, 0, 0, pts, endpts);
    if (sub.num_rects > 0) {
        switch (sub.rects[0]->type) {
        case SUBTITLE_BITMAP:
            // Assume resolution heuristics only work for PGS and DVB
            if (!osd->support_rgba || sh->type != 'p' && sh->type != 'b') {
                if (!vo_spudec)
                    vo_spudec = spudec_new_scaled(NULL, ctx->width, ctx->height,
                                                  NULL, 0);
                old_avsub_to_spudec(sub.rects, sub.num_rects, pts, endpts);
                vo_osd_changed(OSDTYPE_SPU);
                break;
            }
            priv->inbitmaps = talloc_array(priv, struct sub_bitmap,
                                           sub.num_rects);
            for (int i = 0; i < sub.num_rects; i++) {
                struct AVSubtitleRect *r = sub.rects[i];
                struct sub_bitmap *b = &priv->inbitmaps[i];
                uint32_t *outbmp = talloc_size(priv->inbitmaps,
                                               r->w * r->h * 4);
                b->bitmap = outbmp;
                b->w = r->w;
                b->h = r->h;
                b->x = r->x;
                b->y = r->y;
                uint8_t *inbmp = r->pict.data[0];
                uint32_t *palette = (uint32_t *) r->pict.data[1];
                for (int y = 0; y < r->h; y++) {
                    for (int x = 0; x < r->w; x++)
                        *outbmp++ = palette[*inbmp++];
                    inbmp += r->pict.linesize[0] - r->w;
                };
            }
            priv->count = sub.num_rects;
            priv->endpts = endpts;
            break;
        default:
            mp_msg(MSGT_SUBREADER, MSGL_ERR, "sd_lavc: unsupported subtitle "
                   "type from libavcodec\n");
            break;
        }
    }
    avsubtitle_free(&sub);
}