static int subviewer1_read_header(AVFormatContext *s) { int delay = 0; AVPacket *sub = NULL; SubViewer1Context *subviewer1 = s->priv_data; AVStream *st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); avpriv_set_pts_info(st, 64, 1, 1); st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE; st->codecpar->codec_id = AV_CODEC_ID_SUBVIEWER1; while (!avio_feof(s->pb)) { char line[4096]; int len = ff_get_line(s->pb, line, sizeof(line)); int hh, mm, ss; if (!len) break; if (!strncmp(line, "[DELAY]", 7)) { ff_get_line(s->pb, line, sizeof(line)); sscanf(line, "%d", &delay); } if (sscanf(line, "[%d:%d:%d]", &hh, &mm, &ss) == 3) { const int64_t pos = avio_tell(s->pb); int64_t pts_start = hh*3600LL + mm*60LL + ss + delay; len = ff_get_line(s->pb, line, sizeof(line)); line[strcspn(line, "\r\n")] = 0; if (!*line) { if (sub) sub->duration = pts_start - sub->pts; } else { sub = ff_subtitles_queue_insert(&subviewer1->q, line, len, 0); if (!sub) return AVERROR(ENOMEM); sub->pos = pos; sub->pts = pts_start; sub->duration = -1; } } } ff_subtitles_queue_finalize(s, &subviewer1->q); return 0; }
static int pvf_read_header(AVFormatContext *s) { char buffer[32]; AVStream *st; int bps, channels, sample_rate; avio_skip(s->pb, 5); ff_get_line(s->pb, buffer, sizeof(buffer)); if (sscanf(buffer, "%d %d %d", &channels, &sample_rate, &bps) != 3) return AVERROR_INVALIDDATA; if (channels <= 0 || bps <= 0 || sample_rate <= 0) return AVERROR_INVALIDDATA; st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); st->codec->codec_type = AVMEDIA_TYPE_AUDIO; st->codec->channels = channels; st->codec->sample_rate = sample_rate; st->codec->codec_id = ff_get_pcm_codec_id(bps, 0, 1, 0xFFFF); st->codec->bits_per_coded_sample = bps; st->codec->block_align = bps * st->codec->channels / 8; avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); return 0; }
static int read_chomp_line(AVIOContext *s, char *buf, int maxlen) { int len = ff_get_line(s, buf, maxlen); while (len > 0 && isspace(buf[len - 1])) buf[--len] = '\0'; return len; }
static int microdvd_read_header(AVFormatContext *s) { AVRational pts_info = (AVRational){ 2997, 125 }; /* default: 23.976 fps */ MicroDVDContext *microdvd = s->priv_data; AVStream *st = avformat_new_stream(s, NULL); int i, frame; double fps; char c; if (!st) return -1; for (i=0; i<FF_ARRAY_ELEMS(microdvd->lines); i++) { microdvd->pos[i] = avio_tell(s->pb); ff_get_line(s->pb, microdvd->lines[i], sizeof(microdvd->lines[i])); if ((sscanf(microdvd->lines[i], "{%d}{}%6lf", &frame, &fps) == 2 || sscanf(microdvd->lines[i], "{%d}{%*d}%6lf", &frame, &fps) == 2) && frame <= 1 && fps > 3 && fps < 100) pts_info = av_d2q(fps, 100000); if (sscanf(microdvd->lines[i], "{DEFAULT}{}%c", &c) == 1) { st->codec->extradata = av_strdup(microdvd->lines[i] + 11); st->codec->extradata_size = strlen(st->codec->extradata); i--; } } avpriv_set_pts_info(st, 64, pts_info.den, pts_info.num); st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; st->codec->codec_id = CODEC_ID_MICRODVD; return 0; }
static int mpsub_read_header(AVFormatContext *s) { MPSubContext *mpsub = s->priv_data; AVStream *st; AVBPrint buf; AVRational pts_info = (AVRational){ 100, 1 }; // ts based by default int res = 0; float multiplier = 100.0; float current_pts = 0; av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); while (!url_feof(s->pb)) { char line[1024]; float start, duration; int fps, len = ff_get_line(s->pb, line, sizeof(line)); if (!len) break; line[strcspn(line, "\r\n")] = 0; if (sscanf(line, "FORMAT=%d", &fps) == 1 && fps > 3 && fps < 100) { /* frame based timing */ pts_info = (AVRational){ fps, 1 }; multiplier = 1.0; } else if (sscanf(line, "%f %f", &start, &duration) == 2) { AVPacket *sub; const int64_t pos = avio_tell(s->pb); ff_subtitles_read_chunk(s->pb, &buf); if (buf.len) { sub = ff_subtitles_queue_insert(&mpsub->q, buf.str, buf.len, 0); if (!sub) { res = AVERROR(ENOMEM); goto end; } sub->pts = (int64_t)(current_pts + start*multiplier); sub->duration = (int)(duration * multiplier); current_pts += (start + duration) * multiplier; sub->pos = pos; } } } st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); avpriv_set_pts_info(st, 64, pts_info.den, pts_info.num); st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; st->codec->codec_id = AV_CODEC_ID_TEXT; ff_subtitles_queue_finalize(&mpsub->q); end: av_bprint_finalize(&buf, NULL); return res; }
static int text_read_packet(AVFormatContext *s, AVPacket *pkt) { char buffer[2048], *ptr = buffer, *ptr2, *prt3; char data[1024] = {0}; int64_t pos = avio_tell(s->pb); int res = AVERROR_EOF; do { ptr2 = ptr; ptr += ff_get_line(s->pb, ptr, sizeof(buffer)+buffer-ptr); } while(is_eol(*ptr2) && !url_feof(s->pb) && ptr-buffer<sizeof(buffer)-1); do { prt3 = ptr; ptr += ff_get_line(s->pb, ptr, sizeof(buffer)+buffer-ptr); } while(is_eol(*prt3) && !url_feof(s->pb) && ptr-buffer<sizeof(buffer)-1); if (buffer[0]) { int64_t pts; int duration; const char *end = ptr; ptr = buffer; pts = get_pts(&ptr, &duration, data); if (pts != AV_NOPTS_VALUE && !(res = av_new_packet(pkt, strlen(data)))) { memcpy(pkt->data, data, strlen(data)); memset(data, 0, 1024); pkt->flags |= AV_PKT_FLAG_KEY; pkt->pos = pos; pkt->pts = pkt->dts = pts; pkt->duration = duration; } } return res; }
static int get_line(AVIOContext *pb, char *line, int line_size) { ff_get_line(pb, line, line_size); if (pb->error) return pb->error; if (pb->eof_reached) return AVERROR_EOF; trim_right(line); return 0; }
static int read_chomp_line(AVIOContext *s, char *buf, int maxlen) { int len = ff_get_line(s, buf, maxlen); while (len > 0 && isspace(buf[len - 1])) buf[--len] = '\0'; if(len==0){ if(url_feof(s)) return AVERROR_EOF; if(url_ferror(s)) return url_ferror(s); } return len; }
static int microdvd_read_header(AVFormatContext *s) { AVRational pts_info = (AVRational){ 2997, 125 }; /* default: 23.976 fps */ MicroDVDContext *microdvd = s->priv_data; AVStream *st = avformat_new_stream(s, NULL); int i = 0; char line[MAX_LINESIZE]; if (!st) return AVERROR(ENOMEM); while (!url_feof(s->pb)) { AVPacket *sub; int64_t pos = avio_tell(s->pb); int len = ff_get_line(s->pb, line, sizeof(line)); if (!len) break; if (i < 3) { int frame; double fps; char c; i++; if ((sscanf(line, "{%d}{}%6lf", &frame, &fps) == 2 || sscanf(line, "{%d}{%*d}%6lf", &frame, &fps) == 2) && frame <= 1 && fps > 3 && fps < 100) pts_info = av_d2q(fps, 100000); if (!st->codec->extradata && sscanf(line, "{DEFAULT}{}%c", &c) == 1) { st->codec->extradata = av_strdup(line + 11); if (!st->codec->extradata) return AVERROR(ENOMEM); st->codec->extradata_size = strlen(st->codec->extradata) + 1; continue; } } sub = ff_subtitles_queue_insert(µdvd->q, line, len, 0); if (!sub) return AVERROR(ENOMEM); sub->pos = pos; sub->pts = get_pts(sub->data); sub->duration = get_duration(sub->data); } ff_subtitles_queue_finalize(µdvd->q); avpriv_set_pts_info(st, 64, pts_info.den, pts_info.num); st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; st->codec->codec_id = AV_CODEC_ID_MICRODVD; return 0; }
static int get_line(AVIOContext *pb, char *line, int line_size) { int i = ff_get_line(pb, line, line_size); if (i > 1 && line[i - 2] == '\r') line[i - 2] = '\0'; if (pb->error) return pb->error; if (pb->eof_reached) return AVERROR_EOF; return 0; }
static int srt_read_packet(AVFormatContext *s, AVPacket *pkt) { char buffer[2048], *ptr = buffer, *ptr2; int64_t pos = avio_tell(s->pb); int res = AVERROR_EOF; do { ptr2 = ptr; ptr += ff_get_line(s->pb, ptr, sizeof(buffer)+buffer-ptr); } while (!is_eol(*ptr2) && !url_feof(s->pb) && ptr-buffer<sizeof(buffer)-1); if (buffer[0] && !(res = av_new_packet(pkt, ptr-buffer))) { memcpy(pkt->data, buffer, pkt->size); pkt->flags |= AV_PKT_FLAG_KEY; pkt->pos = pos; pkt->pts = pkt->dts = get_pts(pkt->data); } return res; }
static int pjs_read_header(AVFormatContext *s) { PJSContext *pjs = s->priv_data; AVStream *st = avformat_new_stream(s, NULL); int res = 0; if (!st) return AVERROR(ENOMEM); avpriv_set_pts_info(st, 64, 1, 10); st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; st->codec->codec_id = AV_CODEC_ID_PJS; while (!avio_feof(s->pb)) { char line[4096]; char *p = line; const int64_t pos = avio_tell(s->pb); int len = ff_get_line(s->pb, line, sizeof(line)); int64_t pts_start; int duration; if (!len) break; line[strcspn(line, "\r\n")] = 0; pts_start = read_ts(&p, &duration); if (pts_start != AV_NOPTS_VALUE) { AVPacket *sub; p[strcspn(p, "\"")] = 0; sub = ff_subtitles_queue_insert(&pjs->q, p, strlen(p), 0); if (!sub) return AVERROR(ENOMEM); sub->pos = pos; sub->pts = pts_start; sub->duration = duration; } } ff_subtitles_queue_finalize(&pjs->q); return res; }
static int srt_read_packet(AVFormatContext *s, AVPacket *pkt) { char buffer[2048], *ptr = buffer, *ptr2; int64_t pos = avio_tell(s->pb); int res = AVERROR_EOF; do { ptr2 = ptr; ptr += ff_get_line(s->pb, ptr, sizeof(buffer)+buffer-ptr); } while (!is_eol(*ptr2) && !url_feof(s->pb) && ptr-buffer<sizeof(buffer)-1); if (buffer[0]) { int64_t pts; int duration; const char *end = ptr; int32_t x1 = -1, y1 = -1, x2 = -1, y2 = -1; ptr = buffer; pts = get_pts(&ptr, &duration, &x1, &y1, &x2, &y2); if (pts != AV_NOPTS_VALUE && !(res = av_new_packet(pkt, end - ptr))) { memcpy(pkt->data, ptr, pkt->size); pkt->flags |= AV_PKT_FLAG_KEY; pkt->pos = pos; pkt->pts = pkt->dts = pts; pkt->duration = duration; if (x1 != -1) { uint8_t *p = av_packet_new_side_data(pkt, AV_PKT_DATA_SUBTITLE_POSITION, 16); if (p) { AV_WL32(p, x1); AV_WL32(p + 4, y1); AV_WL32(p + 8, x2); AV_WL32(p + 12, y2); } } } } return res; }
static int subviewer_read_header(AVFormatContext *s) { SubViewerContext *subviewer = s->priv_data; AVStream *st = avformat_new_stream(s, NULL); AVBPrint header; int res = 0, new_event = 1; int64_t pts_start = AV_NOPTS_VALUE; int duration = -1; AVPacket *sub = 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_SUBVIEWER; av_bprint_init(&header, 0, AV_BPRINT_SIZE_UNLIMITED); while (!avio_feof(s->pb)) { char line[2048]; int64_t pos = 0; int len = ff_get_line(s->pb, line, sizeof(line)); if (!len) break; line[strcspn(line, "\r\n")] = 0; if (line[0] == '[' && strncmp(line, "[br]", 4)) { /* ignore event style, XXX: add to side_data? */ if (strstr(line, "[COLF]") || strstr(line, "[SIZE]") || strstr(line, "[FONT]") || strstr(line, "[STYLE]")) continue; if (!st->codec->extradata) { // header not finalized yet av_bprintf(&header, "%s\n", line); if (!strncmp(line, "[END INFORMATION]", 17) || !strncmp(line, "[SUBTITLE]", 10)) { /* end of header */ res = avpriv_bprint_to_extradata(st->codec, &header); if (res < 0) goto end; } else if (strncmp(line, "[INFORMATION]", 13)) { /* assume file metadata at this point */ int i, j = 0; char key[32], value[128]; for (i = 1; i < sizeof(key) - 1 && line[i] && line[i] != ']'; i++) key[i - 1] = av_tolower(line[i]); key[i - 1] = 0; if (line[i] == ']') i++; while (line[i] == ' ') i++; while (j < sizeof(value) - 1 && line[i] && line[i] != ']') value[j++] = line[i++]; value[j] = 0; av_dict_set(&s->metadata, key, value, 0); } } } else if (read_ts(line, &pts_start, &duration) >= 0) { new_event = 1; pos = avio_tell(s->pb); } else if (*line) { if (!new_event) { sub = ff_subtitles_queue_insert(&subviewer->q, "\n", 1, 1); if (!sub) { res = AVERROR(ENOMEM); goto end; } } sub = ff_subtitles_queue_insert(&subviewer->q, line, strlen(line), !new_event); if (!sub) { res = AVERROR(ENOMEM); goto end; } if (new_event) { sub->pos = pos; sub->pts = pts_start; sub->duration = duration; } new_event = 0; } } ff_subtitles_queue_finalize(&subviewer->q); end: av_bprint_finalize(&header, NULL); return res; }
static int microdvd_read_header(AVFormatContext *s) { AVRational pts_info = (AVRational){ 2997, 125 }; /* default: 23.976 fps */ MicroDVDContext *microdvd = s->priv_data; AVStream *st = avformat_new_stream(s, NULL); int i = 0; char line[MAX_LINESIZE]; if (!st) return AVERROR(ENOMEM); while (!url_feof(s->pb)) { char *p = line; AVPacket *sub; int64_t pos = avio_tell(s->pb); int len = ff_get_line(s->pb, line, sizeof(line)); if (!len) break; line[strcspn(line, "\r\n")] = 0; if (i++ < 3) { int frame; double fps; char c; if ((sscanf(line, "{%d}{}%6lf", &frame, &fps) == 2 || sscanf(line, "{%d}{%*d}%6lf", &frame, &fps) == 2) && frame <= 1 && fps > 3 && fps < 100) pts_info = av_d2q(fps, 100000); if (!st->codec->extradata && sscanf(line, "{DEFAULT}{}%c", &c) == 1) { st->codec->extradata = av_strdup(line + 11); if (!st->codec->extradata) return AVERROR(ENOMEM); st->codec->extradata_size = strlen(st->codec->extradata) + 1; continue; } } #define SKIP_FRAME_ID \ p = strchr(p, '}'); \ if (!p) { \ av_log(s, AV_LOG_WARNING, "Invalid event \"%s\"" \ " at line %d\n", line, i); \ continue; \ } \ p++ SKIP_FRAME_ID; SKIP_FRAME_ID; if (!*p) continue; sub = ff_subtitles_queue_insert(µdvd->q, p, strlen(p), 0); if (!sub) return AVERROR(ENOMEM); sub->pos = pos; sub->pts = get_pts(line); sub->duration = get_duration(line); } ff_subtitles_queue_finalize(µdvd->q); avpriv_set_pts_info(st, 64, pts_info.den, pts_info.num); st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; st->codec->codec_id = AV_CODEC_ID_MICRODVD; return 0; }
static int nist_read_header(AVFormatContext *s) { char buffer[32], coding[32] = "pcm", format[32] = "01"; int bps = 0, be = 0; int32_t header_size = -1; AVStream *st; st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); st->codec->codec_type = AVMEDIA_TYPE_AUDIO; ff_get_line(s->pb, buffer, sizeof(buffer)); ff_get_line(s->pb, buffer, sizeof(buffer)); sscanf(buffer, "%"SCNd32, &header_size); if (header_size <= 0) return AVERROR_INVALIDDATA; while (!avio_feof(s->pb)) { ff_get_line(s->pb, buffer, sizeof(buffer)); if (avio_tell(s->pb) >= header_size) return AVERROR_INVALIDDATA; if (!memcmp(buffer, "end_head", 8)) { if (!st->codec->bits_per_coded_sample) st->codec->bits_per_coded_sample = bps << 3; if (!av_strcasecmp(coding, "pcm")) { st->codec->codec_id = ff_get_pcm_codec_id(st->codec->bits_per_coded_sample, 0, be, 0xFFFF); } else if (!av_strcasecmp(coding, "alaw")) { st->codec->codec_id = AV_CODEC_ID_PCM_ALAW; } else if (!av_strcasecmp(coding, "ulaw") || !av_strcasecmp(coding, "mu-law")) { st->codec->codec_id = AV_CODEC_ID_PCM_MULAW; } else { avpriv_request_sample(s, "coding %s", coding); } avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); st->codec->block_align = st->codec->bits_per_coded_sample * st->codec->channels / 8; if (avio_tell(s->pb) > header_size) return AVERROR_INVALIDDATA; avio_skip(s->pb, header_size - avio_tell(s->pb)); return 0; } else if (!memcmp(buffer, "channel_count", 13)) { sscanf(buffer, "%*s %*s %"SCNd32, &st->codec->channels); } else if (!memcmp(buffer, "sample_byte_format", 18)) { sscanf(buffer, "%*s %*s %31s", format); if (!av_strcasecmp(format, "01")) { be = 0; } else if (!av_strcasecmp(format, "10")) { be = 1; } else if (av_strcasecmp(format, "1")) { avpriv_request_sample(s, "sample byte format %s", format); return AVERROR_PATCHWELCOME; } } else if (!memcmp(buffer, "sample_coding", 13)) { sscanf(buffer, "%*s %*s %31s", coding); } else if (!memcmp(buffer, "sample_count", 12)) { sscanf(buffer, "%*s %*s %"SCNd64, &st->duration); } else if (!memcmp(buffer, "sample_n_bytes", 14)) { sscanf(buffer, "%*s %*s %"SCNd32, &bps); } else if (!memcmp(buffer, "sample_rate", 11)) { sscanf(buffer, "%*s %*s %"SCNd32, &st->codec->sample_rate); } else if (!memcmp(buffer, "sample_sig_bits", 15)) { sscanf(buffer, "%*s %*s %"SCNd32, &st->codec->bits_per_coded_sample); } else { char key[32], value[32]; if (sscanf(buffer, "%31s %*s %31s", key, value) == 3) { av_dict_set(&s->metadata, key, value, AV_DICT_APPEND); } else { av_log(s, AV_LOG_ERROR, "Failed to parse '%s' as metadata\n", buffer); } } } return AVERROR_EOF; }
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 read_header(AVFormatContext *s) { int i, len, header_remaining; ASSContext *ass = s->priv_data; AVIOContext *pb = s->pb; AVStream *st; int allocated[2]= {0}; uint8_t *p, **dst[2]= {0}; int pos[2]= {0}; st = avformat_new_stream(s, NULL); if (!st) return -1; avpriv_set_pts_info(st, 64, 1, 100); st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; st->codec->codec_id= AV_CODEC_ID_SSA; header_remaining= INT_MAX; dst[0] = &st->codec->extradata; dst[1] = &ass->event_buffer; while(!pb->eof_reached) { uint8_t line[MAX_LINESIZE]; len = ff_get_line(pb, line, sizeof(line)); if(!memcmp(line, "[Events]", 8)) header_remaining= 2; else if(line[0]=='[') header_remaining= INT_MAX; i= header_remaining==0; if(i && get_pts(line) == AV_NOPTS_VALUE) continue; p = av_fast_realloc(*(dst[i]), &allocated[i], pos[i]+MAX_LINESIZE); if(!p) goto fail; *(dst[i])= p; memcpy(p + pos[i], line, len+1); pos[i] += len; if(i) ass->event_count++; else header_remaining--; } st->codec->extradata_size= pos[0]; if(ass->event_count >= UINT_MAX / sizeof(*ass->event)) goto fail; ass->event= av_malloc(ass->event_count * sizeof(*ass->event)); p= ass->event_buffer; for(i=0; i<ass->event_count; i++) { ass->event[i]= p; while(*p && *p != '\n') p++; p++; } qsort(ass->event, ass->event_count, sizeof(*ass->event), (void*)event_cmp); return 0; fail: read_close(s); return -1; }
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; }
static int microdvd_read_packet(AVFormatContext *s, AVPacket *pkt) { MicroDVDContext *microdvd = s->priv_data; char buffer[MAX_LINESIZE]; int64_t pos = avio_tell(s->pb); int i, len = 0, res = AVERROR_EOF; // last packet has its duration set but couldn't be raised earlier if (microdvd->last_pkt_ready) { *pkt = microdvd->last_pkt; microdvd->last_pkt_ready = 0; return 0; } for (i=0; i<FF_ARRAY_ELEMS(microdvd->lines); i++) { if (microdvd->lines[i][0]) { strcpy(buffer, microdvd->lines[i]); pos = microdvd->pos[i]; len = strlen(buffer); microdvd->lines[i][0] = 0; break; } } if (!len) len = ff_get_line(s->pb, buffer, sizeof(buffer)); if (microdvd->last_pkt.duration == -1 && !buffer[0]) { // if the previous subtitle line had no duration, last until the end of // the presentation microdvd->last_pkt.duration = 0; *pkt = microdvd->last_pkt; pkt->duration = -1; res = 0; } else if (buffer[0] && !(res = av_new_packet(pkt, len))) { memcpy(pkt->data, buffer, len); pkt->flags |= AV_PKT_FLAG_KEY; pkt->pos = pos; pkt->pts = pkt->dts = get_pts(buffer); if (pkt->pts != AV_NOPTS_VALUE) { pkt->duration = get_duration(buffer); if (microdvd->last_pkt.duration == -1) { // previous packet wasn't raised because it was lacking the // duration info, so set its duration with the new packet pts // and raise it AVPacket tmp_pkt; tmp_pkt = microdvd->last_pkt; tmp_pkt.duration = pkt->pts - tmp_pkt.pts; microdvd->last_pkt = *pkt; microdvd->last_pkt_ready = pkt->duration != -1; *pkt = tmp_pkt; } else if (pkt->duration == -1) { // no packet without duration queued, and current one is // lacking the duration info, we need to parse another subtitle // event. microdvd->last_pkt = *pkt; res = AVERROR(EAGAIN); } } } return res; }