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; }
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; }
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; }
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; }
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; }
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 }
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; }
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; }
/* * 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; }
/* 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; }
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; }
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; }
/* 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; }
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(); }
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; }
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; }