Пример #1
0
static void fill_plaintext(struct sd *sd, double pts)
{
    struct sd_ass_priv *ctx = sd->priv;
    ASS_Track *track = ctx->shadow_track;

    ass_flush_events(track);

    char *text = get_text(sd, pts);
    if (!text)
        return;

    bstr dst = {0};
    while (*text) {
        if (*text == '{')
            bstr_xappend(NULL, &dst, bstr0("\\"));
        bstr_xappend(NULL, &dst, (bstr){text, 1});
        // Break ASS escapes with U+2060 WORD JOINER
        if (*text == '\\')
            mp_append_utf8_bstr(NULL, &dst, 0x2060);
        text++;
    }

    if (!dst.start || !dst.start[0])
        return;

    int n = ass_alloc_event(track);
    ASS_Event *event = track->events + n;
    event->Start = 0;
    event->Duration = INT_MAX;
    event->Style = track->default_style;
    event->Text = strdup(dst.start);

    if (track->default_style < track->n_styles)
        track->styles[track->default_style].Alignment = ctx->on_top ? 6 : 2;
}
Пример #2
0
static void decode(struct sd *sd, struct demux_packet *packet)
{
    struct sd_ass_priv *ctx = sd->priv;
    ASS_Track *track = ctx->ass_track;
    long long ipts = packet->pts * 1000 + 0.5;
    long long iduration = packet->duration * 1000 + 0.5;
    if (strcmp(sd->codec, "ass") == 0) {
        ass_process_chunk(track, packet->buffer, packet->len, ipts, iduration);
        return;
    } else if (strcmp(sd->codec, "ssa") == 0) {
        // broken ffmpeg ASS packet format
        ctx->flush_on_seek = true;
        ass_process_data(track, packet->buffer, packet->len);
        return;
    }

    // plaintext subs
    if (packet->pts == MP_NOPTS_VALUE) {
        MP_WARN(sd, "Subtitle without pts, ignored\n");
        return;
    }
    if (ctx->extend_event >= 0 && ctx->extend_event < track->n_events) {
        ASS_Event *event = &track->events[ctx->extend_event];
        if (event->Start <= ipts)
            event->Duration = ipts - event->Start;
        ctx->extend_event = -1;
    }

    unsigned char *text = packet->buffer;
    if (!sd->no_remove_duplicates) {
        for (int i = 0; i < track->n_events; i++) {
            if (track->events[i].Start == ipts
                && (track->events[i].Duration == iduration)
                && strcmp(track->events[i].Text, text) == 0)
                return;   // We've already added this subtitle
        }
    }
    int eid = ass_alloc_event(track);
    ASS_Event *event = track->events + eid;

    if (packet->duration == 0) {
        MP_WARN(sd, "Subtitle without duration or "
                "duration set to 0 at pts %f.\n", packet->pts);
    }
    if (packet->duration < 0) {
        // Assume unknown duration. The FFmpeg API is very unclear about this.
        MP_WARN(sd, "Assuming subtitle without duration at pts %f\n", packet->pts);
        // _If_ there's a next subtitle, the duration will be adjusted again.
        // If not, show it forever.
        iduration = INT_MAX;
        ctx->extend_event = eid;
    }

    event->Start = ipts;
    event->Duration = iduration;
    event->Style = track->default_style;
    event->Text = strdup(text);
}
Пример #3
0
static void decode(struct sh_sub *sh, struct osd_state *osd, void *data,
                   int data_len, double pts, double duration)
{
    unsigned char *text = data;
    struct sd_ass_priv *ctx = sh->context;
    ASS_Track *track = ctx->ass_track;

    if (sh->type == 'a') { // ssa/ass subs
        ass_process_chunk(track, data, data_len,
                          (long long)(pts*1000 + 0.5),
                          (long long)(duration*1000 + 0.5));
        return;
    }
    // plaintext subs
    if (pts == MP_NOPTS_VALUE) {
        mp_msg(MSGT_SUBREADER, MSGL_WARN, "Subtitle without pts, ignored\n");
        return;
    }
    long long ipts = pts * 1000 + 0.5;
    long long iduration = duration * 1000 + 0.5;
    if (ctx->incomplete_event) {
        ctx->incomplete_event = false;
        ASS_Event *event = track->events + track->n_events - 1;
        if (ipts <= event->Start)
            free_last_event(track);
        else
            event->Duration = ipts - event->Start;
    }
    // Note: we rely on there being guaranteed 0 bytes after data packets
    int len = strlen(text);
    if (len < 5) {
        // Some tracks use a whitespace (but not empty) packet to mark end
        // of previous subtitle.
        for (int i = 0; i < len; i++)
            if (!strchr(" \f\n\r\t\v", text[i]))
                goto not_all_whitespace;
        return;
    }
 not_all_whitespace:;
    char buf[500];
    subassconvert_subrip(text, buf, sizeof(buf));
    for (int i = 0; i < track->n_events; i++)
        if (track->events[i].Start == ipts
            && (duration <= 0 || track->events[i].Duration == iduration)
            && strcmp(track->events[i].Text, buf) == 0)
            return;   // We've already added this subtitle
    if (duration <= 0) {
        iduration = 10000;
        ctx->incomplete_event = true;
    }
    int eid = ass_alloc_event(track);
    ASS_Event *event = track->events + eid;
    event->Start = ipts;
    event->Duration = iduration;
    event->Style = track->default_style;
    event->Text = strdup(buf);
}
Пример #4
0
void LibASS::addASSEvent(const QByteArray &text, double Start, double Duration)
{
	if (!ass_sub_track || !ass_sub_renderer || text.isEmpty() || Start < 0 || Duration < 0)
		return;
	int eventID = ass_alloc_event(ass_sub_track);
	ASS_Event *event = &ass_sub_track->events[eventID];
	event->Text = strdup(text.data());
	event->Start = Start * 1000;
	event->Duration = Duration * 1000;
	event->Style = 0;
	event->ReadOrder = eventID;
}
Пример #5
0
/**
 * \brief Convert subtitle to ASS_Events for the given track
 * \param track track
 * \param sub subtitle to convert
 * \return event id
 * note: assumes that subtitle is _not_ fps-based; caller must manually correct
 *   Start and Duration in other case.
 **/
static int ass_process_subtitle(ASS_Track *track, subtitle *sub)
{
    int eid;
    ASS_Event *event;
    int len = 0, j;
    char *p;
    char *end;

    eid = ass_alloc_event(track);
    event = track->events + eid;

    event->Start = sub->start * 10;
    event->Duration = (sub->end - sub->start) * 10;
    event->Style = 0;

    for (j = 0; j < sub->lines; ++j)
        len += sub->text[j] ? strlen(sub->text[j]) : 0;

    len += 2 * sub->lines;      // '\N', including the one after the last line
    len += 6;                   // {\anX}
    len += 1;                   // '\0'

    event->Text = malloc(len);
    end = event->Text + len;
    p = event->Text;

    if (sub->alignment)
        p += snprintf(p, end - p, "{\\an%d}", sub->alignment);

    for (j = 0; j < sub->lines; ++j)
        p += snprintf(p, end - p, "%s\\N", sub->text[j]);

    if (sub->lines > 0)
        p -= 2;                 // remove last "\N"
    *p = 0;

    if (check_duplicate_plaintext_event(track)) {
        ass_free_event(track, eid);
        track->n_events--;
        return -1;
    }

    mp_msg(MSGT_ASS, MSGL_V,
           "plaintext event at %" PRId64 ", +%" PRId64 ": %s  \n",
           (int64_t) event->Start, (int64_t) event->Duration, event->Text);

    return eid;
}
Пример #6
0
Файл: sd_ass.c Проект: agiz/mpv
static void decode(struct sd *sd, struct demux_packet *packet)
{
    struct sd_ass_priv *ctx = sd->priv;
    ASS_Track *track = ctx->ass_track;
    long long ipts = packet->pts * 1000 + 0.5;
    long long iduration = packet->duration * 1000 + 0.5;
    if (strcmp(sd->codec, "ass") == 0) {
        ass_process_chunk(track, packet->buffer, packet->len, ipts, iduration);
        return;
    } else if (strcmp(sd->codec, "ssa") == 0) {
        // broken ffmpeg ASS packet format
        ctx->flush_on_seek = true;
        ass_process_data(track, packet->buffer, packet->len);
        return;
    }
    // plaintext subs
    if (packet->pts == MP_NOPTS_VALUE) {
        mp_msg(MSGT_SUBREADER, MSGL_WARN, "Subtitle without pts, ignored\n");
        return;
    }
    if (packet->duration <= 0) {
        mp_msg(MSGT_SUBREADER, MSGL_WARN, "Subtitle without duration or "
               "duration set to 0 at pts %f, ignored\n", packet->pts);
        return;
    }
    unsigned char *text = packet->buffer;
    if (!sd->no_remove_duplicates) {
        for (int i = 0; i < track->n_events; i++) {
            if (track->events[i].Start == ipts
                && (track->events[i].Duration == iduration)
                && strcmp(track->events[i].Text, text) == 0)
                return;   // We've already added this subtitle
        }
    }
    int eid = ass_alloc_event(track);
    ASS_Event *event = track->events + eid;
    event->Start = ipts;
    event->Duration = iduration;
    event->Style = track->default_style;
    event->Text = strdup(text);
}
Пример #7
0
void LibASS::initOSD()
{
	if (osd_track && osd_style && osd_event && osd_renderer)
		return;

	osd_track = ass_new_track(ass);

	int styleID = ass_alloc_style(osd_track);
	osd_style = &osd_track->styles[styleID];
	setOSDStyle();

	int eventID = ass_alloc_event(osd_track);
	osd_event = &osd_track->events[eventID];
	osd_event->Start = 0;
	osd_event->Duration = 1;
	osd_event->Style = styleID;
	osd_event->ReadOrder = eventID;

	osd_renderer = ass_renderer_init(ass);
	ass_set_fonts(osd_renderer, NULL, NULL, 1, NULL, 1);
}