static int parse_presentation_segment(AVCodecContext *avctx, const uint8_t *buf, int buf_size, int64_t pts) { PGSSubContext *ctx = avctx->priv_data; int i, state, ret; // Video descriptor int w = bytestream_get_be16(&buf); int h = bytestream_get_be16(&buf); uint16_t object_index; ctx->presentation.pts = pts; av_dlog(avctx, "Video Dimensions %dx%d\n", w, h); ret = ff_set_dimensions(avctx, w, h); if (ret < 0) return ret; /* Skip 1 bytes of unknown, frame rate */ buf++; // Composition descriptor ctx->presentation.id_number = bytestream_get_be16(&buf); /* * state is a 2 bit field that defines pgs epoch boundaries * 00 - Normal, previously defined objects and palettes are still valid * 01 - Acquisition point, previous objects and palettes can be released * 10 - Epoch start, previous objects and palettes can be released * 11 - Epoch continue, previous objects and palettes can be released * * reserved 6 bits discarded */ state = bytestream_get_byte(&buf) >> 6; if (state != 0) { flush_cache(avctx); } /* * skip palette_update_flag (0x80), */ buf += 1; ctx->presentation.palette_id = bytestream_get_byte(&buf); ctx->presentation.object_count = bytestream_get_byte(&buf); if (ctx->presentation.object_count > MAX_OBJECT_REFS) { av_log(avctx, AV_LOG_ERROR, "Invalid number of presentation objects %d\n", ctx->presentation.object_count); ctx->presentation.object_count = 2; if (avctx->err_recognition & AV_EF_EXPLODE) { return AVERROR_INVALIDDATA; } } for (i = 0; i < ctx->presentation.object_count; i++) { if (buf_end - buf < 8) { av_log(avctx, AV_LOG_ERROR, "Insufficent space for object\n"); ctx->presentation.object_count = i; return AVERROR_INVALIDDATA; } ctx->presentation.objects[i].id = bytestream_get_be16(&buf); ctx->presentation.objects[i].window_id = bytestream_get_byte(&buf); ctx->presentation.objects[i].composition_flag = bytestream_get_byte(&buf); ctx->presentation.objects[i].x = bytestream_get_be16(&buf); ctx->presentation.objects[i].y = bytestream_get_be16(&buf); // If cropping if (ctx->presentation.objects[i].composition_flag & 0x80) { ctx->presentation.objects[i].crop_x = bytestream_get_be16(&buf); ctx->presentation.objects[i].crop_y = bytestream_get_be16(&buf); ctx->presentation.objects[i].crop_w = bytestream_get_be16(&buf); ctx->presentation.objects[i].crop_h = bytestream_get_be16(&buf); } av_dlog(avctx, "Subtitle Placement x=%d, y=%d\n", ctx->presentation.objects[i].x, ctx->presentation.objects[i].y); if (ctx->presentation.objects[i].x > avctx->width || ctx->presentation.objects[i].y > avctx->height) { av_log(avctx, AV_LOG_ERROR, "Subtitle out of video bounds. x = %d, y = %d, video width = %d, video height = %d.\n", ctx->presentation.objects[i].x, ctx->presentation.objects[i].y, avctx->width, avctx->height); ctx->presentation.objects[i].x = 0; ctx->presentation.objects[i].y = 0; if (avctx->err_recognition & AV_EF_EXPLODE) { return AVERROR_INVALIDDATA; } } } return 0; }