Example #1
0
int av_bsf_init(AVBSFContext *ctx)
{
    int ret, i;

    /* check that the codec is supported */
    if (ctx->filter->codec_ids) {
        for (i = 0; ctx->filter->codec_ids[i] != AV_CODEC_ID_NONE; i++)
            if (ctx->par_in->codec_id == ctx->filter->codec_ids[i])
                break;
        if (ctx->filter->codec_ids[i] == AV_CODEC_ID_NONE) {
            const AVCodecDescriptor *desc = avcodec_descriptor_get(ctx->par_in->codec_id);
            av_log(ctx, AV_LOG_ERROR, "Codec '%s' (%d) is not supported by the "
                   "bitstream filter '%s'. Supported codecs are: ",
                   desc ? desc->name : "unknown", ctx->par_in->codec_id, ctx->filter->name);
            for (i = 0; ctx->filter->codec_ids[i] != AV_CODEC_ID_NONE; i++) {
                desc = avcodec_descriptor_get(ctx->filter->codec_ids[i]);
                av_log(ctx, AV_LOG_ERROR, "%s (%d) ",
                       desc ? desc->name : "unknown", ctx->filter->codec_ids[i]);
            }
            av_log(ctx, AV_LOG_ERROR, "\n");
            return AVERROR(EINVAL);
        }
    }

    /* initialize output parameters to be the same as input
     * init below might overwrite that */
    ret = avcodec_parameters_copy(ctx->par_out, ctx->par_in);
    if (ret < 0)
        return ret;

    ctx->time_base_out = ctx->time_base_in;

    if (ctx->filter->init) {
        ret = ctx->filter->init(ctx);
        if (ret < 0)
            return ret;
    }

    return 0;
}
Example #2
0
const char *mp_codec_from_av_codec_id(int codec_id)
{
    const char *name = NULL;
    const AVCodecDescriptor *desc = avcodec_descriptor_get(codec_id);
    if (desc)
        name = desc->name;
    if (!name) {
        AVCodec *avcodec = avcodec_find_decoder(codec_id);
        if (avcodec)
            name = avcodec->name;
    }
    return name;
}
bool SubtitleProcessorFFmpeg::processSubtitle()
{
    m_frames.clear();
    int ss = m_reader.subtitleStream();
    if (ss < 0) {
        qWarning("no subtitle stream found");
        return false;
    }
    codec_ctx = m_reader.subtitleCodecContext();
    AVCodec *dec = avcodec_find_decoder(codec_ctx->codec_id);
    const AVCodecDescriptor *dec_desc = avcodec_descriptor_get(codec_ctx->codec_id);
    if (!dec) {
        if (dec_desc)
            qWarning("Failed to find subtitle codec %s", dec_desc->name);
        else
            qWarning("Failed to find subtitle codec %d", codec_ctx->codec_id);
        return false;
    }
    qDebug("found subtitle decoder '%s'", dec_desc->name);
    // AV_CODEC_PROP_TEXT_SUB: ffmpeg >= 2.0
#ifdef AV_CODEC_PROP_TEXT_SUB
    if (dec_desc && !(dec_desc->props & AV_CODEC_PROP_TEXT_SUB)) {
        qWarning("Only text based subtitles are currently supported");
        return false;
    }
#endif
    AVDictionary *codec_opts = NULL;
    int ret = avcodec_open2(codec_ctx, dec, &codec_opts);
    if (ret < 0) {
        qWarning("open subtitle codec error: %s", av_err2str(ret));
        av_dict_free(&codec_opts);
        return false;
    }
    while (!m_reader.atEnd()) {
        if (!m_reader.readFrame()) { // eof or other errors
            continue;
        }
        if (m_reader.stream() != ss)
            continue;
        const Packet pkt = m_reader.packet();
        if (!pkt.isValid())
            continue;
        SubtitleFrame frame = processLine(pkt.data, pkt.pts, pkt.duration);
        if (frame.isValid())
            m_frames.append(frame);
    }
    avcodec_close(codec_ctx);
    codec_ctx = 0;
    return true;
}
Example #4
0
const char *get_codec_long_name(enum AVCodecID id)
{
    if (id == AV_CODEC_ID_NONE)
        return "none";
    const AVCodecDescriptor *cd = avcodec_descriptor_get(id);
    if (cd)
        return cd->long_name;
    av_log(NULL, AV_LOG_WARNING, "Codec 0x%x is not in the full list.\n", id);
    AVCodec *codec = avcodec_find_decoder(id);
    if (codec)
        return codec->long_name;
    codec = avcodec_find_encoder(id);
    if (codec)
        return codec->long_name;
    return "unknown_codec";
}
int stream_component_open(State *s, int stream_index) {
    AVFormatContext *pFormatCtx = s->pFormatCtx;
    AVCodecContext *codecCtx;
    AVCodec *codec;
    
    if (stream_index < 0 || stream_index >= pFormatCtx->nb_streams) {
        return FAILURE;
    }
    
    // Get a pointer to the codec context for the stream
    codecCtx = pFormatCtx->streams[stream_index]->codec;
    
    const AVCodecDescriptor *codesc = avcodec_descriptor_get(codecCtx->codec_id);
    if (codesc) {
        printf("avcodec_find_decoder %s\n", codesc->name);
    }
    
    // Find the decoder for the audio stream
    codec = avcodec_find_decoder(codecCtx->codec_id);
    
    if(codec == NULL) {
        printf("avcodec_find_decoder() failed to find audio decoder\n");
        return FAILURE;
    }
    
    // Open the codec
    if (!codec || (avcodec_open2(codecCtx, codec, NULL) < 0)) {
        printf("avcodec_open2() failed\n");
        return FAILURE;
    }
    
    switch(codecCtx->codec_type) {
        case AVMEDIA_TYPE_AUDIO:
            s->audio_stream = stream_index;
            s->audio_st = pFormatCtx->streams[stream_index];
            break;
        case AVMEDIA_TYPE_VIDEO:
            s->video_stream = stream_index;
            s->video_st = pFormatCtx->streams[stream_index];
            break;
        default:
            break;
    }
    
    return SUCCESS;
}
Example #6
0
static AVCodec *find_encoder(SCM scm_self, enum AVCodecID codec_id, const char *output_type)
{
  if (codec_id == AV_CODEC_ID_NONE) {// TODO: test (needs wav or mp3 container selection above first)
    ffmpeg_destroy(scm_self);
    scm_misc_error("make-ffmpeg-output", "File format does not support ~a encoding",
                   scm_list_1(scm_from_locale_string(output_type)));
  };

  AVCodec *retval = avcodec_find_encoder(codec_id);// TODO: autodetect or select video codec
  if (!retval) {
    ffmpeg_destroy(scm_self);
    scm_misc_error("make-ffmpeg-output", "Error finding encoder for codec '~a'",
                   scm_list_1(scm_from_locale_string(avcodec_descriptor_get(codec_id)->name)));
  };

  return retval;
}
Example #7
0
static bool supports_format(const char *format)
{
    format = get_lavc_format(format);
    enum AVCodecID cid = mp_codec_to_av_codec_id(format);
    const AVCodecDescriptor *desc = avcodec_descriptor_get(cid);
    if (!desc)
        return false;
    // These are known to support AVSubtitleRect->ass.
    const char *whitelist[] =
        {"text", "ass", "ssa", "srt", "subrip", "microdvd", "mpl2",
         "jacosub", "pjs", "sami", "realtext", "subviewer", "subviewer1",
         "vplayer", "webvtt", 0};
    for (int n = 0; whitelist[n]; n++) {
        if (strcmp(format, whitelist[n]) == 0)
            return true;
    }
    return false;
}
Example #8
0
static bool supports_format(const char *format)
{
    enum AVCodecID cid = mp_codec_to_av_codec_id(format);
    const AVCodecDescriptor *desc = avcodec_descriptor_get(cid);
    if (!desc)
        return false;
#if HAVE_AV_CODEC_PROP_TEXT_SUB
    // These are documented to support AVSubtitleRect->ass.
    return desc->props & AV_CODEC_PROP_TEXT_SUB;
#else
    const char *whitelist[] =
        {"text", "ass", "ssa", "mov_text", "srt", "subrip", "microdvd", "mpl2",
         "jacosub", "pjs", "sami",  "realtext", "subviewer", "subviewer1",
         "vplayer", "webvtt", 0};
    for (int n = 0; whitelist[n]; n++) {
        if (strcmp(format, whitelist[n]) == 0)
            return true;
    }
    return false;
#endif
}
Example #9
0
static av_cold int init_subtitles(AVFilterContext *ctx)
{
    int j, ret, sid;
    int k = 0;
    AVDictionary *codec_opts = NULL;
    AVFormatContext *fmt = NULL;
    AVCodecContext *dec_ctx = NULL;
    AVCodec *dec = NULL;
    const AVCodecDescriptor *dec_desc;
    AVStream *st;
    AVPacket pkt;
    AssContext *ass = ctx->priv;

    /* Init libass */
    ret = init(ctx);
    if (ret < 0)
        return ret;
    ass->track = ass_new_track(ass->library);
    if (!ass->track) {
        av_log(ctx, AV_LOG_ERROR, "Could not create a libass track\n");
        return AVERROR(EINVAL);
    }

    /* Open subtitles file */
    ret = avformat_open_input(&fmt, ass->filename, NULL, NULL);
    if (ret < 0) {
        av_log(ctx, AV_LOG_ERROR, "Unable to open %s\n", ass->filename);
        goto end;
    }
    ret = avformat_find_stream_info(fmt, NULL);
    if (ret < 0)
        goto end;

    /* Locate subtitles stream */
    if (ass->stream_index < 0)
        ret = av_find_best_stream(fmt, AVMEDIA_TYPE_SUBTITLE, -1, -1, NULL, 0);
    else {
        ret = -1;
        if (ass->stream_index < fmt->nb_streams) {
            for (j = 0; j < fmt->nb_streams; j++) {
                if (fmt->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
                    if (ass->stream_index == k) {
                        ret = j;
                        break;
                    }
                    k++;
                }
            }
        }
    }

    if (ret < 0) {
        av_log(ctx, AV_LOG_ERROR, "Unable to locate subtitle stream in %s\n",
               ass->filename);
        goto end;
    }
    sid = ret;
    st = fmt->streams[sid];

    /* Load attached fonts */
    for (j = 0; j < fmt->nb_streams; j++) {
        AVStream *st = fmt->streams[j];
        if (st->codecpar->codec_type == AVMEDIA_TYPE_ATTACHMENT &&
            attachment_is_font(st)) {
            const AVDictionaryEntry *tag = NULL;
            tag = av_dict_get(st->metadata, "filename", NULL,
                              AV_DICT_MATCH_CASE);

            if (tag) {
                av_log(ctx, AV_LOG_DEBUG, "Loading attached font: %s\n",
                       tag->value);
                ass_add_font(ass->library, tag->value,
                             st->codecpar->extradata,
                             st->codecpar->extradata_size);
            } else {
                av_log(ctx, AV_LOG_WARNING,
                       "Font attachment has no filename, ignored.\n");
            }
        }
    }

    /* Initialize fonts */
    ass_set_fonts(ass->renderer, NULL, NULL, 1, NULL, 1);

    /* Open decoder */
    dec = avcodec_find_decoder(st->codecpar->codec_id);
    if (!dec) {
        av_log(ctx, AV_LOG_ERROR, "Failed to find subtitle codec %s\n",
               avcodec_get_name(st->codecpar->codec_id));
        return AVERROR(EINVAL);
    }
    dec_desc = avcodec_descriptor_get(st->codecpar->codec_id);
    if (dec_desc && !(dec_desc->props & AV_CODEC_PROP_TEXT_SUB)) {
        av_log(ctx, AV_LOG_ERROR,
               "Only text based subtitles are currently supported\n");
        return AVERROR_PATCHWELCOME;
    }
    if (ass->charenc)
        av_dict_set(&codec_opts, "sub_charenc", ass->charenc, 0);
    if (LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57,26,100))
        av_dict_set(&codec_opts, "sub_text_format", "ass", 0);

    dec_ctx = avcodec_alloc_context3(dec);
    if (!dec_ctx)
        return AVERROR(ENOMEM);

    ret = avcodec_parameters_to_context(dec_ctx, st->codecpar);
    if (ret < 0)
        goto end;

    /*
     * This is required by the decoding process in order to rescale the
     * timestamps: in the current API the decoded subtitles have their pts
     * expressed in AV_TIME_BASE, and thus the lavc internals need to know the
     * stream time base in order to achieve the rescaling.
     *
     * That API is old and needs to be reworked to match behaviour with A/V.
     */
    av_codec_set_pkt_timebase(dec_ctx, st->time_base);

    ret = avcodec_open2(dec_ctx, NULL, &codec_opts);
    if (ret < 0)
        goto end;

    if (ass->force_style) {
        char **list = NULL;
        char *temp = NULL;
        char *ptr = av_strtok(ass->force_style, ",", &temp);
        int i = 0;
        while (ptr) {
            av_dynarray_add(&list, &i, ptr);
            if (!list) {
                ret = AVERROR(ENOMEM);
                goto end;
            }
            ptr = av_strtok(NULL, ",", &temp);
        }
        av_dynarray_add(&list, &i, NULL);
        if (!list) {
            ret = AVERROR(ENOMEM);
            goto end;
        }
        ass_set_style_overrides(ass->library, list);
        av_free(list);
    }
    /* Decode subtitles and push them into the renderer (libass) */
    if (dec_ctx->subtitle_header)
        ass_process_codec_private(ass->track,
                                  dec_ctx->subtitle_header,
                                  dec_ctx->subtitle_header_size);
    av_init_packet(&pkt);
    pkt.data = NULL;
    pkt.size = 0;
    while (av_read_frame(fmt, &pkt) >= 0) {
        int i, got_subtitle;
        AVSubtitle sub = {0};

        if (pkt.stream_index == sid) {
            ret = avcodec_decode_subtitle2(dec_ctx, &sub, &got_subtitle, &pkt);
            if (ret < 0) {
                av_log(ctx, AV_LOG_WARNING, "Error decoding: %s (ignored)\n",
                       av_err2str(ret));
            } else if (got_subtitle) {
                const int64_t start_time = av_rescale_q(sub.pts, AV_TIME_BASE_Q, av_make_q(1, 1000));
                const int64_t duration   = sub.end_display_time;
                for (i = 0; i < sub.num_rects; i++) {
                    char *ass_line = sub.rects[i]->ass;
                    if (!ass_line)
                        break;
                    if (LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57,25,100))
                        ass_process_data(ass->track, ass_line, strlen(ass_line));
                    else
                        ass_process_chunk(ass->track, ass_line, strlen(ass_line),
                                          start_time, duration);
                }
            }
        }
        av_packet_unref(&pkt);
        avsubtitle_free(&sub);
    }

end:
    av_dict_free(&codec_opts);
    avcodec_close(dec_ctx);
    avcodec_free_context(&dec_ctx);
    avformat_close_input(&fmt);
    return ret;
}
Example #10
0
static int wav_write_header(AVFormatContext *s)
{
    WAVMuxContext *wav = s->priv_data;
    AVIOContext *pb = s->pb;
    int64_t fmt;

    if (s->nb_streams != 1) {
        av_log(s, AV_LOG_ERROR, "WAVE files have exactly one stream\n");
        return AVERROR(EINVAL);
    }

    if (wav->rf64 == RF64_ALWAYS) {
        ffio_wfourcc(pb, "RF64");
        avio_wl32(pb, -1); /* RF64 chunk size: use size in ds64 */
    } else {
        ffio_wfourcc(pb, "RIFF");
        avio_wl32(pb, -1); /* file length */
    }

    ffio_wfourcc(pb, "WAVE");

    if (wav->rf64 != RF64_NEVER) {
        /* write empty ds64 chunk or JUNK chunk to reserve space for ds64 */
        ffio_wfourcc(pb, wav->rf64 == RF64_ALWAYS ? "ds64" : "JUNK");
        avio_wl32(pb, 28); /* chunk size */
        wav->ds64 = avio_tell(pb);
        ffio_fill(pb, 0, 28);
    }

    if (wav->write_peak != 2) {
        /* format header */
        fmt = ff_start_tag(pb, "fmt ");
        if (ff_put_wav_header(pb, s->streams[0]->codec, 0) < 0) {
            const AVCodecDescriptor *desc = avcodec_descriptor_get(s->streams[0]->codec->codec_id);
            av_log(s, AV_LOG_ERROR, "%s codec not supported in WAVE format\n",
                   desc ? desc->name : "unknown");
            return AVERROR(ENOSYS);
        }
        ff_end_tag(pb, fmt);
    }

    if (s->streams[0]->codec->codec_tag != 0x01 /* hence for all other than PCM */
        && s->pb->seekable) {
        wav->fact_pos = ff_start_tag(pb, "fact");
        avio_wl32(pb, 0);
        ff_end_tag(pb, wav->fact_pos);
    }

    if (wav->write_bext)
        bwf_write_bext_chunk(s);

    if (wav->write_peak) {
        int ret;
        if ((ret = peak_init_writer(s)) < 0)
            return ret;
    }

    avpriv_set_pts_info(s->streams[0], 64, 1, s->streams[0]->codec->sample_rate);
    wav->maxpts = wav->last_duration = 0;
    wav->minpts = INT64_MAX;

    if (wav->write_peak != 2) {
        /* info header */
        ff_riff_write_info(s);

        /* data header */
        wav->data = ff_start_tag(pb, "data");
    }

    avio_flush(pb);

    return 0;
}
Example #11
0
/*
 * Set *va_config and the frames_ref fields from the current codec parameters
 * in avctx.
 */
static int vaapi_decode_make_config(AVCodecContext *avctx,
                                    AVBufferRef *device_ref,
                                    VAConfigID *va_config,
                                    AVBufferRef *frames_ref)
{
    AVVAAPIHWConfig       *hwconfig    = NULL;
    AVHWFramesConstraints *constraints = NULL;
    VAStatus vas;
    int err, i, j;
    const AVCodecDescriptor *codec_desc;
    VAProfile profile, va_profile, *profile_list = NULL;
    int profile_count, exact_match, alt_profile;
    const AVPixFmtDescriptor *sw_desc, *desc;

    AVHWDeviceContext    *device = (AVHWDeviceContext*)device_ref->data;
    AVVAAPIDeviceContext *hwctx = device->hwctx;

    codec_desc = avcodec_descriptor_get(avctx->codec_id);
    if (!codec_desc) {
        err = AVERROR(EINVAL);
        goto fail;
    }

    profile_count = vaMaxNumProfiles(hwctx->display);
    profile_list  = av_malloc_array(profile_count,
                                    sizeof(VAProfile));
    if (!profile_list) {
        err = AVERROR(ENOMEM);
        goto fail;
    }

    vas = vaQueryConfigProfiles(hwctx->display,
                                profile_list, &profile_count);
    if (vas != VA_STATUS_SUCCESS) {
        av_log(avctx, AV_LOG_ERROR, "Failed to query profiles: "
               "%d (%s).\n", vas, vaErrorStr(vas));
        err = AVERROR(ENOSYS);
        goto fail;
    }

    profile = VAProfileNone;
    exact_match = 0;

    for (i = 0; i < FF_ARRAY_ELEMS(vaapi_profile_map); i++) {
        int profile_match = 0;
        if (avctx->codec_id != vaapi_profile_map[i].codec_id)
            continue;
        if (avctx->profile == vaapi_profile_map[i].codec_profile)
            profile_match = 1;
        profile = vaapi_profile_map[i].va_profile;
        for (j = 0; j < profile_count; j++) {
            if (profile == profile_list[j]) {
                exact_match = profile_match;
                break;
            }
        }
        if (j < profile_count) {
            if (exact_match)
                break;
            alt_profile = vaapi_profile_map[i].codec_profile;
            va_profile = vaapi_profile_map[i].va_profile;
        }
    }
    av_freep(&profile_list);

    if (profile == VAProfileNone) {
        av_log(avctx, AV_LOG_ERROR, "No support for codec %s "
               "profile %d.\n", codec_desc->name, avctx->profile);
        err = AVERROR(ENOSYS);
        goto fail;
    }
    if (!exact_match) {
        if (avctx->hwaccel_flags &
            AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH) {
            av_log(avctx, AV_LOG_VERBOSE, "Codec %s profile %d not "
                   "supported for hardware decode.\n",
                   codec_desc->name, avctx->profile);
            av_log(avctx, AV_LOG_WARNING, "Using possibly-"
                   "incompatible profile %d instead.\n",
                   alt_profile);
            profile = va_profile;
        } else {
            av_log(avctx, AV_LOG_VERBOSE, "Codec %s profile %d not "
                   "supported for hardware decode.\n",
                   codec_desc->name, avctx->profile);
            err = AVERROR(EINVAL);
            goto fail;
        }
    }

    vas = vaCreateConfig(hwctx->display, profile,
                         VAEntrypointVLD, NULL, 0,
                         va_config);
    if (vas != VA_STATUS_SUCCESS) {
        av_log(avctx, AV_LOG_ERROR, "Failed to create decode "
               "configuration: %d (%s).\n", vas, vaErrorStr(vas));
        err = AVERROR(EIO);
        goto fail;
    }

    hwconfig = av_hwdevice_hwconfig_alloc(device_ref);
    if (!hwconfig) {
        err = AVERROR(ENOMEM);
        goto fail;
    }
    hwconfig->config_id = *va_config;

    constraints =
        av_hwdevice_get_hwframe_constraints(device_ref, hwconfig);
    if (!constraints) {
        err = AVERROR(ENOMEM);
        goto fail;
    }

    if (avctx->coded_width  < constraints->min_width  ||
        avctx->coded_height < constraints->min_height ||
        avctx->coded_width  > constraints->max_width  ||
        avctx->coded_height > constraints->max_height) {
        av_log(avctx, AV_LOG_ERROR, "Hardware does not support image "
               "size %dx%d (constraints: width %d-%d height %d-%d).\n",
               avctx->coded_width, avctx->coded_height,
               constraints->min_width,  constraints->max_width,
               constraints->min_height, constraints->max_height);
        err = AVERROR(EINVAL);
        goto fail;
    }
    if (!constraints->valid_sw_formats ||
        constraints->valid_sw_formats[0] == AV_PIX_FMT_NONE) {
        av_log(avctx, AV_LOG_ERROR, "Hardware does not offer any "
               "usable surface formats.\n");
        err = AVERROR(EINVAL);
        goto fail;
    }

    if (frames_ref) {
        AVHWFramesContext *frames = (AVHWFramesContext *)frames_ref->data;

        frames->format = AV_PIX_FMT_VAAPI;
        frames->width = avctx->coded_width;
        frames->height = avctx->coded_height;

        // Find the first format in the list which matches the expected
        // bit depth and subsampling.  If none are found (this can happen
        // when 10-bit streams are decoded to 8-bit surfaces, for example)
        // then just take the first format on the list.
        frames->sw_format = constraints->valid_sw_formats[0];
        sw_desc = av_pix_fmt_desc_get(avctx->sw_pix_fmt);
        for (i = 0; constraints->valid_sw_formats[i] != AV_PIX_FMT_NONE; i++) {
            desc = av_pix_fmt_desc_get(constraints->valid_sw_formats[i]);
            if (desc->nb_components != sw_desc->nb_components ||
                desc->log2_chroma_w != sw_desc->log2_chroma_w ||
                desc->log2_chroma_h != sw_desc->log2_chroma_h)
                continue;
            for (j = 0; j < desc->nb_components; j++) {
                if (desc->comp[j].depth != sw_desc->comp[j].depth)
                    break;
            }
            if (j < desc->nb_components)
                continue;
            frames->sw_format = constraints->valid_sw_formats[i];
            break;
        }

        frames->initial_pool_size = 1;
        // Add per-codec number of surfaces used for storing reference frames.
        switch (avctx->codec_id) {
        case AV_CODEC_ID_H264:
        case AV_CODEC_ID_HEVC:
            frames->initial_pool_size += 16;
            break;
        case AV_CODEC_ID_VP9:
            frames->initial_pool_size += 8;
            break;
        case AV_CODEC_ID_VP8:
            frames->initial_pool_size += 3;
            break;
        default:
            frames->initial_pool_size += 2;
        }
    }

    av_hwframe_constraints_free(&constraints);
    av_freep(&hwconfig);

    return 0;

fail:
    av_hwframe_constraints_free(&constraints);
    av_freep(&hwconfig);
    if (*va_config != VA_INVALID_ID) {
        vaDestroyConfig(hwctx->display, *va_config);
        *va_config = VA_INVALID_ID;
    }
    av_freep(&profile_list);
    return err;
}
Example #12
0
/* write the header (used two times if non streamed) */
static int asf_write_header1(AVFormatContext *s, int64_t file_size,
                             int64_t data_chunk_size)
{
    ASFContext *asf = s->priv_data;
    AVIOContext *pb = s->pb;
    AVDictionaryEntry *tags[5];
    int header_size, n, extra_size, extra_size2, wav_extra_size;
    int has_title, has_aspect_ratio = 0;
    int metadata_count;
    AVCodecParameters *par;
    int64_t header_offset, cur_pos, hpos;
    int bit_rate;
    int64_t duration;
    int audio_language_counts[128] = { 0 };

    ff_metadata_conv(&s->metadata, ff_asf_metadata_conv, NULL);

    tags[0] = av_dict_get(s->metadata, "title", NULL, 0);
    tags[1] = av_dict_get(s->metadata, "author", NULL, 0);
    tags[2] = av_dict_get(s->metadata, "copyright", NULL, 0);
    tags[3] = av_dict_get(s->metadata, "comment", NULL, 0);
    tags[4] = av_dict_get(s->metadata, "rating", NULL, 0);

    duration       = asf->duration + PREROLL_TIME * 10000;
    has_title      = tags[0] || tags[1] || tags[2] || tags[3] || tags[4];

    if (!file_size) {
        if (ff_parse_creation_time_metadata(s, &asf->creation_time, 0) != 0)
            av_dict_set(&s->metadata, "creation_time", NULL, 0);
    }

    metadata_count = av_dict_count(s->metadata);

    bit_rate = 0;
    for (n = 0; n < s->nb_streams; n++) {
        AVDictionaryEntry *entry;
        par = s->streams[n]->codecpar;

        avpriv_set_pts_info(s->streams[n], 32, 1, 1000); /* 32 bit pts in ms */

        bit_rate += par->bit_rate;
        if (   par->codec_type == AVMEDIA_TYPE_VIDEO
            && par->sample_aspect_ratio.num > 0
            && par->sample_aspect_ratio.den > 0)
            has_aspect_ratio++;

        entry = av_dict_get(s->streams[n]->metadata, "language", NULL, 0);
        if (entry) {
            const char *iso6391lang = ff_convert_lang_to(entry->value, AV_LANG_ISO639_1);
            if (iso6391lang) {
                int i;
                for (i = 0; i < asf->nb_languages; i++) {
                    if (!strcmp(asf->languages[i], iso6391lang)) {
                        asf->streams[n].stream_language_index = i;
                        break;
                    }
                }
                if (i >= asf->nb_languages) {
                    asf->languages[asf->nb_languages] = iso6391lang;
                    asf->streams[n].stream_language_index = asf->nb_languages;
                    asf->nb_languages++;
                }
                if (par->codec_type == AVMEDIA_TYPE_AUDIO)
                    audio_language_counts[asf->streams[n].stream_language_index]++;
            }
        } else {
            asf->streams[n].stream_language_index = 128;
        }
    }

    if (asf->is_streamed) {
        put_chunk(s, 0x4824, 0, 0xc00); /* start of stream (length will be patched later) */
    }

    ff_put_guid(pb, &ff_asf_header);
    avio_wl64(pb, -1); /* header length, will be patched after */
    avio_wl32(pb, 3 + has_title + !!metadata_count + s->nb_streams); /* number of chunks in header */
    avio_w8(pb, 1); /* ??? */
    avio_w8(pb, 2); /* ??? */

    /* file header */
    header_offset = avio_tell(pb);
    hpos          = put_header(pb, &ff_asf_file_header);
    ff_put_guid(pb, &ff_asf_my_guid);
    avio_wl64(pb, file_size);
    avio_wl64(pb, unix_to_file_time(asf->creation_time));
    avio_wl64(pb, asf->nb_packets); /* number of packets */
    avio_wl64(pb, duration); /* end time stamp (in 100ns units) */
    avio_wl64(pb, asf->duration); /* duration (in 100ns units) */
    avio_wl64(pb, PREROLL_TIME); /* start time stamp */
    avio_wl32(pb, (asf->is_streamed || !pb->seekable) ? 3 : 2);  /* ??? */
    avio_wl32(pb, s->packet_size); /* packet size */
    avio_wl32(pb, s->packet_size); /* packet size */
    avio_wl32(pb, bit_rate ? bit_rate : -1); /* Maximum data rate in bps */
    end_header(pb, hpos);

    /* header_extension */
    hpos = put_header(pb, &ff_asf_head1_guid);
    ff_put_guid(pb, &ff_asf_head2_guid);
    avio_wl16(pb, 6);
    avio_wl32(pb, 0); /* length, to be filled later */
    if (asf->nb_languages) {
        int64_t hpos2;
        int i;
        int nb_audio_languages = 0;

        hpos2 = put_header(pb, &ff_asf_language_guid);
        avio_wl16(pb, asf->nb_languages);
        for (i = 0; i < asf->nb_languages; i++) {
            avio_w8(pb, 6);
            avio_put_str16le(pb, asf->languages[i]);
        }
        end_header(pb, hpos2);

        for (i = 0; i < asf->nb_languages; i++)
            if (audio_language_counts[i])
                nb_audio_languages++;

        if (nb_audio_languages > 1) {
            hpos2 = put_header(pb, &ff_asf_group_mutual_exclusion_object);
            ff_put_guid(pb, &ff_asf_mutex_language);
            avio_wl16(pb, nb_audio_languages);
            for (i = 0; i < asf->nb_languages; i++) {
                if (audio_language_counts[i]) {
                    avio_wl16(pb, audio_language_counts[i]);
                    for (n = 0; n < s->nb_streams; n++)
                        if (asf->streams[n].stream_language_index == i && s->streams[n]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
                            avio_wl16(pb, n + 1);
                }
            }
            end_header(pb, hpos2);
        }

        for (n = 0; n < s->nb_streams; n++) {
            int64_t es_pos;
            if (asf->streams[n].stream_language_index > 127)
                continue;
            es_pos = put_header(pb, &ff_asf_extended_stream_properties_object);
            avio_wl64(pb, 0); /* start time */
            avio_wl64(pb, 0); /* end time */
            avio_wl32(pb, s->streams[n]->codecpar->bit_rate); /* data bitrate bps */
            avio_wl32(pb, 5000); /* buffer size ms */
            avio_wl32(pb, 0); /* initial buffer fullness */
            avio_wl32(pb, s->streams[n]->codecpar->bit_rate); /* peak data bitrate */
            avio_wl32(pb, 5000); /* maximum buffer size ms */
            avio_wl32(pb, 0); /* max initial buffer fullness */
            avio_wl32(pb, 0); /* max object size */
            avio_wl32(pb, (!asf->is_streamed && pb->seekable) << 1); /* flags - seekable */
            avio_wl16(pb, n + 1); /* stream number */
            avio_wl16(pb, asf->streams[n].stream_language_index); /* language id index */
            avio_wl64(pb, 0); /* avg time per frame */
            avio_wl16(pb, 0); /* stream name count */
            avio_wl16(pb, 0); /* payload extension system count */
            end_header(pb, es_pos);
        }
    }
    if (has_aspect_ratio) {
        int64_t hpos2;
        hpos2 = put_header(pb, &ff_asf_metadata_header);
        avio_wl16(pb, 2 * has_aspect_ratio);
        for (n = 0; n < s->nb_streams; n++) {
            par = s->streams[n]->codecpar;
            if (   par->codec_type == AVMEDIA_TYPE_VIDEO
                && par->sample_aspect_ratio.num > 0
                && par->sample_aspect_ratio.den > 0) {
                AVRational sar = par->sample_aspect_ratio;
                avio_wl16(pb, 0);
                // the stream number is set like this below
                avio_wl16(pb, n + 1);
                avio_wl16(pb, 26); // name_len
                avio_wl16(pb,  3); // value_type
                avio_wl32(pb,  4); // value_len
                avio_put_str16le(pb, "AspectRatioX");
                avio_wl32(pb, sar.num);
                avio_wl16(pb, 0);
                // the stream number is set like this below
                avio_wl16(pb, n + 1);
                avio_wl16(pb, 26); // name_len
                avio_wl16(pb,  3); // value_type
                avio_wl32(pb,  4); // value_len
                avio_put_str16le(pb, "AspectRatioY");
                avio_wl32(pb, sar.den);
            }
        }
        end_header(pb, hpos2);
    }
    {
        int64_t pos1;
        pos1 = avio_tell(pb);
        avio_seek(pb, hpos + 42, SEEK_SET);
        avio_wl32(pb, pos1 - hpos - 46);
        avio_seek(pb, pos1, SEEK_SET);
    }
    end_header(pb, hpos);

    /* title and other info */
    if (has_title) {
        int len;
        uint8_t *buf;
        AVIOContext *dyn_buf;

        if (avio_open_dyn_buf(&dyn_buf) < 0)
            return AVERROR(ENOMEM);

        hpos = put_header(pb, &ff_asf_comment_header);

        for (n = 0; n < FF_ARRAY_ELEMS(tags); n++) {
            len = tags[n] ? avio_put_str16le(dyn_buf, tags[n]->value) : 0;
            avio_wl16(pb, len);
        }
        len = avio_close_dyn_buf(dyn_buf, &buf);
        avio_write(pb, buf, len);
        av_freep(&buf);
        end_header(pb, hpos);
    }
    if (metadata_count) {
        AVDictionaryEntry *tag = NULL;
        hpos = put_header(pb, &ff_asf_extended_content_header);
        avio_wl16(pb, metadata_count);
        while ((tag = av_dict_get(s->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
            put_str16(pb, tag->key);
            avio_wl16(pb, 0);
            put_str16(pb, tag->value);
        }
        end_header(pb, hpos);
    }
    /* chapters using ASF markers */
    if (!asf->is_streamed && s->nb_chapters) {
        int ret;
        if ((ret = asf_write_markers(s)) < 0)
            return ret;
    }
    /* stream headers */
    for (n = 0; n < s->nb_streams; n++) {
        int64_t es_pos;
        //        ASFStream *stream = &asf->streams[n];

        par                 = s->streams[n]->codecpar;
        asf->streams[n].num = n + 1;
        asf->streams[n].seq = 1;

        switch (par->codec_type) {
        case AVMEDIA_TYPE_AUDIO:
            wav_extra_size = 0;
            extra_size     = 18 + wav_extra_size;
            extra_size2    = 8;
            break;
        default:
        case AVMEDIA_TYPE_VIDEO:
            wav_extra_size = par->extradata_size;
            extra_size     = 0x33 + wav_extra_size;
            extra_size2    = 0;
            break;
        }

        hpos = put_header(pb, &ff_asf_stream_header);
        if (par->codec_type == AVMEDIA_TYPE_AUDIO) {
            ff_put_guid(pb, &ff_asf_audio_stream);
            ff_put_guid(pb, &ff_asf_audio_conceal_spread);
        } else {
            ff_put_guid(pb, &ff_asf_video_stream);
            ff_put_guid(pb, &ff_asf_video_conceal_none);
        }
        avio_wl64(pb, 0); /* ??? */
        es_pos = avio_tell(pb);
        avio_wl32(pb, extra_size); /* wav header len */
        avio_wl32(pb, extra_size2); /* additional data len */
        avio_wl16(pb, n + 1); /* stream number */
        avio_wl32(pb, 0); /* ??? */

        if (par->codec_type == AVMEDIA_TYPE_AUDIO) {
            /* WAVEFORMATEX header */
            int wavsize = ff_put_wav_header(s, pb, par, FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX);

            if (wavsize < 0)
                return -1;
            if (wavsize != extra_size) {
                cur_pos = avio_tell(pb);
                avio_seek(pb, es_pos, SEEK_SET);
                avio_wl32(pb, wavsize); /* wav header len */
                avio_seek(pb, cur_pos, SEEK_SET);
            }
            /* ERROR Correction */
            avio_w8(pb, 0x01);
            if (par->codec_id == AV_CODEC_ID_ADPCM_G726 || !par->block_align) {
                avio_wl16(pb, 0x0190);
                avio_wl16(pb, 0x0190);
            } else {
                avio_wl16(pb, par->block_align);
                avio_wl16(pb, par->block_align);
            }
            avio_wl16(pb, 0x01);
            avio_w8(pb, 0x00);
        } else {
            avio_wl32(pb, par->width);
            avio_wl32(pb, par->height);
            avio_w8(pb, 2); /* ??? */
            avio_wl16(pb, 40 + par->extradata_size); /* size */

            /* BITMAPINFOHEADER header */
            ff_put_bmp_header(pb, par, ff_codec_bmp_tags, 1, 0);
        }
        end_header(pb, hpos);
    }

    /* media comments */

    hpos = put_header(pb, &ff_asf_codec_comment_header);
    ff_put_guid(pb, &ff_asf_codec_comment1_header);
    avio_wl32(pb, s->nb_streams);
    for (n = 0; n < s->nb_streams; n++) {
        const AVCodecDescriptor *codec_desc;
        const char *desc;

        par  = s->streams[n]->codecpar;
        codec_desc = avcodec_descriptor_get(par->codec_id);

        if (par->codec_type == AVMEDIA_TYPE_AUDIO)
            avio_wl16(pb, 2);
        else if (par->codec_type == AVMEDIA_TYPE_VIDEO)
            avio_wl16(pb, 1);
        else
            avio_wl16(pb, -1);

        if (par->codec_id == AV_CODEC_ID_WMAV2)
            desc = "Windows Media Audio V8";
        else
            desc = codec_desc ? codec_desc->name : NULL;

        if (desc) {
            AVIOContext *dyn_buf;
            uint8_t *buf;
            int len;

            if (avio_open_dyn_buf(&dyn_buf) < 0)
                return AVERROR(ENOMEM);

            avio_put_str16le(dyn_buf, desc);
            len = avio_close_dyn_buf(dyn_buf, &buf);
            avio_wl16(pb, len / 2); // "number of characters" = length in bytes / 2

            avio_write(pb, buf, len);
            av_freep(&buf);
        } else
            avio_wl16(pb, 0);

        avio_wl16(pb, 0); /* no parameters */

        /* id */
        if (par->codec_type == AVMEDIA_TYPE_AUDIO) {
            avio_wl16(pb, 2);
            avio_wl16(pb, par->codec_tag);
        } else {
            avio_wl16(pb, 4);
            avio_wl32(pb, par->codec_tag);
        }
        if (!par->codec_tag)
            return -1;
    }
    end_header(pb, hpos);

    /* patch the header size fields */

    cur_pos     = avio_tell(pb);
    header_size = cur_pos - header_offset;
    if (asf->is_streamed) {
        header_size += 8 + 30 + DATA_HEADER_SIZE;

        avio_seek(pb, header_offset - 10 - 30, SEEK_SET);
        avio_wl16(pb, header_size);
        avio_seek(pb, header_offset - 2 - 30, SEEK_SET);
        avio_wl16(pb, header_size);

        header_size -= 8 + 30 + DATA_HEADER_SIZE;
    }
    header_size += 24 + 6;
    avio_seek(pb, header_offset - 14, SEEK_SET);
    avio_wl64(pb, header_size);
    avio_seek(pb, cur_pos, SEEK_SET);

    /* movie chunk, followed by packets of packet_size */
    asf->data_offset = cur_pos;
    ff_put_guid(pb, &ff_asf_data_header);
    avio_wl64(pb, data_chunk_size);
    ff_put_guid(pb, &ff_asf_my_guid);
    avio_wl64(pb, asf->nb_packets); /* nb packets */
    avio_w8(pb, 1); /* ??? */
    avio_w8(pb, 1); /* ??? */
    return 0;
}
Example #13
0
static void show_stream(InputFile *ifile, InputStream *ist)
{
    AVFormatContext *fmt_ctx = ifile->fmt_ctx;
    AVStream *stream = ist->st;
    AVCodecParameters *par;
    AVCodecContext *dec_ctx;
    const AVCodecDescriptor *codec_desc;
    const char *profile;
    char val_str[128];
    AVRational display_aspect_ratio, *sar = NULL;
    const AVPixFmtDescriptor *desc;

    probe_object_header("stream");

    probe_int("index", stream->index);

    par     = stream->codecpar;
    dec_ctx = ist->dec_ctx;
    codec_desc = avcodec_descriptor_get(par->codec_id);
    if (codec_desc) {
        probe_str("codec_name", codec_desc->name);
        probe_str("codec_long_name", codec_desc->long_name);
    } else {
        probe_str("codec_name", "unknown");
    }

    probe_str("codec_type", media_type_string(par->codec_type));

    /* print AVI/FourCC tag */
    av_get_codec_tag_string(val_str, sizeof(val_str), par->codec_tag);
    probe_str("codec_tag_string", val_str);
    probe_str("codec_tag", tag_string(val_str, sizeof(val_str),
                                      par->codec_tag));

    /* print profile, if there is one */
    profile = avcodec_profile_name(par->codec_id, par->profile);
    if (profile)
        probe_str("profile", profile);

    switch (par->codec_type) {
    case AVMEDIA_TYPE_VIDEO:
        probe_int("width",  par->width);
        probe_int("height", par->height);
        if (dec_ctx) {
            probe_int("coded_width",  dec_ctx->coded_width);
            probe_int("coded_height", dec_ctx->coded_height);
            probe_int("has_b_frames", dec_ctx->has_b_frames);
        }
        if (dec_ctx && dec_ctx->sample_aspect_ratio.num)
            sar = &dec_ctx->sample_aspect_ratio;
        else if (par->sample_aspect_ratio.num)
            sar = &par->sample_aspect_ratio;
        else if (stream->sample_aspect_ratio.num)
            sar = &stream->sample_aspect_ratio;

        if (sar) {
            probe_str("sample_aspect_ratio",
                      rational_string(val_str, sizeof(val_str), ":", sar));
            av_reduce(&display_aspect_ratio.num, &display_aspect_ratio.den,
                      par->width  * sar->num, par->height * sar->den,
                      1024*1024);
            probe_str("display_aspect_ratio",
                      rational_string(val_str, sizeof(val_str), ":",
                      &display_aspect_ratio));
        }
        desc = av_pix_fmt_desc_get(par->format);
        probe_str("pix_fmt", desc ? desc->name : "unknown");
        probe_int("level", par->level);

        probe_str("color_range", av_color_range_name    (par->color_range));
        probe_str("color_space", av_color_space_name    (par->color_space));
        probe_str("color_trc",   av_color_transfer_name (par->color_trc));
        probe_str("color_pri",   av_color_primaries_name(par->color_primaries));
        probe_str("chroma_loc", av_chroma_location_name (par->chroma_location));
        break;

    case AVMEDIA_TYPE_AUDIO:
        probe_str("sample_rate",
                  value_string(val_str, sizeof(val_str),
                               par->sample_rate,
                               unit_hertz_str));
        probe_int("channels", par->channels);
        probe_int("bits_per_sample",
                  av_get_bits_per_sample(par->codec_id));
        break;
    }

    if (fmt_ctx->iformat->flags & AVFMT_SHOW_IDS)
        probe_int("id", stream->id);
    probe_str("avg_frame_rate",
              rational_string(val_str, sizeof(val_str), "/",
              &stream->avg_frame_rate));

    if (par->bit_rate)
        probe_str("bit_rate",
                  value_string(val_str, sizeof(val_str),
                               par->bit_rate, unit_bit_per_second_str));
    probe_str("time_base",
              rational_string(val_str, sizeof(val_str), "/",
              &stream->time_base));
    probe_str("start_time",
              time_value_string(val_str, sizeof(val_str),
                                stream->start_time, &stream->time_base));
    probe_str("duration",
              time_value_string(val_str, sizeof(val_str),
                                stream->duration, &stream->time_base));
    if (stream->nb_frames)
        probe_int("nb_frames", stream->nb_frames);

    probe_dict(stream->metadata, "tags");

    if (stream->nb_side_data) {
        int i, j;

        probe_object_header("sidedata");
        for (i = 0; i < stream->nb_side_data; i++) {
            const AVPacketSideData* sd = &stream->side_data[i];
            AVStereo3D *stereo;

            switch (sd->type) {
            case AV_PKT_DATA_DISPLAYMATRIX:
                probe_object_header("displaymatrix");
                probe_array_header("matrix", 1);
                for (j = 0; j < 9; j++)
                    probe_int(NULL, ((int32_t *)sd->data)[j]);
                probe_array_footer("matrix", 1);
                probe_int("rotation",
                          av_display_rotation_get((int32_t *)sd->data));
                probe_object_footer("displaymatrix");
                break;
            case AV_PKT_DATA_STEREO3D:
                stereo = (AVStereo3D *)sd->data;
                probe_object_header("stereo3d");
                probe_str("type", av_stereo3d_type_name(stereo->type));
                probe_int("inverted",
                          !!(stereo->flags & AV_STEREO3D_FLAG_INVERT));
                probe_object_footer("stereo3d");
                break;
            }
        }
        probe_object_footer("sidedata");
    }

    probe_object_footer("stream");
}
int stream_component_open(State *s, int stream_index) {
	AVFormatContext *pFormatCtx = s->pFormatCtx;
	AVCodecContext *codecCtx;
	AVCodec *codec;

	if (stream_index < 0 || stream_index >= pFormatCtx->nb_streams) {
		return FAILURE;
	}

	// Get a pointer to the codec context for the stream
	codecCtx = pFormatCtx->streams[stream_index]->codec;

    const AVCodecDescriptor *codesc = avcodec_descriptor_get(codecCtx->codec_id);
    if (codesc) {
        printf("avcodec_find_decoder %s\n", codesc->name);
    }

	// Find the decoder for the audio stream
	codec = avcodec_find_decoder(codecCtx->codec_id);

	if (codec == NULL) {
	    printf("avcodec_find_decoder() failed to find audio decoder\n");
	    return FAILURE;
	}

	// Open the codec
    if (!codec || (avcodec_open2(codecCtx, codec, NULL) < 0)) {
	  	printf("avcodec_open2() failed\n");
		return FAILURE;
	}

	switch(codecCtx->codec_type) {
		case AVMEDIA_TYPE_AUDIO:
			s->audio_stream = stream_index;
		    s->audio_st = pFormatCtx->streams[stream_index];
			break;
		case AVMEDIA_TYPE_VIDEO:
			s->video_stream = stream_index;
		    s->video_st = pFormatCtx->streams[stream_index];

			AVCodec *targetCodec = avcodec_find_encoder(TARGET_IMAGE_CODEC);
			if (!targetCodec) {
			    printf("avcodec_find_decoder() failed to find encoder\n");
				return FAILURE;
			}

		    s->codecCtx = avcodec_alloc_context3(targetCodec);
			if (!s->codecCtx) {
				printf("avcodec_alloc_context3 failed\n");
				return FAILURE;
			}

			s->codecCtx->bit_rate = s->video_st->codec->bit_rate;
			s->codecCtx->width = s->video_st->codec->width;
			s->codecCtx->height = s->video_st->codec->height;
			s->codecCtx->pix_fmt = TARGET_IMAGE_FORMAT;
			s->codecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
			s->codecCtx->time_base.num = s->video_st->codec->time_base.num;
			s->codecCtx->time_base.den = s->video_st->codec->time_base.den;

			if (!targetCodec || avcodec_open2(s->codecCtx, targetCodec, NULL) < 0) {
			  	printf("avcodec_open2() failed\n");
				return FAILURE;
			}

		    s->sws_ctx = sws_getContext(s->video_st->codec->width,
		    		s->video_st->codec->height,
		    		s->video_st->codec->pix_fmt,
		    		s->video_st->codec->width,
		    		s->video_st->codec->height,
		    		TARGET_IMAGE_FORMAT,
		    		SWS_BILINEAR,
		    		NULL,
		    		NULL,
		    		NULL);
			break;
		default:
			break;
	}

	return SUCCESS;
}
Example #15
0
StreamInfo *FormatContext::getStreamInfo(AVStream *stream) const
{
    if (streamNotValid(stream))
        return nullptr;

    StreamInfo *streamInfo = new StreamInfo;

    if (const AVCodec *codec = avcodec_find_decoder(stream->codecpar->codec_id))
        streamInfo->codec_name = codec->name;

    streamInfo->must_decode = true;
    if (const AVCodecDescriptor *codecDescr = avcodec_descriptor_get(stream->codecpar->codec_id))
    {
        if (codecDescr->props & AV_CODEC_PROP_TEXT_SUB)
            streamInfo->must_decode = false;

        if (streamInfo->codec_name.isEmpty())
            streamInfo->codec_name = codecDescr->name;
    }

    streamInfo->bitrate = stream->codecpar->bit_rate;
    streamInfo->bpcs = stream->codecpar->bits_per_coded_sample;
    streamInfo->codec_tag = stream->codecpar->codec_tag;
    streamInfo->is_default = stream->disposition & AV_DISPOSITION_DEFAULT;
    streamInfo->time_base.num = stream->time_base.num;
    streamInfo->time_base.den = stream->time_base.den;
    streamInfo->type = (QMPlay2MediaType)stream->codecpar->codec_type; //Enumy są takie same

    if (stream->codecpar->extradata_size)
    {
        streamInfo->data.reserve(stream->codecpar->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
        streamInfo->data.resize(stream->codecpar->extradata_size);
        memcpy(streamInfo->data.data(), stream->codecpar->extradata, streamInfo->data.capacity());
        av_free(stream->codecpar->extradata);
        stream->codecpar->extradata = (quint8 *)streamInfo->data.data();
    }

    if (streamInfo->type != QMPLAY2_TYPE_ATTACHMENT)
    {
        QString value;
        if (streamsInfo.count() > 1)
        {
            streamInfo->title  = getTag(stream->metadata, "title");
            streamInfo->artist = getTag(stream->metadata, "artist");
            if (!(value = getTag(stream->metadata, "album")).isEmpty())
                streamInfo->other_info += {QString::number(QMPLAY2_TAG_ALBUM), value};
            if (!(value = getTag(stream->metadata, "genre")).isEmpty())
                streamInfo->other_info += {QString::number(QMPLAY2_TAG_GENRE), value};
            if (!(value = getTag(stream->metadata, "date")).isEmpty())
                streamInfo->other_info += {QString::number(QMPLAY2_TAG_DATE), value};
            if (!(value = getTag(stream->metadata, "comment")).isEmpty())
                streamInfo->other_info += {QString::number(QMPLAY2_TAG_COMMENT), value};
        }
        if (!(value = getTag(stream->metadata, "language", false)).isEmpty() && value != "und")
            streamInfo->other_info += {QString::number(QMPLAY2_TAG_LANGUAGE), value};
    }

    switch (streamInfo->type)
    {
        case QMPLAY2_TYPE_AUDIO:
            streamInfo->format = av_get_sample_fmt_name((AVSampleFormat)stream->codecpar->format);
            streamInfo->channels = stream->codecpar->channels;
            streamInfo->sample_rate = stream->codecpar->sample_rate;
            streamInfo->block_align = stream->codecpar->block_align;
            break;
        case QMPLAY2_TYPE_VIDEO:
        {
            streamInfo->format = av_get_pix_fmt_name((AVPixelFormat)stream->codecpar->format);
            if (stream->sample_aspect_ratio.num)
                streamInfo->sample_aspect_ratio = av_q2d(stream->sample_aspect_ratio);
            else if (stream->codecpar->sample_aspect_ratio.num)
                streamInfo->sample_aspect_ratio = av_q2d(stream->codecpar->sample_aspect_ratio);
            streamInfo->W = stream->codecpar->width;
            streamInfo->H = stream->codecpar->height;
            if (!stillImage)
                streamInfo->FPS = av_q2d(stream->r_frame_rate);

            bool ok = false;
            const double rotation = getTag(stream->metadata, "rotate", false).toDouble(&ok);
            if (ok)
                streamInfo->rotation = rotation;

            if (void *sideData = av_stream_get_side_data(stream, AV_PKT_DATA_SPHERICAL, nullptr))
            {
                streamInfo->spherical = (((AVSphericalMapping *)sideData)->projection == AV_SPHERICAL_EQUIRECTANGULAR);
            }

            break;
        }
        case QMPLAY2_TYPE_ATTACHMENT:
            streamInfo->title = getTag(stream->metadata, "filename", false);
            switch (stream->codecpar->codec_id)
            {
                case AV_CODEC_ID_TTF:
                    streamInfo->codec_name = "TTF";
                    break;
                case AV_CODEC_ID_OTF:
                    streamInfo->codec_name = "OTF";
                    break;
                default:
                    break;
            }
            break;
        default:
            break;
    }

    return streamInfo;
}
Example #16
0
/* write the header (used two times if non streamed) */
static int asf_write_header1(AVFormatContext *s, int64_t file_size,
                             int64_t data_chunk_size)
{
    ASFContext *asf = s->priv_data;
    AVIOContext *pb = s->pb;
    AVDictionaryEntry *tags[5];
    int header_size, n, extra_size, extra_size2, wav_extra_size, file_time;
    int has_title, has_aspect_ratio = 0;
    int metadata_count;
    AVCodecContext *enc;
    int64_t header_offset, cur_pos, hpos;
    int bit_rate;
    int64_t duration;

    ff_metadata_conv(&s->metadata, ff_asf_metadata_conv, NULL);

    tags[0] = av_dict_get(s->metadata, "title", NULL, 0);
    tags[1] = av_dict_get(s->metadata, "author", NULL, 0);
    tags[2] = av_dict_get(s->metadata, "copyright", NULL, 0);
    tags[3] = av_dict_get(s->metadata, "comment", NULL, 0);
    tags[4] = av_dict_get(s->metadata, "rating", NULL, 0);

    duration       = asf->duration + PREROLL_TIME * 10000;
    has_title      = tags[0] || tags[1] || tags[2] || tags[3] || tags[4];
    metadata_count = av_dict_count(s->metadata);

    bit_rate = 0;
    for (n = 0; n < s->nb_streams; n++) {
        enc = s->streams[n]->codec;

        avpriv_set_pts_info(s->streams[n], 32, 1, 1000); /* 32 bit pts in ms */

        bit_rate += enc->bit_rate;
        if (   enc->codec_type == AVMEDIA_TYPE_VIDEO
            && enc->sample_aspect_ratio.num > 0
            && enc->sample_aspect_ratio.den > 0)
            has_aspect_ratio++;
    }

    if (asf->is_streamed) {
        put_chunk(s, 0x4824, 0, 0xc00); /* start of stream (length will be patched later) */
    }

    ff_put_guid(pb, &ff_asf_header);
    avio_wl64(pb, -1); /* header length, will be patched after */
    avio_wl32(pb, 3 + has_title + !!metadata_count + s->nb_streams); /* number of chunks in header */
    avio_w8(pb, 1); /* ??? */
    avio_w8(pb, 2); /* ??? */

    /* file header */
    header_offset = avio_tell(pb);
    hpos          = put_header(pb, &ff_asf_file_header);
    ff_put_guid(pb, &ff_asf_my_guid);
    avio_wl64(pb, file_size);
    file_time = 0;
    avio_wl64(pb, unix_to_file_time(file_time));
    avio_wl64(pb, asf->nb_packets); /* number of packets */
    avio_wl64(pb, duration); /* end time stamp (in 100ns units) */
    avio_wl64(pb, asf->duration); /* duration (in 100ns units) */
    avio_wl64(pb, PREROLL_TIME); /* start time stamp */
    avio_wl32(pb, (asf->is_streamed || !pb->seekable) ? 3 : 2);  /* ??? */
    avio_wl32(pb, s->packet_size); /* packet size */
    avio_wl32(pb, s->packet_size); /* packet size */
    avio_wl32(pb, bit_rate ? bit_rate : -1); /* Maximum data rate in bps */
    end_header(pb, hpos);

    /* unknown headers */
    hpos = put_header(pb, &ff_asf_head1_guid);
    ff_put_guid(pb, &ff_asf_head2_guid);
    avio_wl16(pb, 6);
    if (has_aspect_ratio) {
        int64_t hpos2;
        avio_wl32(pb, 26 + has_aspect_ratio * 84);
        hpos2 = put_header(pb, &ff_asf_metadata_header);
        avio_wl16(pb, 2 * has_aspect_ratio);
        for (n = 0; n < s->nb_streams; n++) {
            enc = s->streams[n]->codec;
            if (   enc->codec_type == AVMEDIA_TYPE_VIDEO
                && enc->sample_aspect_ratio.num > 0
                && enc->sample_aspect_ratio.den > 0) {
                AVRational sar = enc->sample_aspect_ratio;
                avio_wl16(pb, 0);
                // the stream number is set like this below
                avio_wl16(pb, n + 1);
                avio_wl16(pb, 26); // name_len
                avio_wl16(pb,  3); // value_type
                avio_wl32(pb,  4); // value_len
                avio_put_str16le(pb, "AspectRatioX");
                avio_wl32(pb, sar.num);
                avio_wl16(pb, 0);
                // the stream number is set like this below
                avio_wl16(pb, n + 1);
                avio_wl16(pb, 26); // name_len
                avio_wl16(pb,  3); // value_type
                avio_wl32(pb,  4); // value_len
                avio_put_str16le(pb, "AspectRatioY");
                avio_wl32(pb, sar.den);
            }
        }
        end_header(pb, hpos2);
    } else {
        avio_wl32(pb, 0);
    }
    end_header(pb, hpos);

    /* title and other infos */
    if (has_title) {
        int len;
        uint8_t *buf;
        AVIOContext *dyn_buf;

        if (avio_open_dyn_buf(&dyn_buf) < 0)
            return AVERROR(ENOMEM);

        hpos = put_header(pb, &ff_asf_comment_header);

        for (n = 0; n < FF_ARRAY_ELEMS(tags); n++) {
            len = tags[n] ? avio_put_str16le(dyn_buf, tags[n]->value) : 0;
            avio_wl16(pb, len);
        }
        len = avio_close_dyn_buf(dyn_buf, &buf);
        avio_write(pb, buf, len);
        av_freep(&buf);
        end_header(pb, hpos);
    }
    if (metadata_count) {
        AVDictionaryEntry *tag = NULL;
        hpos = put_header(pb, &ff_asf_extended_content_header);
        avio_wl16(pb, metadata_count);
        while ((tag = av_dict_get(s->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
            put_str16(pb, tag->key);
            avio_wl16(pb, 0);
            put_str16(pb, tag->value);
        }
        end_header(pb, hpos);
    }
    /* chapters using ASF markers */
    if (!asf->is_streamed && s->nb_chapters) {
        int ret;
        if (ret = asf_write_markers(s))
            return ret;
    }
    /* stream headers */
    for (n = 0; n < s->nb_streams; n++) {
        int64_t es_pos;
        //        ASFStream *stream = &asf->streams[n];

        enc                 = s->streams[n]->codec;
        asf->streams[n].num = n + 1;
        asf->streams[n].seq = 1;

        switch (enc->codec_type) {
        case AVMEDIA_TYPE_AUDIO:
            wav_extra_size = 0;
            extra_size     = 18 + wav_extra_size;
            extra_size2    = 8;
            break;
        default:
        case AVMEDIA_TYPE_VIDEO:
            wav_extra_size = enc->extradata_size;
            extra_size     = 0x33 + wav_extra_size;
            extra_size2    = 0;
            break;
        }

        hpos = put_header(pb, &ff_asf_stream_header);
        if (enc->codec_type == AVMEDIA_TYPE_AUDIO) {
            ff_put_guid(pb, &ff_asf_audio_stream);
            ff_put_guid(pb, &ff_asf_audio_conceal_spread);
        } else {
            ff_put_guid(pb, &ff_asf_video_stream);
            ff_put_guid(pb, &ff_asf_video_conceal_none);
        }
        avio_wl64(pb, 0); /* ??? */
        es_pos = avio_tell(pb);
        avio_wl32(pb, extra_size); /* wav header len */
        avio_wl32(pb, extra_size2); /* additional data len */
        avio_wl16(pb, n + 1); /* stream number */
        avio_wl32(pb, 0); /* ??? */

        if (enc->codec_type == AVMEDIA_TYPE_AUDIO) {
            /* WAVEFORMATEX header */
            int wavsize = ff_put_wav_header(pb, enc, FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX);

            if (wavsize < 0)
                return -1;
            if (wavsize != extra_size) {
                cur_pos = avio_tell(pb);
                avio_seek(pb, es_pos, SEEK_SET);
                avio_wl32(pb, wavsize); /* wav header len */
                avio_seek(pb, cur_pos, SEEK_SET);
            }
            /* ERROR Correction */
            avio_w8(pb, 0x01);
            if (enc->codec_id == AV_CODEC_ID_ADPCM_G726 || !enc->block_align) {
                avio_wl16(pb, 0x0190);
                avio_wl16(pb, 0x0190);
            } else {
                avio_wl16(pb, enc->block_align);
                avio_wl16(pb, enc->block_align);
            }
            avio_wl16(pb, 0x01);
            avio_w8(pb, 0x00);
        } else {
            avio_wl32(pb, enc->width);
            avio_wl32(pb, enc->height);
            avio_w8(pb, 2); /* ??? */
            avio_wl16(pb, 40 + enc->extradata_size); /* size */

            /* BITMAPINFOHEADER header */
            ff_put_bmp_header(pb, enc, ff_codec_bmp_tags, 1, 0);
        }
        end_header(pb, hpos);
    }

    /* media comments */

    hpos = put_header(pb, &ff_asf_codec_comment_header);
    ff_put_guid(pb, &ff_asf_codec_comment1_header);
    avio_wl32(pb, s->nb_streams);
    for (n = 0; n < s->nb_streams; n++) {
        const AVCodecDescriptor *codec_desc;
        const char *desc;

        enc  = s->streams[n]->codec;
        codec_desc = avcodec_descriptor_get(enc->codec_id);

        if (enc->codec_type == AVMEDIA_TYPE_AUDIO)
            avio_wl16(pb, 2);
        else if (enc->codec_type == AVMEDIA_TYPE_VIDEO)
            avio_wl16(pb, 1);
        else
            avio_wl16(pb, -1);

        if (enc->codec_id == AV_CODEC_ID_WMAV2)
            desc = "Windows Media Audio V8";
        else
            desc = codec_desc ? codec_desc->name : NULL;

        if (desc) {
            AVIOContext *dyn_buf;
            uint8_t *buf;
            int len;

            if (avio_open_dyn_buf(&dyn_buf) < 0)
                return AVERROR(ENOMEM);

            avio_put_str16le(dyn_buf, desc);
            len = avio_close_dyn_buf(dyn_buf, &buf);
            avio_wl16(pb, len / 2); // "number of characters" = length in bytes / 2

            avio_write(pb, buf, len);
            av_freep(&buf);
        } else
            avio_wl16(pb, 0);

        avio_wl16(pb, 0); /* no parameters */

        /* id */
        if (enc->codec_type == AVMEDIA_TYPE_AUDIO) {
            avio_wl16(pb, 2);
            avio_wl16(pb, enc->codec_tag);
        } else {
            avio_wl16(pb, 4);
            avio_wl32(pb, enc->codec_tag);
        }
        if (!enc->codec_tag)
            return -1;
    }
    end_header(pb, hpos);

    /* patch the header size fields */

    cur_pos     = avio_tell(pb);
    header_size = cur_pos - header_offset;
    if (asf->is_streamed) {
        header_size += 8 + 30 + DATA_HEADER_SIZE;

        avio_seek(pb, header_offset - 10 - 30, SEEK_SET);
        avio_wl16(pb, header_size);
        avio_seek(pb, header_offset - 2 - 30, SEEK_SET);
        avio_wl16(pb, header_size);

        header_size -= 8 + 30 + DATA_HEADER_SIZE;
    }
    header_size += 24 + 6;
    avio_seek(pb, header_offset - 14, SEEK_SET);
    avio_wl64(pb, header_size);
    avio_seek(pb, cur_pos, SEEK_SET);

    /* movie chunk, followed by packets of packet_size */
    asf->data_offset = cur_pos;
    ff_put_guid(pb, &ff_asf_data_header);
    avio_wl64(pb, data_chunk_size);
    ff_put_guid(pb, &ff_asf_my_guid);
    avio_wl64(pb, asf->nb_packets); /* nb packets */
    avio_w8(pb, 1); /* ??? */
    avio_w8(pb, 1); /* ??? */
    return 0;
}
Example #17
0
std::string get_codec_name(AVCodecContext *pCodecCtx)
{
  AVCodecID id = pCodecCtx->codec_id;

  // Grab the codec
  const AVCodec *p = avcodec_find_decoder(id);
  const AVCodecDescriptor *desc = avcodec_descriptor_get(id);
  const char *profile = avcodec_profile_name(id, pCodecCtx->profile);

  std::ostringstream codec_name;

  const char *nice_name = nullptr;
  for (int i = 0; i < countof(nice_codec_names); ++i)
  {
    if (nice_codec_names[i].id == id) {
      nice_name = nice_codec_names[i].name;
      break;
    }
  }

  if (id == AV_CODEC_ID_DTS && pCodecCtx->codec_tag == 0xA2) {
    profile = "DTS Express";
  }

  if (id == AV_CODEC_ID_H264 && profile) {
    codec_name << nice_name << " " << tolower(profile);
    if (pCodecCtx->level && pCodecCtx->level != FF_LEVEL_UNKNOWN && pCodecCtx->level < 1000) {
      char l_buf[5];
      sprintf_s(l_buf, "%.1f", pCodecCtx->level / 10.0);
      codec_name << " L" << l_buf;
    }
  } else if (id == AV_CODEC_ID_VC1 && profile) {
    codec_name << nice_name << " " << tolower(profile);
    if (pCodecCtx->level != FF_LEVEL_UNKNOWN) {
      codec_name << " L" << pCodecCtx->level;
    }
  } else if (id == AV_CODEC_ID_DTS && profile) {
    codec_name << tolower(profile);
  } else if (id == AV_CODEC_ID_JPEG2000 && profile) {
    codec_name << tolower(profile);
  } else if (nice_name) {
    codec_name << nice_name;
    if (profile)
      codec_name << " " << tolower(profile);
  } else if (desc && desc->name) {
    codec_name << desc->name;
    if (profile)
      codec_name << " " << tolower(profile);
  } else if (p && p->name) {
    codec_name << p->name;
    if (profile)
      codec_name << " " << tolower(profile);
  } else {
    /* output avi tags */
    char buf[32];
    av_get_codec_tag_string(buf, sizeof(buf), pCodecCtx->codec_tag);
    codec_name << buf;
    sprintf_s(buf, "0x%04X", pCodecCtx->codec_tag);
    codec_name  << " / " << buf;
  }
  return codec_name.str();
}
Example #18
0
static int init_muxer(AVFormatContext *s, AVDictionary **options)
{
    int ret = 0, i;
    AVStream *st;
    AVDictionary *tmp = NULL;
    AVCodecContext *codec = NULL;
    AVOutputFormat *of = s->oformat;
    const AVCodecDescriptor *desc;

    if (options)
        av_dict_copy(&tmp, *options, 0);

    if ((ret = av_opt_set_dict(s, &tmp)) < 0)
        goto fail;

#if FF_API_LAVF_BITEXACT
    if (s->nb_streams && s->streams[0]->codec->flags & AV_CODEC_FLAG_BITEXACT)
        s->flags |= AVFMT_FLAG_BITEXACT;
#endif

    // some sanity checks
    if (s->nb_streams == 0 && !(of->flags & AVFMT_NOSTREAMS)) {
        av_log(s, AV_LOG_ERROR, "no streams\n");
        ret = AVERROR(EINVAL);
        goto fail;
    }

    for (i = 0; i < s->nb_streams; i++) {
        st    = s->streams[i];
        codec = st->codec;

#if FF_API_LAVF_CODEC_TB
FF_DISABLE_DEPRECATION_WARNINGS
        if (!st->time_base.num && codec->time_base.num) {
            av_log(s, AV_LOG_WARNING, "Using AVStream.codec.time_base as a "
                   "timebase hint to the muxer is deprecated. Set "
                   "AVStream.time_base instead.\n");
            avpriv_set_pts_info(st, 64, codec->time_base.num, codec->time_base.den);
        }
FF_ENABLE_DEPRECATION_WARNINGS
#endif

        if (!st->time_base.num) {
            /* fall back on the default timebase values */
            if (codec->codec_type == AVMEDIA_TYPE_AUDIO && codec->sample_rate)
                avpriv_set_pts_info(st, 64, 1, codec->sample_rate);
            else
                avpriv_set_pts_info(st, 33, 1, 90000);
        }

        switch (codec->codec_type) {
        case AVMEDIA_TYPE_AUDIO:
            if (codec->sample_rate <= 0) {
                av_log(s, AV_LOG_ERROR, "sample rate not set\n");
                ret = AVERROR(EINVAL);
                goto fail;
            }
            if (!codec->block_align)
                codec->block_align = codec->channels *
                                     av_get_bits_per_sample(codec->codec_id) >> 3;
            break;
        case AVMEDIA_TYPE_VIDEO:
            if ((codec->width <= 0 || codec->height <= 0) &&
                !(of->flags & AVFMT_NODIMENSIONS)) {
                av_log(s, AV_LOG_ERROR, "dimensions not set\n");
                ret = AVERROR(EINVAL);
                goto fail;
            }

            if (av_cmp_q(st->sample_aspect_ratio,
                         codec->sample_aspect_ratio)) {
                if (st->sample_aspect_ratio.num != 0 &&
                    st->sample_aspect_ratio.den != 0 &&
                    codec->sample_aspect_ratio.den != 0 &&
                    codec->sample_aspect_ratio.den != 0) {
                    av_log(s, AV_LOG_ERROR, "Aspect ratio mismatch between muxer "
                            "(%d/%d) and encoder layer (%d/%d)\n",
                            st->sample_aspect_ratio.num, st->sample_aspect_ratio.den,
                            codec->sample_aspect_ratio.num,
                            codec->sample_aspect_ratio.den);
                    ret = AVERROR(EINVAL);
                    goto fail;
                }
            }
            break;
        }

        desc = avcodec_descriptor_get(codec->codec_id);
        if (desc && desc->props & AV_CODEC_PROP_REORDER)
            st->internal->reorder = 1;

        if (of->codec_tag) {
            if (codec->codec_tag &&
                codec->codec_id == AV_CODEC_ID_RAWVIDEO &&
                !av_codec_get_tag(of->codec_tag, codec->codec_id) &&
                !validate_codec_tag(s, st)) {
                // the current rawvideo encoding system ends up setting
                // the wrong codec_tag for avi, we override it here
                codec->codec_tag = 0;
            }
            if (codec->codec_tag) {
                if (!validate_codec_tag(s, st)) {
                    char tagbuf[32];
                    av_get_codec_tag_string(tagbuf, sizeof(tagbuf), codec->codec_tag);
                    av_log(s, AV_LOG_ERROR,
                           "Tag %s/0x%08x incompatible with output codec id '%d'\n",
                           tagbuf, codec->codec_tag, codec->codec_id);
                    ret = AVERROR_INVALIDDATA;
                    goto fail;
                }
            } else
                codec->codec_tag = av_codec_get_tag(of->codec_tag, codec->codec_id);
        }

        if (of->flags & AVFMT_GLOBALHEADER &&
            !(codec->flags & AV_CODEC_FLAG_GLOBAL_HEADER))
            av_log(s, AV_LOG_WARNING,
                   "Codec for stream %d does not use global headers "
                   "but container format requires global headers\n", i);

        if (codec->codec_type != AVMEDIA_TYPE_ATTACHMENT)
            s->internal->nb_interleaved_streams++;
    }

    if (!s->priv_data && of->priv_data_size > 0) {
        s->priv_data = av_mallocz(of->priv_data_size);
        if (!s->priv_data) {
            ret = AVERROR(ENOMEM);
            goto fail;
        }
        if (of->priv_class) {
            *(const AVClass **)s->priv_data = of->priv_class;
            av_opt_set_defaults(s->priv_data);
            if ((ret = av_opt_set_dict(s->priv_data, &tmp)) < 0)
                goto fail;
        }
    }

    /* set muxer identification string */
    if (!(s->flags & AVFMT_FLAG_BITEXACT)) {
        av_dict_set(&s->metadata, "encoder", LIBAVFORMAT_IDENT, 0);
    }

    if (options) {
         av_dict_free(options);
         *options = tmp;
    }

    return 0;

fail:
    av_dict_free(&tmp);
    return ret;
}
Example #19
0
bool SubtitleProcessorFFmpeg::processSubtitle()
{
    m_frames.clear();
    int ss = m_reader.subtitleStream();
    if (ss < 0) {
        qWarning("no subtitle stream found");
        return false;
    }
    AVCodecContext *ctx = m_reader.subtitleCodecContext();
    AVCodec *dec = avcodec_find_decoder(ctx->codec_id);
    if (!dec) {
        qWarning("Failed to find subtitle codec %s", avcodec_get_name(ctx->codec_id));
        return false;
    }
    const AVCodecDescriptor *dec_desc = avcodec_descriptor_get(ctx->codec_id);
    if (dec_desc && !(dec_desc->props & AV_CODEC_PROP_TEXT_SUB)) {
        qWarning("Only text based subtitles are currently supported");
        return false;
    }
    AVDictionary *codec_opts = NULL;
    int ret = avcodec_open2(ctx, dec, &codec_opts);
    if (ret < 0) {
        qWarning("open subtitle codec error: %s", av_err2str(ret));
        av_dict_free(&codec_opts);
        return false;
    }
    while (!m_reader.atEnd()) {
        if (!m_reader.readFrame())
            continue;
        if (!m_reader.packet()->isValid())
            continue;
        if (m_reader.stream() != ss)
            continue;
        AVPacket packet;
        av_init_packet(&packet);
        packet.size = m_reader.packet()->data.size();
        packet.data = (uint8_t*)m_reader.packet()->data.constData();
        int got_subtitle = 0;
        AVSubtitle sub;
        memset(&sub, 0, sizeof(sub));
        ret = avcodec_decode_subtitle2(ctx, &sub, &got_subtitle, &packet);
        if (ret < 0 || !got_subtitle) {
            av_free_packet(&packet);
            avsubtitle_free(&sub);
            continue;
        }
        qreal pts = m_reader.packet()->pts;
        SubtitleFrame frame;
        frame.begin = pts + qreal(sub.start_display_time)/1000.0;
        frame.end = pts + qreal(sub.end_display_time)/1000.0;
       // qDebug() << QTime(0, 0, 0).addMSecs(frame.begin*1000.0) << "-" << QTime(0, 0, 0).addMSecs(frame.end*1000.0) << " fmt: " << sub.format << " pts: " << m_reader.packet()->pts //sub.pts
        //            << " rects: " << sub.num_rects;
        for (unsigned i = 0; i < sub.num_rects; i++) {
            switch (sub.rects[i]->type) {
            case SUBTITLE_ASS:
                frame.text.append(PlainText::fromAss(sub.rects[i]->ass)).append('\n');
                break;
            case SUBTITLE_TEXT:
                frame.text.append(sub.rects[i]->text).append('\n');
                break;
            case SUBTITLE_BITMAP:
                break;
            default:
                break;
            }
        }
        m_frames.append(frame);
        av_free_packet(&packet);
        avsubtitle_free(&sub);
    }
    avcodec_close(ctx);
    return true;
}