static int gxf_write_umf_media_mpeg(AVIOContext *pb, AVStream *st) { GXFStreamContext *sc = st->priv_data; if (st->codec->pix_fmt == PIX_FMT_YUV422P) avio_wl32(pb, 2); else avio_wl32(pb, 1); /* default to 420 */ avio_wl32(pb, sc->first_gop_closed == 1); /* closed = 1, open = 0, unknown = 255 */ avio_wl32(pb, 3); /* top = 1, bottom = 2, frame = 3, unknown = 0 */ avio_wl32(pb, 1); /* I picture per GOP */ avio_wl32(pb, sc->p_per_gop); avio_wl32(pb, sc->b_per_i_or_p); if (st->codec->codec_id == CODEC_ID_MPEG2VIDEO) avio_wl32(pb, 2); else if (st->codec->codec_id == CODEC_ID_MPEG1VIDEO) avio_wl32(pb, 1); else avio_wl32(pb, 0); avio_wl32(pb, 0); /* reserved */ return 32; }
static int gxf_write_umf_media_description(AVFormatContext *s) { GXFContext *gxf = s->priv_data; AVIOContext *pb = s->pb; int64_t pos; int i, j; pos = url_ftell(pb); gxf->umf_media_offset = pos - gxf->umf_start_offset; for (i = 0; i <= s->nb_streams; ++i) { GXFStreamContext *sc; int64_t startpos, curpos; if (i == s->nb_streams) sc = &gxf->timecode_track; else sc = s->streams[i]->priv_data; startpos = url_ftell(pb); avio_wl16(pb, 0); /* length */ avio_wl16(pb, sc->media_info); avio_wl16(pb, 0); /* reserved */ avio_wl16(pb, 0); /* reserved */ avio_wl32(pb, gxf->nb_fields); avio_wl32(pb, 0); /* attributes rw, ro */ avio_wl32(pb, 0); /* mark in */ avio_wl32(pb, gxf->nb_fields); /* mark out */ avio_write(pb, ES_NAME_PATTERN, strlen(ES_NAME_PATTERN)); avio_wb16(pb, sc->media_info); for (j = strlen(ES_NAME_PATTERN)+2; j < 88; j++) avio_w8(pb, 0); avio_wl32(pb, sc->track_type); avio_wl32(pb, sc->sample_rate); avio_wl32(pb, sc->sample_size); avio_wl32(pb, 0); /* reserved */ if (sc == &gxf->timecode_track) gxf_write_umf_media_timecode(pb, sc); /* 8 0bytes */ else { AVStream *st = s->streams[i]; switch (st->codec->codec_id) { case CODEC_ID_MPEG1VIDEO: case CODEC_ID_MPEG2VIDEO: gxf_write_umf_media_mpeg(pb, st); break; case CODEC_ID_PCM_S16LE: gxf_write_umf_media_audio(pb, sc); break; case CODEC_ID_DVVIDEO: gxf_write_umf_media_dv(pb, sc); break; } } curpos = url_ftell(pb); avio_seek(pb, startpos, SEEK_SET); avio_wl16(pb, curpos - startpos); avio_seek(pb, curpos, SEEK_SET); } return url_ftell(pb) - pos; }
static int avi_write_packet(AVFormatContext *s, AVPacket *pkt) { AVIContext *avi = s->priv_data; AVIOContext *pb = s->pb; unsigned char tag[5]; unsigned int flags=0; const int stream_index= pkt->stream_index; AVIStream *avist= s->streams[stream_index]->priv_data; AVCodecContext *enc= s->streams[stream_index]->codec; int size= pkt->size; // av_log(s, AV_LOG_DEBUG, "%"PRId64" %d %d\n", pkt->dts, avi->packet_count[stream_index], stream_index); while(enc->block_align==0 && pkt->dts != AV_NOPTS_VALUE && pkt->dts > avist->packet_count){ AVPacket empty_packet; av_init_packet(&empty_packet); empty_packet.size= 0; empty_packet.data= NULL; empty_packet.stream_index= stream_index; avi_write_packet(s, &empty_packet); // av_log(s, AV_LOG_DEBUG, "dup %"PRId64" %d\n", pkt->dts, avi->packet_count[stream_index]); } avist->packet_count++; // Make sure to put an OpenDML chunk when the file size exceeds the limits if (!url_is_streamed(pb) && (url_ftell(pb) - avi->riff_start > AVI_MAX_RIFF_SIZE)) { avi_write_ix(s); ff_end_tag(pb, avi->movi_list); if (avi->riff_id == 1) avi_write_idx1(s); ff_end_tag(pb, avi->riff_start); avi->movi_list = avi_start_new_riff(s, pb, "AVIX", "movi"); } avi_stream2fourcc(tag, stream_index, enc->codec_type); if(pkt->flags&AV_PKT_FLAG_KEY) flags = 0x10; if (enc->codec_type == AVMEDIA_TYPE_AUDIO) { avist->audio_strm_length += size; } if (!url_is_streamed(s->pb)) { AVIIndex* idx = &avist->indexes; int cl = idx->entry / AVI_INDEX_CLUSTER_SIZE; int id = idx->entry % AVI_INDEX_CLUSTER_SIZE; if (idx->ents_allocated <= idx->entry) { idx->cluster = av_realloc(idx->cluster, (cl+1)*sizeof(void*)); if (!idx->cluster) return -1; idx->cluster[cl] = av_malloc(AVI_INDEX_CLUSTER_SIZE*sizeof(AVIIentry)); if (!idx->cluster[cl]) return -1; idx->ents_allocated += AVI_INDEX_CLUSTER_SIZE; } idx->cluster[cl][id].flags = flags; idx->cluster[cl][id].pos = url_ftell(pb) - avi->movi_list; idx->cluster[cl][id].len = size; idx->entry++; } avio_write(pb, tag, 4); avio_wl32(pb, size); avio_write(pb, pkt->data, size); if (size & 1) avio_w8(pb, 0); put_flush_packet(pb); return 0; }
static int gxf_write_umf_payload(AVFormatContext *s) { GXFContext *gxf = s->priv_data; AVIOContext *pb = s->pb; avio_wl32(pb, gxf->umf_length); /* total length of the umf data */ avio_wl32(pb, 3); /* version */ avio_wl32(pb, s->nb_streams+1); avio_wl32(pb, gxf->umf_track_offset); /* umf track section offset */ avio_wl32(pb, gxf->umf_track_size); avio_wl32(pb, s->nb_streams+1); avio_wl32(pb, gxf->umf_media_offset); avio_wl32(pb, gxf->umf_media_size); avio_wl32(pb, gxf->umf_length); /* user data offset */ avio_wl32(pb, 0); /* user data size */ avio_wl32(pb, 0); /* reserved */ avio_wl32(pb, 0); /* reserved */ return 48; }
int64_t ff_start_tag(AVIOContext *pb, const char *tag) { ffio_wfourcc(pb, tag); avio_wl32(pb, 0); return avio_tell(pb); }
static int avi_write_header(AVFormatContext *s) { AVIContext *avi = s->priv_data; AVIOContext *pb = s->pb; int bitrate, n, i, nb_frames, au_byterate, au_ssize, au_scale; AVCodecContext *stream, *video_enc; int64_t list1, list2, strh, strf; AVDictionaryEntry *t = NULL; if (s->nb_streams > AVI_MAX_STREAM_COUNT) { av_log(s, AV_LOG_ERROR, "AVI does not support >%d streams\n", AVI_MAX_STREAM_COUNT); return AVERROR(EINVAL); } for(n=0;n<s->nb_streams;n++) { s->streams[n]->priv_data= av_mallocz(sizeof(AVIStream)); if(!s->streams[n]->priv_data) return AVERROR(ENOMEM); } /* header list */ avi->riff_id = 0; list1 = avi_start_new_riff(s, pb, "AVI ", "hdrl"); /* avi header */ ffio_wfourcc(pb, "avih"); avio_wl32(pb, 14 * 4); bitrate = 0; video_enc = NULL; for(n=0;n<s->nb_streams;n++) { stream = s->streams[n]->codec; bitrate += stream->bit_rate; if (stream->codec_type == AVMEDIA_TYPE_VIDEO) video_enc = stream; } nb_frames = 0; if(video_enc){ avio_wl32(pb, (uint32_t)(INT64_C(1000000) * video_enc->time_base.num / video_enc->time_base.den)); } else { avio_wl32(pb, 0); } avio_wl32(pb, bitrate / 8); /* XXX: not quite exact */ avio_wl32(pb, 0); /* padding */ if (!pb->seekable) avio_wl32(pb, AVIF_TRUSTCKTYPE | AVIF_ISINTERLEAVED); /* flags */ else avio_wl32(pb, AVIF_TRUSTCKTYPE | AVIF_HASINDEX | AVIF_ISINTERLEAVED); /* flags */ avi->frames_hdr_all = avio_tell(pb); /* remember this offset to fill later */ avio_wl32(pb, nb_frames); /* nb frames, filled later */ avio_wl32(pb, 0); /* initial frame */ avio_wl32(pb, s->nb_streams); /* nb streams */ avio_wl32(pb, 1024 * 1024); /* suggested buffer size */ if(video_enc){ avio_wl32(pb, video_enc->width); avio_wl32(pb, video_enc->height); } else { avio_wl32(pb, 0); avio_wl32(pb, 0); } avio_wl32(pb, 0); /* reserved */ avio_wl32(pb, 0); /* reserved */ avio_wl32(pb, 0); /* reserved */ avio_wl32(pb, 0); /* reserved */ /* stream list */ for(i=0;i<n;i++) { AVIStream *avist= s->streams[i]->priv_data; list2 = ff_start_tag(pb, "LIST"); ffio_wfourcc(pb, "strl"); stream = s->streams[i]->codec; /* stream generic header */ strh = ff_start_tag(pb, "strh"); switch(stream->codec_type) { case AVMEDIA_TYPE_SUBTITLE: // XSUB subtitles behave like video tracks, other subtitles // are not (yet) supported. if (stream->codec_id != AV_CODEC_ID_XSUB) { av_log(s, AV_LOG_ERROR, "Subtitle streams other than DivX XSUB are not supported by the AVI muxer.\n"); return AVERROR_PATCHWELCOME; } case AVMEDIA_TYPE_VIDEO: ffio_wfourcc(pb, "vids"); break; case AVMEDIA_TYPE_AUDIO: ffio_wfourcc(pb, "auds"); break; // case AVMEDIA_TYPE_TEXT : ffio_wfourcc(pb, "txts"); break; case AVMEDIA_TYPE_DATA : ffio_wfourcc(pb, "dats"); break; } if(stream->codec_type == AVMEDIA_TYPE_VIDEO || stream->codec_id == AV_CODEC_ID_XSUB) avio_wl32(pb, stream->codec_tag); else avio_wl32(pb, 1); avio_wl32(pb, 0); /* flags */ avio_wl16(pb, 0); /* priority */ avio_wl16(pb, 0); /* language */ avio_wl32(pb, 0); /* initial frame */ ff_parse_specific_params(stream, &au_byterate, &au_ssize, &au_scale); if ( stream->codec_type == AVMEDIA_TYPE_VIDEO && stream->codec_id != AV_CODEC_ID_XSUB && au_byterate > 1000LL*au_scale) { au_byterate = 600; au_scale = 1; } avpriv_set_pts_info(s->streams[i], 64, au_scale, au_byterate); if(stream->codec_id == AV_CODEC_ID_XSUB) au_scale = au_byterate = 0; avio_wl32(pb, au_scale); /* scale */ avio_wl32(pb, au_byterate); /* rate */ avio_wl32(pb, 0); /* start */ avist->frames_hdr_strm = avio_tell(pb); /* remember this offset to fill later */ if (!pb->seekable) avio_wl32(pb, AVI_MAX_RIFF_SIZE); /* FIXME: this may be broken, but who cares */ else avio_wl32(pb, 0); /* length, XXX: filled later */ /* suggested buffer size */ //FIXME set at the end to largest chunk if(stream->codec_type == AVMEDIA_TYPE_VIDEO) avio_wl32(pb, 1024 * 1024); else if(stream->codec_type == AVMEDIA_TYPE_AUDIO) avio_wl32(pb, 12 * 1024); else avio_wl32(pb, 0); avio_wl32(pb, -1); /* quality */ avio_wl32(pb, au_ssize); /* sample size */ avio_wl32(pb, 0); avio_wl16(pb, stream->width); avio_wl16(pb, stream->height); ff_end_tag(pb, strh); if(stream->codec_type != AVMEDIA_TYPE_DATA){ int ret; strf = ff_start_tag(pb, "strf"); switch(stream->codec_type) { case AVMEDIA_TYPE_SUBTITLE: // XSUB subtitles behave like video tracks, other subtitles // are not (yet) supported. if (stream->codec_id != AV_CODEC_ID_XSUB) break; case AVMEDIA_TYPE_VIDEO: ff_put_bmp_header(pb, stream, ff_codec_bmp_tags, 0); break; case AVMEDIA_TYPE_AUDIO: if ((ret = ff_put_wav_header(pb, stream)) < 0) { return ret; } break; default: av_log(s, AV_LOG_ERROR, "Invalid or not supported codec type '%s' found in the input\n", (char *)av_x_if_null(av_get_media_type_string(stream->codec_type), "?")); return AVERROR(EINVAL); } ff_end_tag(pb, strf); if ((t = av_dict_get(s->streams[i]->metadata, "title", NULL, 0))) { ff_riff_write_info_tag(s->pb, "strn", t->value); t = NULL; } } if (pb->seekable) { unsigned char tag[5]; int j; /* Starting to lay out AVI OpenDML master index. * We want to make it JUNK entry for now, since we'd * like to get away without making AVI an OpenDML one * for compatibility reasons. */ avist->indexes.entry = avist->indexes.ents_allocated = 0; avist->indexes.indx_start = ff_start_tag(pb, "JUNK"); avio_wl16(pb, 4); /* wLongsPerEntry */ avio_w8(pb, 0); /* bIndexSubType (0 == frame index) */ avio_w8(pb, 0); /* bIndexType (0 == AVI_INDEX_OF_INDEXES) */ avio_wl32(pb, 0); /* nEntriesInUse (will fill out later on) */ ffio_wfourcc(pb, avi_stream2fourcc(tag, i, stream->codec_type)); /* dwChunkId */ avio_wl64(pb, 0); /* dwReserved[3] avio_wl32(pb, 0); Must be 0. */ for (j=0; j < AVI_MASTER_INDEX_SIZE * 2; j++) avio_wl64(pb, 0); ff_end_tag(pb, avist->indexes.indx_start); } if( stream->codec_type == AVMEDIA_TYPE_VIDEO && s->streams[i]->sample_aspect_ratio.num>0 && s->streams[i]->sample_aspect_ratio.den>0){ int vprp= ff_start_tag(pb, "vprp"); AVRational dar = av_mul_q(s->streams[i]->sample_aspect_ratio, (AVRational){stream->width, stream->height}); int num, den; av_reduce(&num, &den, dar.num, dar.den, 0xFFFF); avio_wl32(pb, 0); //video format = unknown avio_wl32(pb, 0); //video standard= unknown avio_wl32(pb, lrintf(1.0/av_q2d(stream->time_base))); avio_wl32(pb, stream->width ); avio_wl32(pb, stream->height); avio_wl16(pb, den); avio_wl16(pb, num); avio_wl32(pb, stream->width ); avio_wl32(pb, stream->height); avio_wl32(pb, 1); //progressive FIXME avio_wl32(pb, stream->height); avio_wl32(pb, stream->width ); avio_wl32(pb, stream->height); avio_wl32(pb, stream->width ); avio_wl32(pb, 0); avio_wl32(pb, 0); avio_wl32(pb, 0); avio_wl32(pb, 0); ff_end_tag(pb, vprp); } ff_end_tag(pb, list2); } if (pb->seekable) { /* AVI could become an OpenDML one, if it grows beyond 2Gb range */ avi->odml_list = ff_start_tag(pb, "JUNK"); ffio_wfourcc(pb, "odml"); ffio_wfourcc(pb, "dmlh"); avio_wl32(pb, 248); for (i = 0; i < 248; i+= 4) avio_wl32(pb, 0); ff_end_tag(pb, avi->odml_list); } ff_end_tag(pb, list1); ff_riff_write_info(s); /* some padding for easier tag editing */ list2 = ff_start_tag(pb, "JUNK"); for (i = 0; i < 1016; i += 4) avio_wl32(pb, 0); ff_end_tag(pb, list2); avi->movi_list = ff_start_tag(pb, "LIST"); ffio_wfourcc(pb, "movi"); avio_flush(pb); return 0; }
/* returns the size or -1 on error */ int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc, int flags) { int bps, blkalign, bytespersec, frame_size; int hdrsize; int64_t hdrstart = avio_tell(pb); int waveformatextensible; uint8_t temp[256]; uint8_t *riff_extradata = temp; uint8_t *riff_extradata_start = temp; if (!enc->codec_tag || enc->codec_tag > 0xffff) return -1; /* We use the known constant frame size for the codec if known, otherwise * fall back on using AVCodecContext.frame_size, which is not as reliable * for indicating packet duration. */ frame_size = av_get_audio_frame_duration(enc, 0); if (!frame_size) frame_size = enc->frame_size; waveformatextensible = (enc->channels > 2 && enc->channel_layout) || enc->sample_rate > 48000 || enc->codec_id == AV_CODEC_ID_EAC3 || av_get_bits_per_sample(enc->codec_id) > 16; if (waveformatextensible) avio_wl16(pb, 0xfffe); else avio_wl16(pb, enc->codec_tag); avio_wl16(pb, enc->channels); avio_wl32(pb, enc->sample_rate); if (enc->codec_id == AV_CODEC_ID_ATRAC3 || enc->codec_id == AV_CODEC_ID_G723_1 || enc->codec_id == AV_CODEC_ID_MP2 || enc->codec_id == AV_CODEC_ID_MP3 || enc->codec_id == AV_CODEC_ID_GSM_MS) { bps = 0; } else { if (!(bps = av_get_bits_per_sample(enc->codec_id))) { if (enc->bits_per_coded_sample) bps = enc->bits_per_coded_sample; else bps = 16; // default to 16 } } if (bps != enc->bits_per_coded_sample && enc->bits_per_coded_sample) { av_log(enc, AV_LOG_WARNING, "requested bits_per_coded_sample (%d) " "and actually stored (%d) differ\n", enc->bits_per_coded_sample, bps); } if (enc->codec_id == AV_CODEC_ID_MP2 || enc->codec_id == AV_CODEC_ID_MP3) { /* This is wrong, but it seems many demuxers do not work if this * is set correctly. */ blkalign = frame_size; // blkalign = 144 * enc->bit_rate/enc->sample_rate; } else if (enc->codec_id == AV_CODEC_ID_AC3) { blkalign = 3840; /* maximum bytes per frame */ } else if (enc->codec_id == AV_CODEC_ID_AAC) { blkalign = 768 * enc->channels; /* maximum bytes per frame */ } else if (enc->codec_id == AV_CODEC_ID_G723_1) { blkalign = 24; } else if (enc->block_align != 0) { /* specified by the codec */ blkalign = enc->block_align; } else blkalign = bps * enc->channels / av_gcd(8, bps); if (enc->codec_id == AV_CODEC_ID_PCM_U8 || enc->codec_id == AV_CODEC_ID_PCM_S24LE || enc->codec_id == AV_CODEC_ID_PCM_S32LE || enc->codec_id == AV_CODEC_ID_PCM_F32LE || enc->codec_id == AV_CODEC_ID_PCM_F64LE || enc->codec_id == AV_CODEC_ID_PCM_S16LE) { bytespersec = enc->sample_rate * blkalign; } else if (enc->codec_id == AV_CODEC_ID_G723_1) { bytespersec = 800; } else { bytespersec = enc->bit_rate / 8; } avio_wl32(pb, bytespersec); /* bytes per second */ avio_wl16(pb, blkalign); /* block align */ avio_wl16(pb, bps); /* bits per sample */ if (enc->codec_id == AV_CODEC_ID_MP3) { bytestream_put_le16(&riff_extradata, 1); /* wID */ bytestream_put_le32(&riff_extradata, 2); /* fdwFlags */ bytestream_put_le16(&riff_extradata, 1152); /* nBlockSize */ bytestream_put_le16(&riff_extradata, 1); /* nFramesPerBlock */ bytestream_put_le16(&riff_extradata, 1393); /* nCodecDelay */ } else if (enc->codec_id == AV_CODEC_ID_MP2) { /* fwHeadLayer */ bytestream_put_le16(&riff_extradata, 2); /* dwHeadBitrate */ bytestream_put_le32(&riff_extradata, enc->bit_rate); /* fwHeadMode */ bytestream_put_le16(&riff_extradata, enc->channels == 2 ? 1 : 8); /* fwHeadModeExt */ bytestream_put_le16(&riff_extradata, 0); /* wHeadEmphasis */ bytestream_put_le16(&riff_extradata, 1); /* fwHeadFlags */ bytestream_put_le16(&riff_extradata, 16); /* dwPTSLow */ bytestream_put_le32(&riff_extradata, 0); /* dwPTSHigh */ bytestream_put_le32(&riff_extradata, 0); } else if (enc->codec_id == AV_CODEC_ID_G723_1) { bytestream_put_le32(&riff_extradata, 0x9ace0002); /* extradata needed for msacm g723.1 codec */ bytestream_put_le32(&riff_extradata, 0xaea2f732); bytestream_put_le16(&riff_extradata, 0xacde); } else if (enc->codec_id == AV_CODEC_ID_GSM_MS || enc->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) { /* wSamplesPerBlock */ bytestream_put_le16(&riff_extradata, frame_size); } else if (enc->extradata_size) { riff_extradata_start = enc->extradata; riff_extradata = enc->extradata + enc->extradata_size; } /* write WAVEFORMATEXTENSIBLE extensions */ if (waveformatextensible) { int write_channel_mask = enc->strict_std_compliance < FF_COMPLIANCE_NORMAL || enc->channel_layout < 0x40000; /* 22 is WAVEFORMATEXTENSIBLE size */ avio_wl16(pb, riff_extradata - riff_extradata_start + 22); /* ValidBitsPerSample || SamplesPerBlock || Reserved */ avio_wl16(pb, bps); /* dwChannelMask */ avio_wl32(pb, write_channel_mask ? enc->channel_layout : 0); /* GUID + next 3 */ if (enc->codec_id == AV_CODEC_ID_EAC3) { ff_put_guid(pb, get_codec_guid(enc->codec_id, ff_codec_wav_guids)); } else { avio_wl32(pb, enc->codec_tag); avio_wl32(pb, 0x00100000); avio_wl32(pb, 0xAA000080); avio_wl32(pb, 0x719B3800); } } else if ((flags & FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX) || enc->codec_tag != 0x0001 /* PCM */ || riff_extradata - riff_extradata_start) { /* WAVEFORMATEX */ avio_wl16(pb, riff_extradata - riff_extradata_start); /* cbSize */ } /* else PCMWAVEFORMAT */ avio_write(pb, riff_extradata_start, riff_extradata - riff_extradata_start); hdrsize = avio_tell(pb) - hdrstart; if (hdrsize & 1) { hdrsize++; avio_w8(pb, 0); } return hdrsize; }
static int rv10_write_header(AVFormatContext *ctx, int data_size, int index_pos) { RMMuxContext *rm = ctx->priv_data; AVIOContext *s = ctx->pb; StreamInfo *stream; unsigned char *data_offset_ptr, *start_ptr; const char *desc, *mimetype; int nb_packets, packet_total_size, packet_max_size, size, packet_avg_size, i; int bit_rate, v, duration, flags, data_pos; AVDictionaryEntry *tag; start_ptr = s->buf_ptr; ffio_wfourcc(s, ".RMF"); avio_wb32(s,18); /* header size */ avio_wb16(s,0); avio_wb32(s,0); avio_wb32(s,4 + ctx->nb_streams); /* num headers */ ffio_wfourcc(s,"PROP"); avio_wb32(s, 50); avio_wb16(s, 0); packet_max_size = 0; packet_total_size = 0; nb_packets = 0; bit_rate = 0; duration = 0; for(i=0;i<ctx->nb_streams;i++) { StreamInfo *stream = &rm->streams[i]; bit_rate += stream->bit_rate; if (stream->packet_max_size > packet_max_size) packet_max_size = stream->packet_max_size; nb_packets += stream->nb_packets; packet_total_size += stream->packet_total_size; /* select maximum duration */ v = (int) (1000.0 * (float)stream->total_frames / stream->frame_rate); if (v > duration) duration = v; } avio_wb32(s, bit_rate); /* max bit rate */ avio_wb32(s, bit_rate); /* avg bit rate */ avio_wb32(s, packet_max_size); /* max packet size */ if (nb_packets > 0) packet_avg_size = packet_total_size / nb_packets; else packet_avg_size = 0; avio_wb32(s, packet_avg_size); /* avg packet size */ avio_wb32(s, nb_packets); /* num packets */ avio_wb32(s, duration); /* duration */ avio_wb32(s, BUFFER_DURATION); /* preroll */ avio_wb32(s, index_pos); /* index offset */ /* computation of data the data offset */ data_offset_ptr = s->buf_ptr; avio_wb32(s, 0); /* data offset : will be patched after */ avio_wb16(s, ctx->nb_streams); /* num streams */ flags = 1 | 2; /* save allowed & perfect play */ if (!s->seekable) flags |= 4; /* live broadcast */ avio_wb16(s, flags); /* comments */ ffio_wfourcc(s,"CONT"); size = 4 * 2 + 10; for(i=0; i<FF_ARRAY_ELEMS(ff_rm_metadata); i++) { tag = av_dict_get(ctx->metadata, ff_rm_metadata[i], NULL, 0); if(tag) size += strlen(tag->value); } avio_wb32(s,size); avio_wb16(s,0); for(i=0; i<FF_ARRAY_ELEMS(ff_rm_metadata); i++) { tag = av_dict_get(ctx->metadata, ff_rm_metadata[i], NULL, 0); put_str(s, tag ? tag->value : ""); } for(i=0;i<ctx->nb_streams;i++) { int codec_data_size; stream = &rm->streams[i]; if (stream->par->codec_type == AVMEDIA_TYPE_AUDIO) { desc = "The Audio Stream"; mimetype = "audio/x-pn-realaudio"; codec_data_size = 73; } else { desc = "The Video Stream"; mimetype = "video/x-pn-realvideo"; codec_data_size = 34; } ffio_wfourcc(s,"MDPR"); size = 10 + 9 * 4 + strlen(desc) + strlen(mimetype) + codec_data_size; avio_wb32(s, size); avio_wb16(s, 0); avio_wb16(s, i); /* stream number */ avio_wb32(s, stream->bit_rate); /* max bit rate */ avio_wb32(s, stream->bit_rate); /* avg bit rate */ avio_wb32(s, stream->packet_max_size); /* max packet size */ if (stream->nb_packets > 0) packet_avg_size = stream->packet_total_size / stream->nb_packets; else packet_avg_size = 0; avio_wb32(s, packet_avg_size); /* avg packet size */ avio_wb32(s, 0); /* start time */ avio_wb32(s, BUFFER_DURATION); /* preroll */ /* duration */ if (!s->seekable || !stream->total_frames) avio_wb32(s, (int)(3600 * 1000)); else avio_wb32(s, (int)(stream->total_frames * 1000 / stream->frame_rate)); put_str8(s, desc); put_str8(s, mimetype); avio_wb32(s, codec_data_size); if (stream->par->codec_type == AVMEDIA_TYPE_AUDIO) { int coded_frame_size, fscode, sample_rate; int frame_size = av_get_audio_frame_duration2(stream->par, 0); sample_rate = stream->par->sample_rate; coded_frame_size = (stream->par->bit_rate * frame_size) / (8 * sample_rate); /* audio codec info */ avio_write(s, ".ra", 3); avio_w8(s, 0xfd); avio_wb32(s, 0x00040000); /* version */ ffio_wfourcc(s, ".ra4"); avio_wb32(s, 0x01b53530); /* stream length */ avio_wb16(s, 4); /* unknown */ avio_wb32(s, 0x39); /* header size */ switch(sample_rate) { case 48000: case 24000: case 12000: fscode = 1; break; default: case 44100: case 22050: case 11025: fscode = 2; break; case 32000: case 16000: case 8000: fscode = 3; } avio_wb16(s, fscode); /* codec additional info, for AC-3, seems to be a frequency code */ /* special hack to compensate rounding errors... */ if (coded_frame_size == 557) coded_frame_size--; avio_wb32(s, coded_frame_size); /* frame length */ avio_wb32(s, 0x51540); /* unknown */ avio_wb32(s, 0x249f0); /* unknown */ avio_wb32(s, 0x249f0); /* unknown */ avio_wb16(s, 0x01); /* frame length : seems to be very important */ avio_wb16(s, coded_frame_size); avio_wb32(s, 0); /* unknown */ avio_wb16(s, stream->par->sample_rate); /* sample rate */ avio_wb32(s, 0x10); /* unknown */ avio_wb16(s, stream->par->channels); put_str8(s, "Int0"); /* codec name */ if (stream->par->codec_tag) { avio_w8(s, 4); /* tag length */ avio_wl32(s, stream->par->codec_tag); } else { av_log(ctx, AV_LOG_ERROR, "Invalid codec tag\n"); return -1; } avio_wb16(s, 0); /* title length */ avio_wb16(s, 0); /* author length */ avio_wb16(s, 0); /* copyright length */ avio_w8(s, 0); /* end of header */ } else { /* video codec info */ avio_wb32(s,34); /* size */ ffio_wfourcc(s, "VIDO"); if(stream->par->codec_id == AV_CODEC_ID_RV10) ffio_wfourcc(s,"RV10"); else ffio_wfourcc(s,"RV20"); avio_wb16(s, stream->par->width); avio_wb16(s, stream->par->height); avio_wb16(s, (int) stream->frame_rate); /* frames per seconds ? */ avio_wb32(s,0); /* unknown meaning */ avio_wb16(s, (int) stream->frame_rate); /* unknown meaning */ avio_wb32(s,0); /* unknown meaning */ avio_wb16(s, 8); /* unknown meaning */ /* Seems to be the codec version: only use basic H.263. The next versions seems to add a differential DC coding as in MPEG... nothing new under the sun. */ if(stream->par->codec_id == AV_CODEC_ID_RV10) avio_wb32(s,0x10000000); else avio_wb32(s,0x20103001); //avio_wb32(s,0x10003000); } } /* patch data offset field */ data_pos = s->buf_ptr - start_ptr; rm->data_pos = data_pos; data_offset_ptr[0] = data_pos >> 24; data_offset_ptr[1] = data_pos >> 16; data_offset_ptr[2] = data_pos >> 8; data_offset_ptr[3] = data_pos; /* data stream */ ffio_wfourcc(s, "DATA"); avio_wb32(s,data_size + 10 + 8); avio_wb16(s,0); avio_wb32(s, nb_packets); /* number of packets */ avio_wb32(s,0); /* next data header */ 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 = 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; }
static int write_header(AVFormatContext *s) { AVIOContext *pb = s->pb; WtvContext *wctx = s->priv_data; int i, pad, ret; AVStream *st; wctx->last_chunk_pos = -1; wctx->last_timestamp_pos = -1; ff_put_guid(pb, &ff_wtv_guid); ff_put_guid(pb, &sub_wtv_guid); avio_wl32(pb, 0x01); avio_wl32(pb, 0x02); avio_wl32(pb, 1 << WTV_SECTOR_BITS); avio_wl32(pb, 1 << WTV_BIGSECTOR_BITS); //write initial root fields avio_wl32(pb, 0); // root_size, update later write_pad(pb, 4); avio_wl32(pb, 0); // root_sector, update it later. write_pad(pb, 32); avio_wl32(pb, 0); // file ends pointer, update it later. pad = (1 << WTV_SECTOR_BITS) - avio_tell(pb); write_pad(pb, pad); wctx->timeline_start_pos = avio_tell(pb); wctx->serial = 1; wctx->last_chunk_pos = -1; wctx->first_video_flag = 1; for (i = 0; i < s->nb_streams; i++) { st = s->streams[i]; if (st->codec->codec_id == AV_CODEC_ID_MJPEG) continue; ret = write_stream_codec(s, st); if (ret < 0) { av_log(s, AV_LOG_ERROR, "write stream codec failed codec_type(0x%x)\n", st->codec->codec_type); return -1; } if (!i) write_sync(s); } for (i = 0; i < s->nb_streams; i++) { st = s->streams[i]; if (st->codec->codec_id == AV_CODEC_ID_MJPEG) continue; ret = write_stream_data(s, st); if (ret < 0) { av_log(s, AV_LOG_ERROR, "write stream data failed codec_type(0x%x)\n", st->codec->codec_type); return -1; } } if (wctx->nb_index) write_index(s); return 0; }
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 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 aiff_write_header(AVFormatContext *s) { AIFFOutputContext *aiff = s->priv_data; AVIOContext *pb = s->pb; AVCodecParameters *par; uint64_t sample_rate; int i, aifc = 0; aiff->audio_stream_idx = -1; for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; if (aiff->audio_stream_idx < 0 && st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { aiff->audio_stream_idx = i; } else if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO) { av_log(s, AV_LOG_ERROR, "AIFF allows only one audio stream and a picture.\n"); return AVERROR(EINVAL); } } if (aiff->audio_stream_idx < 0) { av_log(s, AV_LOG_ERROR, "No audio stream present.\n"); return AVERROR(EINVAL); } par = s->streams[aiff->audio_stream_idx]->codecpar; /* First verify if format is ok */ if (!par->codec_tag) return -1; if (par->codec_tag != MKTAG('N','O','N','E')) aifc = 1; /* FORM AIFF header */ ffio_wfourcc(pb, "FORM"); aiff->form = avio_tell(pb); avio_wb32(pb, 0); /* file length */ ffio_wfourcc(pb, aifc ? "AIFC" : "AIFF"); if (aifc) { // compressed audio if (!par->block_align) { av_log(s, AV_LOG_ERROR, "block align not set\n"); return -1; } /* Version chunk */ ffio_wfourcc(pb, "FVER"); avio_wb32(pb, 4); avio_wb32(pb, 0xA2805140); } if (par->channels > 2 && par->channel_layout) { ffio_wfourcc(pb, "CHAN"); avio_wb32(pb, 12); ff_mov_write_chan(pb, par->channel_layout); } put_meta(s, "title", MKTAG('N', 'A', 'M', 'E')); put_meta(s, "author", MKTAG('A', 'U', 'T', 'H')); put_meta(s, "copyright", MKTAG('(', 'c', ')', ' ')); put_meta(s, "comment", MKTAG('A', 'N', 'N', 'O')); /* Common chunk */ ffio_wfourcc(pb, "COMM"); avio_wb32(pb, aifc ? 24 : 18); /* size */ avio_wb16(pb, par->channels); /* Number of channels */ aiff->frames = avio_tell(pb); avio_wb32(pb, 0); /* Number of frames */ if (!par->bits_per_coded_sample) par->bits_per_coded_sample = av_get_bits_per_sample(par->codec_id); if (!par->bits_per_coded_sample) { av_log(s, AV_LOG_ERROR, "could not compute bits per sample\n"); return -1; } if (!par->block_align) par->block_align = (par->bits_per_coded_sample * par->channels) >> 3; avio_wb16(pb, par->bits_per_coded_sample); /* Sample size */ sample_rate = av_double2int(par->sample_rate); avio_wb16(pb, (sample_rate >> 52) + (16383 - 1023)); avio_wb64(pb, UINT64_C(1) << 63 | sample_rate << 11); if (aifc) { avio_wl32(pb, par->codec_tag); avio_wb16(pb, 0); } if (par->codec_tag == MKTAG('Q','D','M','2') && par->extradata_size) { ffio_wfourcc(pb, "wave"); avio_wb32(pb, par->extradata_size); avio_write(pb, par->extradata, par->extradata_size); } /* Sound data chunk */ ffio_wfourcc(pb, "SSND"); aiff->ssnd = avio_tell(pb); /* Sound chunk size */ avio_wb32(pb, 0); /* Sound samples data size */ avio_wb32(pb, 0); /* Data offset */ avio_wb32(pb, 0); /* Block-size (block align) */ avpriv_set_pts_info(s->streams[aiff->audio_stream_idx], 64, 1, s->streams[aiff->audio_stream_idx]->codecpar->sample_rate); /* Data is starting here */ avio_flush(pb); return 0; }
static int aiff_write_header(AVFormatContext *s) { AIFFOutputContext *aiff = s->priv_data; AVIOContext *pb = s->pb; AVCodecContext *enc = s->streams[0]->codec; uint64_t sample_rate; int aifc = 0; /* First verify if format is ok */ if (!enc->codec_tag) return -1; if (enc->codec_tag != MKTAG('N','O','N','E')) aifc = 1; /* FORM AIFF header */ ffio_wfourcc(pb, "FORM"); aiff->form = avio_tell(pb); avio_wb32(pb, 0); /* file length */ ffio_wfourcc(pb, aifc ? "AIFC" : "AIFF"); if (aifc) { // compressed audio enc->bits_per_coded_sample = 16; if (!enc->block_align) { av_log(s, AV_LOG_ERROR, "block align not set\n"); return -1; } /* Version chunk */ ffio_wfourcc(pb, "FVER"); avio_wb32(pb, 4); avio_wb32(pb, 0xA2805140); } if (enc->channels > 2 && enc->channel_layout) { ffio_wfourcc(pb, "CHAN"); avio_wb32(pb, 12); ff_mov_write_chan(pb, enc->channel_layout); } /* Common chunk */ ffio_wfourcc(pb, "COMM"); avio_wb32(pb, aifc ? 24 : 18); /* size */ avio_wb16(pb, enc->channels); /* Number of channels */ aiff->frames = avio_tell(pb); avio_wb32(pb, 0); /* Number of frames */ if (!enc->bits_per_coded_sample) enc->bits_per_coded_sample = av_get_bits_per_sample(enc->codec_id); if (!enc->bits_per_coded_sample) { av_log(s, AV_LOG_ERROR, "could not compute bits per sample\n"); return -1; } if (!enc->block_align) enc->block_align = (enc->bits_per_coded_sample * enc->channels) >> 3; avio_wb16(pb, enc->bits_per_coded_sample); /* Sample size */ sample_rate = av_double2int(enc->sample_rate); avio_wb16(pb, (sample_rate >> 52) + (16383 - 1023)); avio_wb64(pb, UINT64_C(1) << 63 | sample_rate << 11); if (aifc) { avio_wl32(pb, enc->codec_tag); avio_wb16(pb, 0); } if (enc->codec_tag == MKTAG('Q','D','M','2') && enc->extradata_size) { ffio_wfourcc(pb, "wave"); avio_wb32(pb, enc->extradata_size); avio_write(pb, enc->extradata, enc->extradata_size); } /* Sound data chunk */ ffio_wfourcc(pb, "SSND"); aiff->ssnd = avio_tell(pb); /* Sound chunk size */ avio_wb32(pb, 0); /* Sound samples data size */ avio_wb32(pb, 0); /* Data offset */ avio_wb32(pb, 0); /* Block-size (block align) */ avpriv_set_pts_info(s->streams[0], 64, 1, s->streams[0]->codec->sample_rate); /* Data is starting here */ avio_flush(pb); return 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; int metadata_count; AVCodecContext *enc; int64_t header_offset, cur_pos, hpos; int bit_rate; int64_t duration; 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 = s->metadata ? s->metadata->count : 0; bit_rate = 0; for(n=0;n<s->nb_streams;n++) { enc = s->streams[n]->codec; av_set_pts_info(s->streams[n], 32, 1, 1000); /* 32 bit pts in ms */ bit_rate += enc->bit_rate; } if (asf->is_streamed) { put_chunk(s, 0x4824, 0, 0xc00); /* start of stream (length will be patched later) */ } 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); 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); /* Nominal data rate in bps */ end_header(pb, hpos); /* unknown headers */ hpos = put_header(pb, &ff_asf_head1_guid); put_guid(pb, &ff_asf_head2_guid); avio_wl32(pb, 6); avio_wl16(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))) { if (!strcmp(tag->key, "cover")) { const char *mime = av_metadata_get_attribute(tag, "mime"); int len; if (!mime) { av_log(s, AV_LOG_ERROR, "error, no mime type set for cover\n"); return 0; } len = 1 + 4 + (strlen(mime)+1)*2 + 2 + tag->len; put_str16(pb, tag->key); avio_wl16(pb, 1); avio_wl16(pb, len); avio_w8(pb, 3); avio_wl32(pb, tag->len); put_str16(pb, mime); avio_wl16(pb, 0); avio_write(pb, tag->value, tag->len); } else { const char *key = NULL; int i; for (i = 0; ff_asf_metadata_conv[i].native; i++) { if (!strcmp(ff_asf_metadata_conv[i].generic, tag->key)) { key = ff_asf_metadata_conv[i].native; break; } } if (!tag) continue; put_str16(pb, key); if (tag->type == METADATA_BYTEARRAY) { avio_wl16(pb, 1); avio_wl16(pb, tag->len); avio_write(pb, tag->value, tag->len); } else { avio_wl16(pb, 0); put_str16(pb, tag->value); } } } end_header(pb, hpos); } /* 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 = 0; 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) { put_guid(pb, &ff_asf_audio_stream); put_guid(pb, &ff_asf_audio_conceal_spread); } else { put_guid(pb, &ff_asf_video_stream); 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); if ((enc->codec_id != CODEC_ID_MP3) && (enc->codec_id != CODEC_ID_MP2) && (enc->codec_id != CODEC_ID_ADPCM_IMA_WAV) && (enc->extradata_size==0)) { wavsize += 2; avio_wl16(pb, 0); } 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 == 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); } end_header(pb, hpos); } /* media comments */ hpos = put_header(pb, &ff_asf_codec_comment_header); put_guid(pb, &ff_asf_codec_comment1_header); avio_wl32(pb, s->nb_streams); for(n=0;n<s->nb_streams;n++) { AVCodec *p; const char *desc; int len; uint8_t *buf; AVIOContext *dyn_buf; enc = s->streams[n]->codec; p = avcodec_find_encoder(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 == CODEC_ID_WMAV2) desc = "Windows Media Audio V8"; else desc = p ? p->name : enc->codec_name; 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); 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 + 50; 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 + 50; } 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; put_guid(pb, &ff_asf_data_header); avio_wl64(pb, data_chunk_size); 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 int ffm_write_header(AVFormatContext *s) { FFMContext *ffm = s->priv_data; AVDictionaryEntry *t; AVStream *st; AVIOContext *pb = s->pb; AVCodecContext *codec; int bit_rate, i, ret; if (t = av_dict_get(s->metadata, "creation_time", NULL, 0)) { ret = av_parse_time(&ffm->start_time, t->value, 0); if (ret < 0) return ret; } ffm->packet_size = FFM_PACKET_SIZE; /* header */ avio_wl32(pb, MKTAG('F', 'F', 'M', '2')); avio_wb32(pb, ffm->packet_size); avio_wb64(pb, 0); /* current write position */ if(avio_open_dyn_buf(&pb) < 0) return AVERROR(ENOMEM); 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); write_header_chunk(s->pb, pb, MKBETAG('M', 'A', 'I', 'N')); /* list of streams */ for(i=0;i<s->nb_streams;i++) { st = s->streams[i]; avpriv_set_pts_info(st, 64, 1, 1000000); if(avio_open_dyn_buf(&pb) < 0) return AVERROR(ENOMEM); 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); if (codec->flags & CODEC_FLAG_GLOBAL_HEADER) { avio_wb32(pb, codec->extradata_size); avio_write(pb, codec->extradata, codec->extradata_size); } write_header_chunk(s->pb, pb, MKBETAG('C', 'O', 'M', 'M')); /* specific info */ switch(codec->codec_type) { case AVMEDIA_TYPE_VIDEO: if (st->recommended_encoder_configuration) { av_log(NULL, AV_LOG_DEBUG, "writing recommended configuration: %s\n", st->recommended_encoder_configuration); if ((ret = ffm_write_recommended_config(s->pb, codec, MKBETAG('S', '2', 'V', 'I'), st->recommended_encoder_configuration)) < 0) return ret; } else if ((ret = ffm_write_header_codec_ctx(s->pb, codec, MKBETAG('S', '2', 'V', 'I'), AV_OPT_FLAG_VIDEO_PARAM)) < 0 || (ret = ffm_write_header_codec_private_ctx(s, codec, AV_OPT_FLAG_VIDEO_PARAM)) < 0) return ret; break; case AVMEDIA_TYPE_AUDIO: if (st->recommended_encoder_configuration) { av_log(NULL, AV_LOG_DEBUG, "writing recommended configuration: %s\n", st->recommended_encoder_configuration); if ((ret = ffm_write_recommended_config(s->pb, codec, MKBETAG('S', '2', 'A', 'U'), st->recommended_encoder_configuration)) < 0) return ret; } else if ((ret = ffm_write_header_codec_ctx(s->pb, codec, MKBETAG('S', '2', 'A', 'U'), AV_OPT_FLAG_AUDIO_PARAM)) < 0 || (ret = ffm_write_header_codec_private_ctx(s, codec, AV_OPT_FLAG_AUDIO_PARAM)) < 0) return ret; break; default: return -1; } } pb = s->pb; avio_wb64(pb, 0); // end of header /* 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; }
static int aiff_write_header(AVFormatContext *s) { AIFFOutputContext *aiff = s->priv_data; AVIOContext *pb = s->pb; AVCodecContext *enc = s->streams[0]->codec; AVExtFloat sample_rate; int aifc = 0; /* First verify if format is ok */ if (!enc->codec_tag) return -1; if (enc->codec_tag != MKTAG('N','O','N','E')) aifc = 1; /* FORM AIFF header */ ffio_wfourcc(pb, "FORM"); aiff->form = avio_tell(pb); avio_wb32(pb, 0); /* file length */ ffio_wfourcc(pb, aifc ? "AIFC" : "AIFF"); if (aifc) { // compressed audio enc->bits_per_coded_sample = 16; if (!enc->block_align) { av_log(s, AV_LOG_ERROR, "block align not set\n"); return -1; } /* Version chunk */ ffio_wfourcc(pb, "FVER"); avio_wb32(pb, 4); avio_wb32(pb, 0xA2805140); } /* Common chunk */ ffio_wfourcc(pb, "COMM"); avio_wb32(pb, aifc ? 24 : 18); /* size */ avio_wb16(pb, enc->channels); /* Number of channels */ aiff->frames = avio_tell(pb); avio_wb32(pb, 0); /* Number of frames */ if (!enc->bits_per_coded_sample) enc->bits_per_coded_sample = av_get_bits_per_sample(enc->codec_id); if (!enc->bits_per_coded_sample) { av_log(s, AV_LOG_ERROR, "could not compute bits per sample\n"); return -1; } if (!enc->block_align) enc->block_align = (enc->bits_per_coded_sample * enc->channels) >> 3; avio_wb16(pb, enc->bits_per_coded_sample); /* Sample size */ sample_rate = av_dbl2ext((double)enc->sample_rate); avio_write(pb, (uint8_t*)&sample_rate, sizeof(sample_rate)); if (aifc) { avio_wl32(pb, enc->codec_tag); avio_wb16(pb, 0); } /* Sound data chunk */ ffio_wfourcc(pb, "SSND"); aiff->ssnd = avio_tell(pb); /* Sound chunk size */ avio_wb32(pb, 0); /* Sound samples data size */ avio_wb32(pb, 0); /* Data offset */ avio_wb32(pb, 0); /* Block-size (block align) */ av_set_pts_info(s->streams[0], 64, 1, s->streams[0]->codec->sample_rate); /* Data is starting here */ 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; assert(ffm->packet_end >= ffm->packet); ffm->frame_offset = 0; ffm->dts = 0; ffm->first_packet = 1; return 0; }
static int swf_write_header(AVFormatContext *s) { SWFContext *swf = s->priv_data; AVIOContext *pb = s->pb; PutBitContext p; uint8_t buf1[256]; int i, width, height, rate, rate_base; int version; swf->sound_samples = 0; swf->swf_frame_number = 0; swf->video_frame_number = 0; for(i=0;i<s->nb_streams;i++) { AVCodecContext *enc = s->streams[i]->codec; if (enc->codec_type == AVMEDIA_TYPE_AUDIO) { if (enc->codec_id == AV_CODEC_ID_MP3) { swf->audio_enc = enc; swf->audio_fifo= av_fifo_alloc(AUDIO_FIFO_SIZE); if (!swf->audio_fifo) return AVERROR(ENOMEM); } else { av_log(s, AV_LOG_ERROR, "SWF muxer only supports MP3\n"); return -1; } } else { if (enc->codec_id == AV_CODEC_ID_VP6F || enc->codec_id == AV_CODEC_ID_FLV1 || enc->codec_id == AV_CODEC_ID_MJPEG) { swf->video_enc = enc; } else { av_log(s, AV_LOG_ERROR, "SWF muxer only supports VP6, FLV1 and MJPEG\n"); return -1; } } } if (!swf->video_enc) { /* currently, cannot work correctly if audio only */ width = 320; height = 200; rate = 10; rate_base= 1; } else { width = swf->video_enc->width; height = swf->video_enc->height; rate = swf->video_enc->time_base.den; rate_base = swf->video_enc->time_base.num; } if (!swf->audio_enc) swf->samples_per_frame = (44100. * rate_base) / rate; else swf->samples_per_frame = (swf->audio_enc->sample_rate * rate_base) / rate; avio_write(pb, "FWS", 3); if (!strcmp("avm2", s->oformat->name)) version = 9; else if (swf->video_enc && swf->video_enc->codec_id == AV_CODEC_ID_VP6F) version = 8; /* version 8 and above support VP6 codec */ else if (swf->video_enc && swf->video_enc->codec_id == AV_CODEC_ID_FLV1) version = 6; /* version 6 and above support FLV1 codec */ else version = 4; /* version 4 for mpeg audio support */ avio_w8(pb, version); avio_wl32(pb, DUMMY_FILE_SIZE); /* dummy size (will be patched if not streamed) */ put_swf_rect(pb, 0, width * 20, 0, height * 20); avio_wl16(pb, (rate * 256) / rate_base); /* frame rate */ swf->duration_pos = avio_tell(pb); avio_wl16(pb, (uint16_t)(DUMMY_DURATION * (int64_t)rate / rate_base)); /* frame count */ /* avm2/swf v9 (also v8?) files require a file attribute tag */ if (version == 9) { put_swf_tag(s, TAG_FILEATTRIBUTES); avio_wl32(pb, 1<<3); /* set ActionScript v3/AVM2 flag */ put_swf_end_tag(s); } /* define a shape with the jpeg inside */ if (swf->video_enc && swf->video_enc->codec_id == AV_CODEC_ID_MJPEG) { put_swf_tag(s, TAG_DEFINESHAPE); avio_wl16(pb, SHAPE_ID); /* ID of shape */ /* bounding rectangle */ put_swf_rect(pb, 0, width, 0, height); /* style info */ avio_w8(pb, 1); /* one fill style */ avio_w8(pb, 0x41); /* clipped bitmap fill */ avio_wl16(pb, BITMAP_ID); /* bitmap ID */ /* position of the bitmap */ put_swf_matrix(pb, (int)(1.0 * (1 << FRAC_BITS)), 0, 0, (int)(1.0 * (1 << FRAC_BITS)), 0, 0); avio_w8(pb, 0); /* no line style */ /* shape drawing */ init_put_bits(&p, buf1, sizeof(buf1)); put_bits(&p, 4, 1); /* one fill bit */ put_bits(&p, 4, 0); /* zero line bit */ put_bits(&p, 1, 0); /* not an edge */ put_bits(&p, 5, FLAG_MOVETO | FLAG_SETFILL0); put_bits(&p, 5, 1); /* nbits */ put_bits(&p, 1, 0); /* X */ put_bits(&p, 1, 0); /* Y */ put_bits(&p, 1, 1); /* set fill style 1 */ /* draw the rectangle ! */ put_swf_line_edge(&p, width, 0); put_swf_line_edge(&p, 0, height); put_swf_line_edge(&p, -width, 0); put_swf_line_edge(&p, 0, -height); /* end of shape */ put_bits(&p, 1, 0); /* not an edge */ put_bits(&p, 5, 0); flush_put_bits(&p); avio_write(pb, buf1, put_bits_ptr(&p) - p.buf); put_swf_end_tag(s); } if (swf->audio_enc && swf->audio_enc->codec_id == AV_CODEC_ID_MP3) { int v = 0; /* start sound */ put_swf_tag(s, TAG_STREAMHEAD2); switch(swf->audio_enc->sample_rate) { case 11025: v |= 1 << 2; break; case 22050: v |= 2 << 2; break; case 44100: v |= 3 << 2; break; default: /* not supported */ av_log(s, AV_LOG_ERROR, "swf does not support that sample rate, choose from (44100, 22050, 11025).\n"); return -1; } v |= 0x02; /* 16 bit playback */ if (swf->audio_enc->channels == 2) v |= 0x01; /* stereo playback */ avio_w8(s->pb, v); v |= 0x20; /* mp3 compressed */ avio_w8(s->pb, v); avio_wl16(s->pb, swf->samples_per_frame); /* avg samples per frame */ avio_wl16(s->pb, 0); put_swf_end_tag(s); } avio_flush(s->pb); return 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)) < 0) 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; }
/* returns the size or -1 on error */ int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc) { int bps, blkalign, bytespersec, frame_size; int hdrsize = 18; int waveformatextensible; uint8_t temp[256]; uint8_t *riff_extradata= temp; uint8_t *riff_extradata_start= temp; if(!enc->codec_tag || enc->codec_tag > 0xffff) return -1; /* We use the known constant frame size for the codec if known, otherwise fallback to using AVCodecContext.frame_size, which is not as reliable for indicating packet duration */ frame_size = av_get_audio_frame_duration(enc, 0); if (!frame_size) frame_size = enc->frame_size; waveformatextensible = (enc->channels > 2 && enc->channel_layout) || enc->sample_rate > 48000 || av_get_bits_per_sample(enc->codec_id) > 16; if (waveformatextensible) { avio_wl16(pb, 0xfffe); } else { avio_wl16(pb, enc->codec_tag); } avio_wl16(pb, enc->channels); avio_wl32(pb, enc->sample_rate); if (enc->codec_id == AV_CODEC_ID_MP2 || enc->codec_id == AV_CODEC_ID_MP3 || enc->codec_id == AV_CODEC_ID_GSM_MS) { bps = 0; } else { if (!(bps = av_get_bits_per_sample(enc->codec_id))) { if (enc->bits_per_coded_sample) bps = enc->bits_per_coded_sample; else bps = 16; // default to 16 } } if(bps != enc->bits_per_coded_sample && enc->bits_per_coded_sample){ av_log(enc, AV_LOG_WARNING, "requested bits_per_coded_sample (%d) and actually stored (%d) differ\n", enc->bits_per_coded_sample, bps); } if (enc->codec_id == AV_CODEC_ID_MP2 || enc->codec_id == AV_CODEC_ID_MP3) { /* this is wrong, but it seems many demuxers do not work if this is set correctly */ blkalign = frame_size; //blkalign = 144 * enc->bit_rate/enc->sample_rate; } else if (enc->codec_id == AV_CODEC_ID_AC3) { blkalign = 3840; //maximum bytes per frame } else if (enc->block_align != 0) { /* specified by the codec */ blkalign = enc->block_align; } else blkalign = bps * enc->channels / av_gcd(8, bps); if (enc->codec_id == AV_CODEC_ID_PCM_U8 || enc->codec_id == AV_CODEC_ID_PCM_S24LE || enc->codec_id == AV_CODEC_ID_PCM_S32LE || enc->codec_id == AV_CODEC_ID_PCM_F32LE || enc->codec_id == AV_CODEC_ID_PCM_F64LE || enc->codec_id == AV_CODEC_ID_PCM_S16LE) { bytespersec = enc->sample_rate * blkalign; } else { bytespersec = enc->bit_rate / 8; } avio_wl32(pb, bytespersec); /* bytes per second */ avio_wl16(pb, blkalign); /* block align */ avio_wl16(pb, bps); /* bits per sample */ if (enc->codec_id == AV_CODEC_ID_MP3) { hdrsize += 12; bytestream_put_le16(&riff_extradata, 1); /* wID */ bytestream_put_le32(&riff_extradata, 2); /* fdwFlags */ bytestream_put_le16(&riff_extradata, 1152); /* nBlockSize */ bytestream_put_le16(&riff_extradata, 1); /* nFramesPerBlock */ bytestream_put_le16(&riff_extradata, 1393); /* nCodecDelay */ } else if (enc->codec_id == AV_CODEC_ID_MP2) { hdrsize += 22; bytestream_put_le16(&riff_extradata, 2); /* fwHeadLayer */ bytestream_put_le32(&riff_extradata, enc->bit_rate); /* dwHeadBitrate */ bytestream_put_le16(&riff_extradata, enc->channels == 2 ? 1 : 8); /* fwHeadMode */ bytestream_put_le16(&riff_extradata, 0); /* fwHeadModeExt */ bytestream_put_le16(&riff_extradata, 1); /* wHeadEmphasis */ bytestream_put_le16(&riff_extradata, 16); /* fwHeadFlags */ bytestream_put_le32(&riff_extradata, 0); /* dwPTSLow */ bytestream_put_le32(&riff_extradata, 0); /* dwPTSHigh */ } else if (enc->codec_id == AV_CODEC_ID_GSM_MS || enc->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) { hdrsize += 2; bytestream_put_le16(&riff_extradata, frame_size); /* wSamplesPerBlock */ } else if(enc->extradata_size){ riff_extradata_start= enc->extradata; riff_extradata= enc->extradata + enc->extradata_size; hdrsize += enc->extradata_size; } if(waveformatextensible) { /* write WAVEFORMATEXTENSIBLE extensions */ hdrsize += 22; avio_wl16(pb, riff_extradata - riff_extradata_start + 22); /* 22 is WAVEFORMATEXTENSIBLE size */ avio_wl16(pb, bps); /* ValidBitsPerSample || SamplesPerBlock || Reserved */ avio_wl32(pb, enc->channel_layout); /* dwChannelMask */ avio_wl32(pb, enc->codec_tag); /* GUID + next 3 */ avio_wl32(pb, 0x00100000); avio_wl32(pb, 0xAA000080); avio_wl32(pb, 0x719B3800); } else { avio_wl16(pb, riff_extradata - riff_extradata_start); /* cbSize */ } avio_write(pb, riff_extradata_start, riff_extradata - riff_extradata_start); if(hdrsize&1){ hdrsize++; avio_w8(pb, 0); } return hdrsize; }
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; switch (enc->codec_id) { case AV_CODEC_ID_AAC: case AV_CODEC_ID_AC3: av_log(s, AV_LOG_ERROR, "muxing codec currently unsupported\n"); return AVERROR_PATCHWELCOME; } switch (enc->codec_id) { case AV_CODEC_ID_PCM_S8: case AV_CODEC_ID_PCM_S16LE: case AV_CODEC_ID_PCM_S16BE: case AV_CODEC_ID_PCM_S24LE: case AV_CODEC_ID_PCM_S24BE: case AV_CODEC_ID_PCM_S32LE: case AV_CODEC_ID_PCM_S32BE: case AV_CODEC_ID_PCM_F32LE: case AV_CODEC_ID_PCM_F32BE: case AV_CODEC_ID_PCM_F64LE: case AV_CODEC_ID_PCM_F64BE: case AV_CODEC_ID_PCM_ALAW: case AV_CODEC_ID_PCM_MULAW: codec_tag = MKTAG('l','p','c','m'); } 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; } 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, samples_per_packet(enc->codec_id, enc->channels)); //< 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 avi_write_packet(AVFormatContext *s, AVPacket *pkt) { AVIContext *avi = s->priv_data; AVIOContext *pb = s->pb; unsigned char tag[5]; unsigned int flags=0; const int stream_index= pkt->stream_index; AVIStream *avist= s->streams[stream_index]->priv_data; AVCodecContext *enc= s->streams[stream_index]->codec; int size= pkt->size; av_dlog(s, "dts:%s packet_count:%d stream_index:%d\n", av_ts2str(pkt->dts), avist->packet_count, stream_index); while(enc->block_align==0 && pkt->dts != AV_NOPTS_VALUE && pkt->dts > avist->packet_count && enc->codec_id != AV_CODEC_ID_XSUB){ AVPacket empty_packet; if(pkt->dts - avist->packet_count > 60000){ av_log(s, AV_LOG_ERROR, "Too large number of skipped frames %"PRId64" > 60000\n", pkt->dts - avist->packet_count); return AVERROR(EINVAL); } av_init_packet(&empty_packet); empty_packet.size= 0; empty_packet.data= NULL; empty_packet.stream_index= stream_index; avi_write_packet(s, &empty_packet); av_dlog(s, "dup dts:%s packet_count:%d\n", av_ts2str(pkt->dts), avist->packet_count); } avist->packet_count++; // Make sure to put an OpenDML chunk when the file size exceeds the limits if (pb->seekable && (avio_tell(pb) - avi->riff_start > AVI_MAX_RIFF_SIZE)) { avi_write_ix(s); ff_end_tag(pb, avi->movi_list); if (avi->riff_id == 1) avi_write_idx1(s); ff_end_tag(pb, avi->riff_start); avi->movi_list = avi_start_new_riff(s, pb, "AVIX", "movi"); } avi_stream2fourcc(tag, stream_index, enc->codec_type); if(pkt->flags&AV_PKT_FLAG_KEY) flags = 0x10; if (enc->codec_type == AVMEDIA_TYPE_AUDIO) { avist->audio_strm_length += size; } if (s->pb->seekable) { AVIIndex* idx = &avist->indexes; int cl = idx->entry / AVI_INDEX_CLUSTER_SIZE; int id = idx->entry % AVI_INDEX_CLUSTER_SIZE; if (idx->ents_allocated <= idx->entry) { idx->cluster = av_realloc_f(idx->cluster, sizeof(void*), cl+1); if (!idx->cluster) return AVERROR(ENOMEM); idx->cluster[cl] = av_malloc(AVI_INDEX_CLUSTER_SIZE*sizeof(AVIIentry)); if (!idx->cluster[cl]) return AVERROR(ENOMEM); idx->ents_allocated += AVI_INDEX_CLUSTER_SIZE; } idx->cluster[cl][id].flags = flags; idx->cluster[cl][id].pos = avio_tell(pb) - avi->movi_list; idx->cluster[cl][id].len = size; idx->entry++; } avio_write(pb, tag, 4); avio_wl32(pb, size); avio_write(pb, pkt->data, size); if (size & 1) avio_w8(pb, 0); return 0; }
static void put_videoinfoheader2(AVIOContext *pb, AVStream *st) { AVRational dar = av_mul_q(st->sample_aspect_ratio, (AVRational){st->codec->width, st->codec->height}); unsigned int num, den; av_reduce(&num, &den, dar.num, dar.den, 0xFFFFFFFF); /* VIDEOINFOHEADER2 */ avio_wl32(pb, 0); avio_wl32(pb, 0); avio_wl32(pb, st->codec->width); avio_wl32(pb, st->codec->height); avio_wl32(pb, 0); avio_wl32(pb, 0); avio_wl32(pb, 0); avio_wl32(pb, 0); avio_wl32(pb, st->codec->bit_rate); avio_wl32(pb, 0); avio_wl64(pb, st->avg_frame_rate.num && st->avg_frame_rate.den ? INT64_C(10000000) / av_q2d(st->avg_frame_rate) : 0); avio_wl32(pb, 0); avio_wl32(pb, 0); avio_wl32(pb, num); avio_wl32(pb, den); avio_wl32(pb, 0); avio_wl32(pb, 0); ff_put_bmp_header(pb, st->codec, ff_codec_bmp_tags, 0, 1); if (st->codec->codec_id == AV_CODEC_ID_MPEG2VIDEO) { int padding = (st->codec->extradata_size & 3) ? 4 - (st->codec->extradata_size & 3) : 0; /* MPEG2VIDEOINFO */ avio_wl32(pb, 0); avio_wl32(pb, st->codec->extradata_size + padding); avio_wl32(pb, -1); avio_wl32(pb, -1); avio_wl32(pb, 0); avio_write(pb, st->codec->extradata, st->codec->extradata_size); ffio_fill(pb, 0, padding); } }