static int jacosub_read_header(AVFormatContext *s) { AVBPrint header; AVIOContext *pb = s->pb; char line[JSS_MAX_LINESIZE]; JACOsubContext *jacosub = s->priv_data; int shift_set = 0; // only the first shift matters int merge_line = 0; int i, ret; AVStream *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_JACOSUB; jacosub->timeres = 30; av_bprint_init(&header, 1024+FF_INPUT_BUFFER_PADDING_SIZE, 4096); while (!avio_feof(pb)) { int cmd_len; const char *p = line; int64_t pos = avio_tell(pb); int len = ff_get_line(pb, line, sizeof(line)); p = jss_skip_whitespace(p); /* queue timed line */ if (merge_line || timed_line(p)) { AVPacket *sub; sub = ff_subtitles_queue_insert(&jacosub->q, line, len, merge_line); if (!sub) return AVERROR(ENOMEM); sub->pos = pos; merge_line = len > 1 && !strcmp(&line[len - 2], "\\\n"); continue; } /* skip all non-compiler commands and focus on the command */ if (*p != '#') continue; p++; i = get_jss_cmd(p[0]); if (i == -1) continue; /* trim command + spaces */ cmd_len = strlen(cmds[i]); if (av_strncasecmp(p, cmds[i], cmd_len) == 0) p += cmd_len; else p++; p = jss_skip_whitespace(p); /* handle commands which affect the whole script */ switch (cmds[i][0]) { case 'S': // SHIFT command affect the whole script... if (!shift_set) { jacosub->shift = get_shift(jacosub->timeres, p); shift_set = 1; } av_bprintf(&header, "#S %s", p); break; case 'T': // ...but must be placed after TIMERES jacosub->timeres = strtol(p, NULL, 10); if (!jacosub->timeres) jacosub->timeres = 30; else av_bprintf(&header, "#T %s", p); break; } } /* general/essential directives in the extradata */ ret = avpriv_bprint_to_extradata(st->codec, &header); if (ret < 0) return ret; /* SHIFT and TIMERES affect the whole script so packet timing can only be * done in a second pass */ for (i = 0; i < jacosub->q.nb_subs; i++) { AVPacket *sub = &jacosub->q.subs[i]; read_ts(jacosub, sub->data, &sub->pts, &sub->duration); } ff_subtitles_queue_finalize(&jacosub->q); return 0; }
static int jacosub_read_header(AVFormatContext *s) { AVBPrint header; AVIOContext *pb = s->pb; char line[JSS_MAX_LINESIZE]; JACOsubContext *jacosub = s->priv_data; int shift_set = 0; // only the first shift matters int merge_line = 0; int i; AVStream *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 = CODEC_ID_JACOSUB; jacosub->timeres = 30; av_bprint_init(&header, 1024+FF_INPUT_BUFFER_PADDING_SIZE, 4096); while (!url_feof(pb)) { int cmd_len; const char *p = line; int64_t pos = avio_tell(pb); ff_get_line(pb, line, sizeof(line)); p = jss_skip_whitespace(p); /* queue timed line */ if (merge_line || timed_line(p)) { SubEntry *subs, *sub; const int len = strlen(line); if (merge_line) { char *tmp; const int old_len = strlen(sub->line); sub = &subs[jacosub->nsub]; tmp = av_realloc(sub->line, old_len + len + 1); if (!tmp) return AVERROR(ENOMEM); sub->line = tmp; strcpy(sub->line + old_len, line); } else { subs = av_realloc(jacosub->subs, sizeof(*jacosub->subs) * (jacosub->nsub+1)); if (!subs) return AVERROR(ENOMEM); jacosub->subs = subs; sub = &subs[jacosub->nsub]; sub->pos = pos; sub->line = av_strdup(line); if (!sub->line) return AVERROR(ENOMEM); } merge_line = len > 1 && !strcmp(&line[len - 2], "\\\n"); if (!merge_line) jacosub->nsub++; continue; } /* skip all non-compiler commands and focus on the command */ if (*p != '#') continue; p++; i = get_jss_cmd(p[0]); if (i == -1) continue; /* trim command + spaces */ cmd_len = strlen(cmds[i]); if (av_strncasecmp(p, cmds[i], cmd_len) == 0) p += cmd_len; else p++; p = jss_skip_whitespace(p); /* handle commands which affect the whole script */ switch (cmds[i][0]) { case 'S': // SHIFT command affect the whole script... if (!shift_set) { jacosub->shift = get_shift(jacosub->timeres, p); shift_set = 1; } av_bprintf(&header, "#S %s", p); break; case 'T': // ...but must be placed after TIMERES jacosub->timeres = strtol(p, NULL, 10); av_bprintf(&header, "#T %s", p); break; } } /* general/essential directives in the extradata */ av_bprint_finalize(&header, (char **)&st->codec->extradata); st->codec->extradata_size = header.len + 1; /* SHIFT and TIMERES affect the whole script so packet timing can only be * done in a second pass */ for (i = 0; i < jacosub->nsub; i++) { SubEntry *sub = &jacosub->subs[i]; read_ts(jacosub, sub->line, &sub->start, &sub->end); } qsort(jacosub->subs, jacosub->nsub, sizeof(*jacosub->subs), cmp_timed_sub); return 0; }