static int write_frame(struct AVFormatContext *s, int stream_index, AVFrame **frame, unsigned flags) { AVBPrint bp; int ret = 0; enum AVMediaType type; const char *type_name; if ((flags & AV_WRITE_UNCODED_FRAME_QUERY)) return 0; av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED); av_bprintf(&bp, "%d, %10"PRId64"", stream_index, (*frame)->pts); type = s->streams[stream_index]->codec->codec_type; type_name = av_get_media_type_string(type); av_bprintf(&bp, ", %s", type_name ? type_name : "unknown"); switch (type) { case AVMEDIA_TYPE_VIDEO: video_frame_cksum(&bp, *frame); break; case AVMEDIA_TYPE_AUDIO: audio_frame_cksum(&bp, *frame); break; } av_bprint_chars(&bp, '\n', 1); if (av_bprint_is_complete(&bp)) avio_write(s->pb, bp.str, bp.len); else ret = AVERROR(ENOMEM); av_bprint_finalize(&bp, NULL); return ret; }
static void video_frame_cksum(AVBPrint *bp, AVFrame *frame) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format); int i, y; uint8_t *data; int linesize[5] = { 0 }; av_bprintf(bp, ", %d x %d", frame->width, frame->height); if (!desc) { av_bprintf(bp, ", unknown"); return; } if (av_image_fill_linesizes(linesize, frame->format, frame->width) < 0) return; av_bprintf(bp, ", %s", desc->name); for (i = 0; linesize[i]; i++) { unsigned cksum = 0; int h = frame->height; if ((i == 1 || i == 2) && desc->nb_components >= 3) h = AV_CEIL_RSHIFT(h, desc->log2_chroma_h); data = frame->data[i]; for (y = 0; y < h; y++) { cksum = av_adler32_update(cksum, data, linesize[i]); data += frame->linesize[i]; } av_bprintf(bp, ", 0x%08x", cksum); } }
static int rt_event_to_ass(AVBPrint *buf, const char *p) { int prev_chr_is_space = 1; while (*p) { if (*p != '<') { if (!isspace(*p)) av_bprint_chars(buf, *p, 1); else if (!prev_chr_is_space) av_bprint_chars(buf, ' ', 1); prev_chr_is_space = isspace(*p); } else { const char *end = strchr(p, '>'); if (!end) break; if (!av_strncasecmp(p, "<br/>", 5) || !av_strncasecmp(p, "<br>", 4)) { av_bprintf(buf, "\\N"); } p = end; } p++; } av_bprintf(buf, "\r\n"); return 0; }
static int webvtt_event_to_ass(AVBPrint *buf, const char *p) { int i, skip = 0; while (*p) { for (i = 0; i < FF_ARRAY_ELEMS(webvtt_tag_replace); i++) { const char *from = webvtt_tag_replace[i].from; const size_t len = strlen(from); if (!strncmp(p, from, len)) { av_bprintf(buf, "%s", webvtt_tag_replace[i].to); p += len; break; } } if (!*p) break; if (*p == '<') skip = 1; else if (*p == '>') skip = 0; else if (p[0] == '\n' && p[1]) av_bprintf(buf, "\\N"); else if (!skip && *p != '\r') av_bprint_chars(buf, *p, 1); p++; } av_bprintf(buf, "\r\n"); return 0; }
static void format_line(void *ptr, int level, const char *fmt, va_list vl, AVBPrint part[3], int *print_prefix, int type[2]) { AVClass* avc = ptr ? *(AVClass **) ptr : NULL; av_bprint_init(part+0, 0, 1); av_bprint_init(part+1, 0, 1); av_bprint_init(part+2, 0, 65536); if(type) type[0] = type[1] = AV_CLASS_CATEGORY_NA + 16; if (*print_prefix && avc) { if (avc->parent_log_context_offset) { AVClass** parent = *(AVClass ***) (((uint8_t *) ptr) + avc->parent_log_context_offset); if (parent && *parent) { av_bprintf(part+0, "[%s @ %p] ", (*parent)->item_name(parent), parent); if(type) type[0] = get_category(parent); } } av_bprintf(part+1, "[%s @ %p] ", avc->item_name(ptr), ptr); if(type) type[1] = get_category(ptr); } av_vbprintf(part+2, fmt, vl); if(*part[0].str || *part[1].str || *part[2].str) { char lastc = part[2].len ? part[2].str[part[2].len - 1] : 0; *print_prefix = lastc == '\n' || lastc == '\r'; } }
static int print_link_prop(AVBPrint *buf, AVFilterLink *link) { char *format; char layout[64]; if (!buf) buf = &(AVBPrint){ 0 }; /* dummy buffer */ switch (link->type) { case AVMEDIA_TYPE_VIDEO: format = av_x_if_null(av_get_pix_fmt_name(link->format), "?"); av_bprintf(buf, "[%dx%d %d:%d %s]", link->w, link->h, link->sample_aspect_ratio.num, link->sample_aspect_ratio.den, format); break; case AVMEDIA_TYPE_AUDIO: av_get_channel_layout_string(layout, sizeof(layout), -1, link->channel_layout); format = av_x_if_null(av_get_sample_fmt_name(link->format), "?"); av_bprintf(buf, "[%dHz %s:%s:%s]", (int)link->sample_rate, format, layout, link->planar ? "planar" : "packed"); break; default: av_bprintf(buf, "?"); break; } return buf->len; }
int ff_ass_add_rect(AVSubtitle *sub, const char *dialog, int ts_start, int duration, int raw) { AVBPrint buf; int ret, dlen; AVSubtitleRect **rects; av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); if (!raw) { av_bprintf(&buf, "Dialogue: 0,"); insert_ts(&buf, ts_start); insert_ts(&buf, duration == -1 ? -1 : ts_start + duration); av_bprintf(&buf, "Default,"); } dlen = strcspn(dialog, "\n"); dlen += dialog[dlen] == '\n'; av_bprintf(&buf, "%.*s", dlen, dialog); if (!av_bprint_is_complete(&buf)) return AVERROR(ENOMEM); rects = av_realloc(sub->rects, (sub->num_rects+1) * sizeof(*sub->rects)); if (!rects) return AVERROR(ENOMEM); sub->rects = rects; sub->end_display_time = FFMAX(sub->end_display_time, 10 * duration); rects[sub->num_rects] = av_mallocz(sizeof(*rects[0])); rects[sub->num_rects]->type = SUBTITLE_ASS; ret = av_bprint_finalize(&buf, &rects[sub->num_rects]->ass); if (ret < 0) return ret; sub->num_rects++; return dlen; }
static void microdvd_close_no_persistent_tags(AVBPrint *new_line, struct microdvd_tag *tags) { int i, sidx; for (i = sizeof(MICRODVD_TAGS) - 2; i >= 0; i--) { if (tags[i].persistent != MICRODVD_PERSISTENT_OFF) continue; switch (tags[i].key) { case 'y': for (sidx = sizeof(MICRODVD_STYLES) - 2; sidx >= 0; sidx--) if (tags[i].data1 & (1 << sidx)) av_bprintf(new_line, "{\\%c0}", MICRODVD_STYLES[sidx]); break; case 'c': av_bprintf(new_line, "{\\c}"); break; case 'f': av_bprintf(new_line, "{\\fn}"); break; case 's': av_bprintf(new_line, "{\\fs}"); break; } tags[i].key = 0; } }
EXPORT int duplicate_stream(void *actx,enum DuplicateFormat format) { int ret = 0; struct liveStream *ctx = (struct liveStream *)actx; if(!ctx) return -1; av_bprint_init(&ctx->graph_desc, 0, 1); if(format == SIDE_BY_SIDE) av_bprintf(&ctx->graph_desc, "[0]format=yuv420p,scale=iw/2:ih,pad=iw*2:ih[main];[main]split[dup1][dup2];[dup1][dup2]overlay=W/2:0[bg]"); else if ( format == TOP_N_BOTTOM) av_bprintf(&ctx->graph_desc, "[0]format=yuv420p,scale=iw:ih/2,pad=iw:ih*2[main];[main]split[dup1][dup2];[dup1][dup2]overlay=0:H/2[bg]"); else { av_log(NULL,AV_LOG_ERROR,"Invalid format Speified only side_by_side and top_n_bottom supported\n"); return -1; } ret = configure_filter(ctx); if(ret < 0) { av_log(NULL,AV_LOG_ERROR,"Unable to configure Filter\n"); return ret; } return ret; }
static int func_metadata(AVFilterContext *ctx, AVBPrint *bp, char *fct, unsigned argc, char **argv, int tag) { DrawTextContext *s = ctx->priv; AVDictionaryEntry *e = av_dict_get(s->metadata, argv[0], NULL, 0); if (e && e->value) av_bprintf(bp, "%s", e->value); else if (argc >= 2) av_bprintf(bp, "%s", argv[1]); return 0; }
static void insert_ts(AVBPrint *buf, int ts) { if (ts == -1) { av_bprintf(buf, "9:59:59.99,"); } else { int h, m, s; h = ts/360000; ts -= 360000*h; m = ts/ 6000; ts -= 6000*m; s = ts/ 100; ts -= 100*s; av_bprintf(buf, "%d:%02d:%02d.%02d,", h, m, s, ts); } }
static int func_pts(AVFilterContext *ctx, AVBPrint *bp, char *fct, unsigned argc, char **argv, int tag) { DrawTextContext *s = ctx->priv; const char *fmt; double pts = s->var_values[VAR_T]; int ret; fmt = argc >= 1 ? argv[0] : "flt"; if (argc >= 2) { int64_t delta; if ((ret = av_parse_time(&delta, argv[1], 1)) < 0) { av_log(ctx, AV_LOG_ERROR, "Invalid delta '%s'\n", argv[1]); return ret; } pts += (double)delta / AV_TIME_BASE; } if (!strcmp(fmt, "flt")) { av_bprintf(bp, "%.6f", pts); } else if (!strcmp(fmt, "hms")) { if (isnan(pts)) { av_bprintf(bp, " ??:??:??.???"); } else { int64_t ms = llrint(pts * 1000); char sign = ' '; if (ms < 0) { sign = '-'; ms = -ms; } av_bprintf(bp, "%c%02d:%02d:%02d.%03d", sign, (int)(ms / (60 * 60 * 1000)), (int)(ms / (60 * 1000)) % 60, (int)(ms / 1000) % 60, (int)(ms % 1000)); } } else if (!strcmp(fmt, "localtime") || !strcmp(fmt, "gmtime")) { struct tm tm; time_t ms = (time_t)pts; const char *timefmt = argc >= 3 ? argv[2] : "%Y-%m-%d %H:%M:%S"; if (!strcmp(fmt, "localtime")) localtime_r(&ms, &tm); else gmtime_r(&ms, &tm); av_bprint_strftime(bp, timefmt, &tm); } else { av_log(ctx, AV_LOG_ERROR, "Invalid format '%s'\n", fmt); return AVERROR(EINVAL); } return 0; }
static int microdvd_init(AVCodecContext *avctx) { int i, sidx; AVBPrint font_buf; int font_size = ASS_DEFAULT_FONT_SIZE; int color = ASS_DEFAULT_COLOR; int bold = ASS_DEFAULT_BOLD; int italic = ASS_DEFAULT_ITALIC; int underline = ASS_DEFAULT_UNDERLINE; int alignment = ASS_DEFAULT_ALIGNMENT; struct microdvd_tag tags[sizeof(MICRODVD_TAGS) - 1] = {{0}}; av_bprint_init(&font_buf, 0, AV_BPRINT_SIZE_AUTOMATIC); av_bprintf(&font_buf, "%s", ASS_DEFAULT_FONT); if (avctx->extradata) { microdvd_load_tags(tags, avctx->extradata); for (i = 0; i < sizeof(MICRODVD_TAGS) - 1; i++) { switch (av_tolower(tags[i].key)) { case 'y': for (sidx = 0; sidx < sizeof(MICRODVD_STYLES) - 1; sidx++) { if (tags[i].data1 & (1 << sidx)) { switch (MICRODVD_STYLES[sidx]) { case 'i': italic = 1; break; case 'b': bold = 1; break; case 'u': underline = 1; break; } } } break; case 'c': color = tags[i].data1; break; case 's': font_size = tags[i].data1; break; case 'p': alignment = 8; break; case 'f': av_bprint_clear(&font_buf); av_bprintf(&font_buf, "%.*s", tags[i].data_string_len, tags[i].data_string); break; } } } return ff_ass_subtitle_header(avctx, font_buf.str, font_size, color, ASS_DEFAULT_BACK_COLOR, bold, italic, underline, ASS_DEFAULT_BORDERSTYLE, alignment); }
static int read_dialogue(ASSContext *ass, AVBPrint *dst, const uint8_t *p, int64_t *start, int *duration) { int pos = 0; int64_t end; int hh1, mm1, ss1, ms1; int hh2, mm2, ss2, ms2; if (sscanf(p, "Dialogue: %*[^,],%d:%d:%d%*c%d,%d:%d:%d%*c%d,%n", &hh1, &mm1, &ss1, &ms1, &hh2, &mm2, &ss2, &ms2, &pos) >= 8 && pos > 0) { /* This is not part of the sscanf itself in order to handle an actual * number (which would be the Layer) or the form "Marked=N" (which is * the old SSA field, now replaced by Layer, and will lead to Layer * being 0 here). */ const int layer = atoi(p + 10); end = (hh2*3600LL + mm2*60LL + ss2) * 100LL + ms2; *start = (hh1*3600LL + mm1*60LL + ss1) * 100LL + ms1; *duration = end - *start; av_bprint_clear(dst); av_bprintf(dst, "%u,%d,%s", ass->readorder++, layer, p + pos); /* right strip the buffer */ while (dst->len > 0 && dst->str[dst->len - 1] == '\r' || dst->str[dst->len - 1] == '\n') dst->str[--dst->len] = 0; return 0; } return -1; }
static int sami_read_header(AVFormatContext *s) { SAMIContext *sami = s->priv_data; AVStream *st = avformat_new_stream(s, NULL); AVBPrint buf, hdr_buf; char c = 0; int res = 0, got_first_sync_point = 0; FFTextReader tr; ff_text_init_avio(&tr, s->pb); if (!st) return AVERROR(ENOMEM); avpriv_set_pts_info(st, 64, 1, 1000); st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; st->codec->codec_id = AV_CODEC_ID_SAMI; av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); av_bprint_init(&hdr_buf, 0, AV_BPRINT_SIZE_UNLIMITED); while (!ff_text_eof(&tr)) { AVPacket *sub; const int64_t pos = ff_text_pos(&tr) - (c != 0); int is_sync, n = ff_smil_extract_next_text_chunk(&tr, &buf, &c); if (n == 0) break; is_sync = !av_strncasecmp(buf.str, "<SYNC", 5); if (is_sync) got_first_sync_point = 1; if (!got_first_sync_point) { av_bprintf(&hdr_buf, "%s", buf.str); } else { sub = ff_subtitles_queue_insert(&sami->q, buf.str, buf.len, !is_sync); if (!sub) { res = AVERROR(ENOMEM); goto end; } if (is_sync) { const char *p = ff_smil_get_attr_ptr(buf.str, "Start"); sub->pos = pos; sub->pts = p ? strtol(p, NULL, 10) : 0; sub->duration = -1; } } av_bprint_clear(&buf); } res = avpriv_bprint_to_extradata(st->codec, &hdr_buf); if (res < 0) goto end; ff_subtitles_queue_finalize(&sami->q); end: av_bprint_finalize(&buf, NULL); return res; }
static int func_eval_expr_int_format(AVFilterContext *ctx, AVBPrint *bp, char *fct, unsigned argc, char **argv, int tag) { DrawTextContext *s = ctx->priv; double res; int intval; int ret; unsigned int positions = 0; char fmt_str[30] = "%"; /* * argv[0] expression to be converted to `int` * argv[1] format: 'x', 'X', 'd' or 'u' * argv[2] positions printed (optional) */ ret = av_expr_parse_and_eval(&res, argv[0], var_names, s->var_values, NULL, NULL, fun2_names, fun2, &s->prng, 0, ctx); if (ret < 0) { av_log(ctx, AV_LOG_ERROR, "Expression '%s' for the expr text expansion function is not valid\n", argv[0]); return ret; } if (!strchr("xXdu", argv[1][0])) { av_log(ctx, AV_LOG_ERROR, "Invalid format '%c' specified," " allowed values: 'x', 'X', 'd', 'u'\n", argv[1][0]); return AVERROR(EINVAL); } if (argc == 3) { ret = sscanf(argv[2], "%u", &positions); if (ret != 1) { av_log(ctx, AV_LOG_ERROR, "expr_int_format(): Invalid number of positions" " to print: '%s'\n", argv[2]); return AVERROR(EINVAL); } } feclearexcept(FE_ALL_EXCEPT); intval = res; if ((ret = fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW))) { av_log(ctx, AV_LOG_ERROR, "Conversion of floating-point result to int failed. Control register: 0x%08x. Conversion result: %d\n", ret, intval); return AVERROR(EINVAL); } if (argc == 3) av_strlcatf(fmt_str, sizeof(fmt_str), "0%u", positions); av_strlcatf(fmt_str, sizeof(fmt_str), "%c", argv[1][0]); av_log(ctx, AV_LOG_DEBUG, "Formatting value %f (expr '%s') with spec '%s'\n", res, argv[0], fmt_str); av_bprintf(bp, fmt_str, intval); return 0; }
static int subviewer_event_to_ass(AVBPrint *buf, const char *p) { while (*p) { if (!strncmp(p, "[br]", 4)) { av_bprintf(buf, "\\N"); p += 4; } else { if (p[0] == '\n' && p[1]) av_bprintf(buf, "\\N"); else if (*p != '\n' && *p != '\r') av_bprint_chars(buf, *p, 1); p++; } } return 0; }
static void read_chunk(AVIOContext *pb, AVBPrint *buf) { char eol_buf[5]; int n = 0, i = 0, nb_eol = 0; av_bprint_clear(buf); for (;;) { char c = avio_r8(pb); if (!c) break; /* ignore all initial line breaks */ if (n == 0 && is_eol(c)) continue; /* line break buffering: we don't want to add the trailing \r\n */ if (is_eol(c)) { nb_eol += c == '\n'; if (nb_eol == 2) break; eol_buf[i++] = c; if (i == sizeof(eol_buf) - 1) break; continue; } /* only one line break followed by data: we flush the line breaks * buffer */ if (i) { eol_buf[i] = 0; av_bprintf(buf, "%s", eol_buf); i = nb_eol = 0; } av_bprint_chars(buf, c, 1); n++; } /* FIXME: remove the following when the lavc SubRip decoder is fixed * (trailing tags are not correctly flushed, see what happens to FATE when * you disable this code) */ if (buf->len) av_bprintf(buf, "\n"); }
static int func_frame_num(AVFilterContext *ctx, AVBPrint *bp, char *fct, unsigned argc, char **argv, int tag) { DrawTextContext *s = ctx->priv; av_bprintf(bp, "%d", (int)s->var_values[VAR_N]); return 0; }
static int func_pict_type(AVFilterContext *ctx, AVBPrint *bp, char *fct, unsigned argc, char **argv, int tag) { DrawTextContext *s = ctx->priv; av_bprintf(bp, "%c", av_get_picture_type_char(s->var_values[VAR_PICT_TYPE])); return 0; }
int ff_ass_add_rect_bprint(AVSubtitle *sub, AVBPrint *buf, int ts_start, int duration) { av_bprintf(buf, "\r\n"); if (!av_bprint_is_complete(buf)) return AVERROR(ENOMEM); return ff_ass_add_rect(sub, buf->str, ts_start, duration, 0); }
static void bprint_pascal(AVBPrint *b, unsigned size) { unsigned i, j; unsigned p[42]; av_assert0(size < FF_ARRAY_ELEMS(p)); p[0] = 1; av_bprintf(b, "%8d\n", 1); for (i = 1; i <= size; i++) { p[i] = 1; for (j = i - 1; j > 0; j--) p[j] = p[j] + p[j - 1]; for (j = 0; j <= i; j++) av_bprintf(b, "%8d", p[j]); av_bprintf(b, "\n"); } }
static void audio_frame_cksum(AVBPrint *bp, AVFrame *frame) { int nb_planes, nb_samples, p; const char *name; nb_planes = av_frame_get_channels(frame); nb_samples = frame->nb_samples; if (!av_sample_fmt_is_planar(frame->format)) { nb_samples *= nb_planes; nb_planes = 1; } name = av_get_sample_fmt_name(frame->format); av_bprintf(bp, ", %d samples", frame->nb_samples); av_bprintf(bp, ", %s", name ? name : "unknown"); for (p = 0; p < nb_planes; p++) { uint32_t cksum = 0; void *d = frame->extended_data[p]; switch (frame->format) { case AV_SAMPLE_FMT_U8: case AV_SAMPLE_FMT_U8P: cksum_line_u8(&cksum, d, nb_samples); break; case AV_SAMPLE_FMT_S16: case AV_SAMPLE_FMT_S16P: cksum_line_s16(&cksum, d, nb_samples); break; case AV_SAMPLE_FMT_S32: case AV_SAMPLE_FMT_S32P: cksum_line_s32(&cksum, d, nb_samples); break; case AV_SAMPLE_FMT_FLT: case AV_SAMPLE_FMT_FLTP: cksum_line_flt(&cksum, d, nb_samples); break; case AV_SAMPLE_FMT_DBL: case AV_SAMPLE_FMT_DBLP: cksum_line_dbl(&cksum, d, nb_samples); break; default: av_assert0(!"reached"); } av_bprintf(bp, ", 0x%08x", cksum); } }
static int text_to_ass(AVBPrint *buf, const char *text, const char *text_end) { while (text < text_end) { switch (*text) { case '\r': break; case '\n': av_bprintf(buf, "\\N"); break; default: av_bprint_chars(buf, *text, 1); break; } text++; } av_bprintf(buf, "\r\n"); return 0; }
static int microdvd_decode_frame(AVCodecContext *avctx, void *data, int *got_sub_ptr, AVPacket *avpkt) { AVSubtitle *sub = data; AVBPrint new_line; char *decoded_sub; char *line = avpkt->data; char *end = avpkt->data + avpkt->size; struct microdvd_tag tags[sizeof(MICRODVD_TAGS) - 1] = {{0}}; if (avpkt->size <= 0) return avpkt->size; av_bprint_init(&new_line, 0, 2048); // skip {frame_start}{frame_end} line = strchr(line, '}'); if (!line) goto end; line++; line = strchr(line, '}'); if (!line) goto end; line++; // subtitle content while (line < end && *line) { // parse MicroDVD tags, and open them in ASS line = microdvd_load_tags(tags, line); microdvd_open_tags(&new_line, tags); // simple copy until EOL or forced carriage return while (line < end && *line && *line != '|') { av_bprint_chars(&new_line, *line, 1); line++; } // line split if (line < end && *line == '|') { microdvd_close_no_persistent_tags(&new_line, tags); av_bprintf(&new_line, "\\N"); line++; } } end: av_bprint_finalize(&new_line, &decoded_sub); if (*decoded_sub) { int64_t start = avpkt->pts; int64_t duration = avpkt->duration; int ts_start = av_rescale_q(start, avctx->time_base, (AVRational){1,100}); int ts_duration = duration != -1 ? av_rescale_q(duration, avctx->time_base, (AVRational){1,100}) : -1; ff_ass_add_rect(sub, decoded_sub, ts_start, ts_duration, 0); } av_free(decoded_sub); *got_sub_ptr = sub->num_rects > 0; return avpkt->size; }
static int ass_read_header(AVFormatContext *s) { ASSContext *ass = s->priv_data; AVBPrint header, line, rline; int res = 0; AVStream *st; FFTextReader tr; ff_text_init_avio(s, &tr, s->pb); st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); avpriv_set_pts_info(st, 64, 1, 100); st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; st->codec->codec_id = AV_CODEC_ID_ASS; av_bprint_init(&header, 0, AV_BPRINT_SIZE_UNLIMITED); av_bprint_init(&line, 0, AV_BPRINT_SIZE_UNLIMITED); av_bprint_init(&rline, 0, AV_BPRINT_SIZE_UNLIMITED); for (;;) { int64_t pos = get_line(&line, &tr); int64_t ts_start = AV_NOPTS_VALUE; int duration = -1; AVPacket *sub; if (!line.str[0]) // EOF break; if (read_dialogue(ass, &rline, line.str, &ts_start, &duration) < 0) { av_bprintf(&header, "%s", line.str); continue; } sub = ff_subtitles_queue_insert(&ass->q, rline.str, rline.len, 0); if (!sub) { res = AVERROR(ENOMEM); goto end; } sub->pos = pos; sub->pts = ts_start; sub->duration = duration; } res = avpriv_bprint_to_extradata(st->codec, &header); if (res < 0) goto end; ff_subtitles_queue_finalize(&ass->q); end: av_bprint_finalize(&header, NULL); av_bprint_finalize(&line, NULL); av_bprint_finalize(&rline, NULL); return res; }
void av_bprint_channel_layout(struct AVBPrint *bp, int nb_channels, uint64_t channel_layout) { int i; if (nb_channels <= 0) nb_channels = av_get_channel_layout_nb_channels(channel_layout); for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); i++) if (nb_channels == channel_layout_map[i].nb_channels && channel_layout == channel_layout_map[i].layout) { av_bprintf(bp, "%s", channel_layout_map[i].name); return; } av_bprintf(bp, "%d channels", nb_channels); if (channel_layout) { int i, ch; av_bprintf(bp, " ("); for (i = 0, ch = 0; i < 64; i++) { if ((channel_layout & (UINT64_C(1) << i))) { const char *name = get_channel_name(i); if (name) { if (ch > 0) av_bprintf(bp, "+"); av_bprintf(bp, "%s", name); } ch++; } } av_bprintf(bp, ")"); } }
static int mpl2_event_to_ass(AVBPrint *buf, const char *p) { if (*p == ' ') p++; while (*p) { int got_style = 0; while (*p && strchr("/\\_", *p)) { if (*p == '/') av_bprintf(buf, "{\\i1}"); else if (*p == '\\') av_bprintf(buf, "{\\b1}"); else if (*p == '_') av_bprintf(buf, "{\\u1}"); got_style = 1; p++; } while (*p && *p != '|') { if (*p != '\r' && *p != '\n') av_bprint_chars(buf, *p, 1); p++; } if (*p == '|') { if (got_style) av_bprintf(buf, "{\\r}"); av_bprintf(buf, "\\N"); p++; } } av_bprintf(buf, "\r\n"); return 0; }
void ff_ass_bprint_text_event(AVBPrint *buf, const char *p, int size, const char *linebreaks, int keep_ass_markup) { const char *p_end = p + size; for (; p < p_end && *p; p++) { /* forced custom line breaks, not accounted as "normal" EOL */ if (linebreaks && strchr(linebreaks, *p)) { av_bprintf(buf, "\\N"); /* standard ASS escaping so random characters don't get mis-interpreted * as ASS */ } else if (!keep_ass_markup && strchr("{}\\", *p)) { av_bprintf(buf, "\\%c", *p); /* some packets might end abruptly (no \0 at the end, like for example * in some cases of demuxing from a classic video container), some * might be terminated with \n or \r\n which we have to remove (for * consistency with those who haven't), and we also have to deal with * evil cases such as \r at the end of the buffer (and no \0 terminated * character) */ } else if (p[0] == '\n') { /* some stuff left so we can insert a line break */ if (p < p_end - 1) av_bprintf(buf, "\\N"); } else if (p[0] == '\r' && p < p_end - 1 && p[1] == '\n') { /* \r followed by a \n, we can skip it. We don't insert the \N yet * because we don't know if it is followed by more text */ continue; /* finally, a sane character */ } else { av_bprint_chars(buf, *p, 1); } } av_bprintf(buf, "\r\n"); }
int ff_ass_bprint_dialog(AVBPrint *buf, const char *dialog, int ts_start, int duration, int raw) { int dlen; if (!raw || raw == 2) { long int layer = 0; if (raw == 2) { /* skip ReadOrder */ dialog = strchr(dialog, ','); if (!dialog) return AVERROR_INVALIDDATA; dialog++; /* extract Layer or Marked */ layer = strtol(dialog, (char**)&dialog, 10); if (*dialog != ',') return AVERROR_INVALIDDATA; dialog++; } av_bprintf(buf, "Dialogue: %ld,", layer); insert_ts(buf, ts_start); insert_ts(buf, duration == -1 ? -1 : ts_start + duration); if (raw != 2) av_bprintf(buf, "Default,,0,0,0,,"); } dlen = strcspn(dialog, "\n"); dlen += dialog[dlen] == '\n'; av_bprintf(buf, "%.*s", dlen, dialog); if (raw == 2) av_bprintf(buf, "\r\n"); return dlen; }