static int ffm_write_recommended_config(AVIOContext *pb, AVCodecContext *ctx, unsigned tag, const char *configuration) { int ret; const AVCodec *enc = ctx->codec ? ctx->codec : avcodec_find_encoder(ctx->codec_id); AVIOContext *tmp; AVDictionaryEntry *t = NULL; AVDictionary *all = NULL, *comm = NULL, *prv = NULL; char *buf = NULL; if (!enc || !enc->priv_class || !enc->priv_data_size) { /* codec is not known/has no private options, so save everything as common options */ if (avio_open_dyn_buf(&tmp) < 0) return AVERROR(ENOMEM); avio_put_str(tmp, configuration); write_header_chunk(pb, tmp, tag); return 0; } if ((ret = av_dict_parse_string(&all, configuration, "=", ",", 0)) < 0) return ret; while ((t = av_dict_get(all, "", t, AV_DICT_IGNORE_SUFFIX))) { if (av_opt_find((void *)&enc->priv_class, t->key, NULL, 0, AV_OPT_SEARCH_FAKE_OBJ)) { if ((ret = av_dict_set(&prv, t->key, t->value, 0)) < 0) goto fail; } else if ((ret = av_dict_set(&comm, t->key, t->value, 0)) < 0) goto fail; } if (comm) { if ((ret = av_dict_get_string(comm, &buf, '=', ',')) < 0 || (ret = avio_open_dyn_buf(&tmp)) < 0) goto fail; avio_put_str(tmp, buf); av_freep(&buf); write_header_chunk(pb, tmp, tag); } if (prv) { if ((ret = av_dict_get_string(prv, &buf, '=', ',')) < 0 || (ret = avio_open_dyn_buf(&tmp)) < 0) goto fail; avio_put_str(tmp, buf); write_header_chunk(pb, tmp, MKBETAG('C', 'P', 'R', 'V')); } fail: av_free(buf); av_dict_free(&all); av_dict_free(&comm); av_dict_free(&prv); return ret; }
static int ffm_write_header_codec_private_ctx(AVFormatContext *s, AVCodecContext *ctx, int type) { AVIOContext *pb = s->pb; AVIOContext *tmp; char *buf = NULL; int ret; const AVCodec *enc = ctx->codec ? ctx->codec : avcodec_find_encoder(ctx->codec_id); if (!enc) { av_log(s, AV_LOG_WARNING, "Stream codec is not found. Codec private options are not stored.\n"); return 0; } if (ctx->priv_data && enc->priv_class && enc->priv_data_size) { if ((ret = av_opt_serialize(ctx->priv_data, AV_OPT_FLAG_ENCODING_PARAM | type, AV_OPT_SERIALIZE_SKIP_DEFAULTS, &buf, '=', ',')) < 0) return ret; if (buf && strlen(buf)) { if (avio_open_dyn_buf(&tmp) < 0) { av_free(buf); return AVERROR(ENOMEM); } avio_put_str(tmp, buf); write_header_chunk(pb, tmp, MKBETAG('C', 'P', 'R', 'V')); } av_free(buf); } return 0; }
int ff_ape_write_tag(AVFormatContext *s) { AVDictionaryEntry *e = NULL; int64_t start, end; int size, count = 0; if (!s->pb->seekable) return 0; start = avio_tell(s->pb); // header avio_write(s->pb, "APETAGEX", 8); // id avio_wl32 (s->pb, APE_TAG_VERSION); // version avio_wl32(s->pb, 0); // reserve space for size avio_wl32(s->pb, 0); // reserve space for tag count // flags avio_wl32(s->pb, APE_TAG_FLAG_CONTAINS_HEADER | APE_TAG_FLAG_CONTAINS_FOOTER | APE_TAG_FLAG_IS_HEADER); ffio_fill(s->pb, 0, 8); // reserved while ((e = av_dict_get(s->metadata, "", e, AV_DICT_IGNORE_SUFFIX))) { int val_len; if (!string_is_ascii(e->key)) { av_log(s, AV_LOG_WARNING, "Non ASCII keys are not allowed\n"); continue; } val_len = strlen(e->value); avio_wl32(s->pb, val_len); // value length avio_wl32(s->pb, 0); // item flags avio_put_str(s->pb, e->key); // key avio_write(s->pb, e->value, val_len); // value count++; } size = avio_tell(s->pb) - start; // footer avio_write(s->pb, "APETAGEX", 8); // id avio_wl32 (s->pb, APE_TAG_VERSION); // version avio_wl32(s->pb, size); // size avio_wl32(s->pb, count); // tag count // flags avio_wl32(s->pb, APE_TAG_FLAG_CONTAINS_HEADER | APE_TAG_FLAG_CONTAINS_FOOTER); ffio_fill(s->pb, 0, 8); // reserved // update values in the header end = avio_tell(s->pb); avio_seek(s->pb, start + 12, SEEK_SET); avio_wl32(s->pb, size); avio_wl32(s->pb, count); avio_seek(s->pb, end, SEEK_SET); return 0; }
void ff_riff_write_info_tag(AVIOContext *pb, const char *tag, const char *str) { int len = strlen(str); if (len > 0) { len++; ffio_wfourcc(pb, tag); avio_wl32(pb, len); avio_put_str(pb, str); if (len & 1) avio_w8(pb, 0); } }
static void bwf_write_bext_chunk(AVFormatContext *s) { AVDictionaryEntry *tmp_tag; uint64_t time_reference = 0; int64_t bext = ff_start_tag(s->pb, "bext"); bwf_write_bext_string(s, "description", 256); bwf_write_bext_string(s, "originator", 32); bwf_write_bext_string(s, "originator_reference", 32); bwf_write_bext_string(s, "origination_date", 10); bwf_write_bext_string(s, "origination_time", 8); if (tmp_tag = av_dict_get(s->metadata, "time_reference", NULL, 0)) time_reference = strtoll(tmp_tag->value, NULL, 10); avio_wl64(s->pb, time_reference); avio_wl16(s->pb, 1); // set version to 1 if (tmp_tag = av_dict_get(s->metadata, "umid", NULL, 0)) { unsigned char umidpart_str[17] = {0}; int i; uint64_t umidpart; int len = strlen(tmp_tag->value+2); for (i = 0; i < len/16; i++) { memcpy(umidpart_str, tmp_tag->value + 2 + (i*16), 16); umidpart = strtoll(umidpart_str, NULL, 16); avio_wb64(s->pb, umidpart); } ffio_fill(s->pb, 0, 64 - i*8); } else ffio_fill(s->pb, 0, 64); // zero UMID ffio_fill(s->pb, 0, 190); // Reserved if (tmp_tag = av_dict_get(s->metadata, "coding_history", NULL, 0)) avio_put_str(s->pb, tmp_tag->value); ff_end_tag(s->pb, bext); }
int ff_ape_write_tag(AVFormatContext *s) { AVDictionaryEntry *e = NULL; int size, ret, count = 0; AVIOContext *dyn_bc = NULL; uint8_t *dyn_buf = NULL; if ((ret = avio_open_dyn_buf(&dyn_bc)) < 0) goto end; // flags avio_wl32(dyn_bc, APE_TAG_FLAG_CONTAINS_HEADER | APE_TAG_FLAG_CONTAINS_FOOTER | APE_TAG_FLAG_IS_HEADER); ffio_fill(dyn_bc, 0, 8); // reserved ff_standardize_creation_time(s); while ((e = av_dict_get(s->metadata, "", e, AV_DICT_IGNORE_SUFFIX))) { int val_len; if (!string_is_ascii(e->key)) { av_log(s, AV_LOG_WARNING, "Non ASCII keys are not allowed\n"); continue; } val_len = strlen(e->value); avio_wl32(dyn_bc, val_len); // value length avio_wl32(dyn_bc, 0); // item flags avio_put_str(dyn_bc, e->key); // key avio_write(dyn_bc, e->value, val_len); // value count++; } if (!count) goto end; size = avio_close_dyn_buf(dyn_bc, &dyn_buf); if (size <= 0) goto end; size += 20; // header avio_write(s->pb, "APETAGEX", 8); // id avio_wl32(s->pb, APE_TAG_VERSION); // version avio_wl32(s->pb, size); avio_wl32(s->pb, count); avio_write(s->pb, dyn_buf, size - 20); // footer avio_write(s->pb, "APETAGEX", 8); // id avio_wl32(s->pb, APE_TAG_VERSION); // version avio_wl32(s->pb, size); // size avio_wl32(s->pb, count); // tag count // flags avio_wl32(s->pb, APE_TAG_FLAG_CONTAINS_HEADER | APE_TAG_FLAG_CONTAINS_FOOTER); ffio_fill(s->pb, 0, 8); // reserved end: if (dyn_bc && !dyn_buf) avio_close_dyn_buf(dyn_bc, &dyn_buf); av_freep(&dyn_buf); return ret; }
static int caf_write_header(AVFormatContext *s) { AVIOContext *pb = s->pb; AVCodecContext *enc = s->streams[0]->codec; CAFContext *caf = s->priv_data; AVDictionaryEntry *t = NULL; unsigned int codec_tag = ff_codec_get_tag(ff_codec_caf_tags, enc->codec_id); int64_t chunk_size = 0; int frame_size = enc->frame_size; if (s->nb_streams != 1) { av_log(s, AV_LOG_ERROR, "CAF files have exactly one stream\n"); return AVERROR(EINVAL); } switch (enc->codec_id) { case AV_CODEC_ID_AAC: av_log(s, AV_LOG_ERROR, "muxing codec currently unsupported\n"); return AVERROR_PATCHWELCOME; } if (!codec_tag) { av_log(s, AV_LOG_ERROR, "unsupported codec\n"); return AVERROR_INVALIDDATA; } if (!enc->block_align && !pb->seekable) { av_log(s, AV_LOG_ERROR, "Muxing variable packet size not supported on non seekable output\n"); return AVERROR_INVALIDDATA; } if (enc->codec_id != AV_CODEC_ID_MP3 || frame_size != 576) frame_size = samples_per_packet(enc->codec_id, enc->channels, enc->block_align); ffio_wfourcc(pb, "caff"); //< mFileType avio_wb16(pb, 1); //< mFileVersion avio_wb16(pb, 0); //< mFileFlags ffio_wfourcc(pb, "desc"); //< Audio Description chunk avio_wb64(pb, 32); //< mChunkSize avio_wb64(pb, av_double2int(enc->sample_rate)); //< mSampleRate avio_wl32(pb, codec_tag); //< mFormatID avio_wb32(pb, codec_flags(enc->codec_id)); //< mFormatFlags avio_wb32(pb, enc->block_align); //< mBytesPerPacket avio_wb32(pb, frame_size); //< mFramesPerPacket avio_wb32(pb, enc->channels); //< mChannelsPerFrame avio_wb32(pb, av_get_bits_per_sample(enc->codec_id)); //< mBitsPerChannel if (enc->channel_layout) { ffio_wfourcc(pb, "chan"); avio_wb64(pb, 12); ff_mov_write_chan(pb, enc->channel_layout); } if (enc->codec_id == AV_CODEC_ID_ALAC) { ffio_wfourcc(pb, "kuki"); avio_wb64(pb, 12 + enc->extradata_size); avio_write(pb, "\0\0\0\14frmaalac", 12); avio_write(pb, enc->extradata, enc->extradata_size); } else if (enc->codec_id == AV_CODEC_ID_AMR_NB) { ffio_wfourcc(pb, "kuki"); avio_wb64(pb, 29); avio_write(pb, "\0\0\0\14frmasamr", 12); avio_wb32(pb, 0x11); /* size */ avio_write(pb, "samrFFMP", 8); avio_w8(pb, 0); /* decoder version */ avio_wb16(pb, 0x81FF); /* Mode set (all modes for AMR_NB) */ avio_w8(pb, 0x00); /* Mode change period (no restriction) */ avio_w8(pb, 0x01); /* Frames per sample */ } else if (enc->codec_id == AV_CODEC_ID_QDM2) { ffio_wfourcc(pb, "kuki"); avio_wb64(pb, enc->extradata_size); avio_write(pb, enc->extradata, enc->extradata_size); } if (av_dict_count(s->metadata)) { ffio_wfourcc(pb, "info"); //< Information chunk while ((t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX))) { chunk_size += strlen(t->key) + strlen(t->value) + 2; } avio_wb64(pb, chunk_size + 4); avio_wb32(pb, av_dict_count(s->metadata)); t = NULL; while ((t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX))) { avio_put_str(pb, t->key); avio_put_str(pb, t->value); } } ffio_wfourcc(pb, "data"); //< Audio Data chunk caf->data = avio_tell(pb); avio_wb64(pb, -1); //< mChunkSize avio_wb32(pb, 0); //< mEditCount avio_flush(pb); return 0; }
static int ffm_write_header(AVFormatContext *s) { FFMContext *ffm = s->priv_data; AVStream *st; AVIOContext *pb = s->pb; AVCodecContext *codec; int bit_rate, i; ffm->packet_size = FFM_PACKET_SIZE; /* header */ avio_wl32(pb, MKTAG('F', 'F', 'M', '1')); avio_wb32(pb, ffm->packet_size); avio_wb64(pb, 0); /* current write position */ avio_wb32(pb, s->nb_streams); bit_rate = 0; for(i=0;i<s->nb_streams;i++) { st = s->streams[i]; bit_rate += st->codec->bit_rate; } avio_wb32(pb, bit_rate); /* list of streams */ for(i=0;i<s->nb_streams;i++) { st = s->streams[i]; avpriv_set_pts_info(st, 64, 1, 1000000); codec = st->codec; /* generic info */ avio_wb32(pb, codec->codec_id); avio_w8(pb, codec->codec_type); avio_wb32(pb, codec->bit_rate); avio_wb32(pb, codec->flags); avio_wb32(pb, codec->flags2); avio_wb32(pb, codec->debug); /* specific info */ switch(codec->codec_type) { case AVMEDIA_TYPE_VIDEO: avio_wb32(pb, codec->time_base.num); avio_wb32(pb, codec->time_base.den); avio_wb16(pb, codec->width); avio_wb16(pb, codec->height); avio_wb16(pb, codec->gop_size); avio_wb32(pb, codec->pix_fmt); avio_w8(pb, codec->qmin); avio_w8(pb, codec->qmax); avio_w8(pb, codec->max_qdiff); avio_wb16(pb, (int) (codec->qcompress * 10000.0)); avio_wb16(pb, (int) (codec->qblur * 10000.0)); avio_wb32(pb, codec->bit_rate_tolerance); avio_put_str(pb, codec->rc_eq ? codec->rc_eq : "tex^qComp"); avio_wb32(pb, codec->rc_max_rate); avio_wb32(pb, codec->rc_min_rate); avio_wb32(pb, codec->rc_buffer_size); avio_wb64(pb, av_double2int(codec->i_quant_factor)); avio_wb64(pb, av_double2int(codec->b_quant_factor)); avio_wb64(pb, av_double2int(codec->i_quant_offset)); avio_wb64(pb, av_double2int(codec->b_quant_offset)); avio_wb32(pb, codec->dct_algo); avio_wb32(pb, codec->strict_std_compliance); avio_wb32(pb, codec->max_b_frames); avio_wb32(pb, codec->mpeg_quant); avio_wb32(pb, codec->intra_dc_precision); avio_wb32(pb, codec->me_method); avio_wb32(pb, codec->mb_decision); avio_wb32(pb, codec->nsse_weight); avio_wb32(pb, codec->frame_skip_cmp); avio_wb64(pb, av_double2int(codec->rc_buffer_aggressivity)); avio_wb32(pb, codec->codec_tag); avio_w8(pb, codec->thread_count); avio_wb32(pb, codec->coder_type); avio_wb32(pb, codec->me_cmp); avio_wb32(pb, codec->me_subpel_quality); avio_wb32(pb, codec->me_range); avio_wb32(pb, codec->keyint_min); avio_wb32(pb, codec->scenechange_threshold); avio_wb32(pb, codec->b_frame_strategy); avio_wb64(pb, av_double2int(codec->qcompress)); avio_wb64(pb, av_double2int(codec->qblur)); avio_wb32(pb, codec->max_qdiff); avio_wb32(pb, codec->refs); break; case AVMEDIA_TYPE_AUDIO: avio_wb32(pb, codec->sample_rate); avio_wl16(pb, codec->channels); avio_wl16(pb, codec->frame_size); avio_wl16(pb, codec->sample_fmt); break; default: return -1; } if (codec->flags & CODEC_FLAG_GLOBAL_HEADER) { avio_wb32(pb, codec->extradata_size); avio_write(pb, codec->extradata, codec->extradata_size); } } /* flush until end of block reached */ while ((avio_tell(pb) % ffm->packet_size) != 0) avio_w8(pb, 0); avio_flush(pb); /* init packet mux */ ffm->packet_ptr = ffm->packet; ffm->packet_end = ffm->packet + ffm->packet_size - FFM_HEADER_SIZE; av_assert0(ffm->packet_end >= ffm->packet); ffm->frame_offset = 0; ffm->dts = 0; ffm->first_packet = 1; return 0; }