static int init(struct sd *sd) { struct sd_lavc_priv *priv = talloc_zero(NULL, struct sd_lavc_priv); enum AVCodecID cid = mp_codec_to_av_codec_id(sd->codec); AVCodecContext *ctx = NULL; AVCodec *sub_codec = avcodec_find_decoder(cid); if (!sub_codec) goto error; ctx = avcodec_alloc_context3(sub_codec); if (!ctx) goto error; mp_lavc_set_extradata(ctx, sd->extradata, sd->extradata_len); if (avcodec_open2(ctx, sub_codec, NULL) < 0) goto error; priv->avctx = ctx; sd->priv = priv; priv->displayed_id = -1; return 0; error: MP_FATAL(sd, "Could not open libavcodec subtitle decoder\n"); av_free(ctx); talloc_free(priv); return -1; }
static void set_mp4_vobsub_idx(AVCodecContext *avctx, char *src, int w, int h) { char pal_s[128]; int pal_s_pos = 0; for (int i = 0; i < 16; i++) { unsigned int e = AV_RB32(src + i * 4); // lavc doesn't accept YUV palette - "does god hate me?" struct mp_csp_params csp = MP_CSP_PARAMS_DEFAULTS; csp.int_bits_in = 8; csp.int_bits_out = 8; float cmatrix[3][4]; mp_get_yuv2rgb_coeffs(&csp, cmatrix); int c[3] = {(e >> 16) & 0xff, (e >> 8) & 0xff, e & 0xff}; mp_map_int_color(cmatrix, 8, c); e = (c[2] << 16) | (c[1] << 8) | c[0]; snprintf(pal_s + pal_s_pos, sizeof(pal_s) - pal_s_pos, "%06x%s", e, i != 15 ? ", " : ""); pal_s_pos = strlen(pal_s); if (pal_s_pos >= sizeof(pal_s)) break; } char buf[256] = ""; snprintf(buf, sizeof(buf), "size: %dx%d\npalette: %s\n", w, h, pal_s); mp_lavc_set_extradata(avctx, buf, strlen(buf)); }
static int init(struct sd *sd) { enum AVCodecID cid = mp_codec_to_av_codec_id(sd->codec->codec); // Supported codecs must be known to decode to paletted bitmaps switch (cid) { case AV_CODEC_ID_DVB_SUBTITLE: case AV_CODEC_ID_HDMV_PGS_SUBTITLE: case AV_CODEC_ID_XSUB: case AV_CODEC_ID_DVD_SUBTITLE: break; default: return -1; } struct sd_lavc_priv *priv = talloc_zero(NULL, struct sd_lavc_priv); AVCodecContext *ctx = NULL; AVCodec *sub_codec = avcodec_find_decoder(cid); if (!sub_codec) goto error; ctx = avcodec_alloc_context3(sub_codec); if (!ctx) goto error; mp_lavc_set_extradata(ctx, sd->codec->extradata, sd->codec->extradata_size); #if LIBAVCODEC_VERSION_MICRO >= 100 if (cid == AV_CODEC_ID_HDMV_PGS_SUBTITLE) { // We don't always want to set this, because the ridiculously shitty // libavcodec API will mess with certain fields (end_display_time) // when setting it. On the other hand, PGS in particular needs PTS // mangling. While the PGS decoder doesn't modify the timestamps (just // reorder it), the ridiculously shitty libavcodec wants a timebase // anyway and for no good reason. It always sets end_display_time to // UINT32_MAX (which is a broken and undocumented way to say "unknown"), // which coincidentally won't be overridden by the ridiculously shitty // pkt_timebase code. also, Libav doesn't have the pkt_timebase field, // because Libav tends to avoid _adding_ ridiculously shitty APIs. priv->pkt_timebase = (AVRational){1, AV_TIME_BASE}; ctx->pkt_timebase = priv->pkt_timebase; } else { // But old ffmpeg releases have a buggy pkt_timebase check, because the // shit above wasn't bad enough! ctx->pkt_timebase = (AVRational){0, 0}; } #endif if (avcodec_open2(ctx, sub_codec, NULL) < 0) goto error; priv->avctx = ctx; sd->priv = priv; priv->displayed_id = -1; priv->current_pts = MP_NOPTS_VALUE; priv->packer = talloc_zero(priv, struct bitmap_packer); return 0; error: MP_FATAL(sd, "Could not open libavcodec subtitle decoder\n"); av_free(ctx); talloc_free(priv); return -1; }
// Copy the codec-related fields from st into avctx. This does not set the // codec itself, only codec related header data provided by libavformat. // The goal is to initialize a new decoder with the header data provided by // libavformat, and unlike avcodec_copy_context(), allow the user to create // a clean AVCodecContext for a manually selected AVCodec. // This is strictly for decoding only. void mp_copy_lav_codec_headers(AVCodecContext *avctx, AVCodecContext *st) { mp_lavc_set_extradata(avctx, st->extradata, st->extradata_size); avctx->codec_tag = st->codec_tag; avctx->bit_rate = st->bit_rate; avctx->width = st->width; avctx->height = st->height; avctx->pix_fmt = st->pix_fmt; avctx->chroma_sample_location = st->chroma_sample_location; avctx->sample_rate = st->sample_rate; avctx->channels = st->channels; avctx->block_align = st->block_align; avctx->channel_layout = st->channel_layout; avctx->bits_per_coded_sample = st->bits_per_coded_sample; avctx->has_b_frames = st->has_b_frames; }
struct lavc_conv *lavc_conv_create(struct mp_log *log, const char *codec_name, char *extradata, int extradata_len) { struct lavc_conv *priv = talloc_zero(NULL, struct lavc_conv); priv->log = log; priv->cur_list = talloc_array(priv, char*, 0); priv->codec = talloc_strdup(priv, codec_name); AVCodecContext *avctx = NULL; AVDictionary *opts = NULL; const char *fmt = get_lavc_format(priv->codec); AVCodec *codec = avcodec_find_decoder(mp_codec_to_av_codec_id(fmt)); if (!codec) goto error; avctx = avcodec_alloc_context3(codec); if (!avctx) goto error; if (mp_lavc_set_extradata(avctx, extradata, extradata_len) < 0) goto error; if (strcmp(codec_name, "eia_608") == 0) av_dict_set(&opts, "real_time", "1", 0); if (avcodec_open2(avctx, codec, &opts) < 0) goto error; av_dict_free(&opts); // Documented as "set by libavcodec", but there is no other way avctx->time_base = (AVRational) {1, 1000}; #if LIBAVCODEC_VERSION_MICRO >= 100 avctx->pkt_timebase = avctx->time_base; #endif priv->avctx = avctx; priv->extradata = talloc_strndup(priv, avctx->subtitle_header, avctx->subtitle_header_size); disable_styles(bstr0(priv->extradata)); return priv; error: MP_FATAL(priv, "Could not open libavcodec subtitle converter\n"); av_dict_free(&opts); av_free(avctx); talloc_free(priv); return NULL; }