static int idcin_read_header(AVFormatContext *s) { AVIOContext *pb = s->pb; IdcinDemuxContext *idcin = s->priv_data; AVStream *st; unsigned int width, height; unsigned int sample_rate, bytes_per_sample, channels; int ret; /* get the 5 header parameters */ width = avio_rl32(pb); height = avio_rl32(pb); sample_rate = avio_rl32(pb); bytes_per_sample = avio_rl32(pb); channels = avio_rl32(pb); if (s->pb->eof_reached) { av_log(s, AV_LOG_ERROR, "incomplete header\n"); return s->pb->error ? s->pb->error : AVERROR_EOF; } if (av_image_check_size(width, height, 0, s) < 0) return AVERROR_INVALIDDATA; if (sample_rate > 0) { if (sample_rate < 14 || sample_rate > INT_MAX) { av_log(s, AV_LOG_ERROR, "invalid sample rate: %u\n", sample_rate); return AVERROR_INVALIDDATA; } if (bytes_per_sample < 1 || bytes_per_sample > 2) { av_log(s, AV_LOG_ERROR, "invalid bytes per sample: %u\n", bytes_per_sample); return AVERROR_INVALIDDATA; } if (channels < 1 || channels > 2) { av_log(s, AV_LOG_ERROR, "invalid channels: %u\n", channels); return AVERROR_INVALIDDATA; } idcin->audio_present = 1; } else { /* if sample rate is 0, assume no audio */ idcin->audio_present = 0; } st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); avpriv_set_pts_info(st, 33, 1, IDCIN_FPS); st->start_time = 0; idcin->video_stream_index = st->index; st->codec->codec_type = AVMEDIA_TYPE_VIDEO; st->codec->codec_id = AV_CODEC_ID_IDCIN; st->codec->codec_tag = 0; /* no fourcc */ st->codec->width = width; st->codec->height = height; /* load up the Huffman tables into extradata */ st->codec->extradata_size = HUFFMAN_TABLE_SIZE; st->codec->extradata = av_malloc(HUFFMAN_TABLE_SIZE); ret = avio_read(pb, st->codec->extradata, HUFFMAN_TABLE_SIZE); if (ret < 0) { return ret; } else if (ret != HUFFMAN_TABLE_SIZE) { av_log(s, AV_LOG_ERROR, "incomplete header\n"); return AVERROR(EIO); } if (idcin->audio_present) { idcin->audio_present = 1; st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); avpriv_set_pts_info(st, 63, 1, sample_rate); st->start_time = 0; idcin->audio_stream_index = st->index; st->codec->codec_type = AVMEDIA_TYPE_AUDIO; st->codec->codec_tag = 1; st->codec->channels = channels; st->codec->channel_layout = channels > 1 ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO; st->codec->sample_rate = sample_rate; st->codec->bits_per_coded_sample = bytes_per_sample * 8; st->codec->bit_rate = sample_rate * bytes_per_sample * 8 * channels; st->codec->block_align = idcin->block_align = bytes_per_sample * channels; if (bytes_per_sample == 1) st->codec->codec_id = AV_CODEC_ID_PCM_U8; else st->codec->codec_id = AV_CODEC_ID_PCM_S16LE; if (sample_rate % 14 != 0) { idcin->audio_chunk_size1 = (sample_rate / 14) * bytes_per_sample * channels; idcin->audio_chunk_size2 = (sample_rate / 14 + 1) * bytes_per_sample * channels; } else { idcin->audio_chunk_size1 = idcin->audio_chunk_size2 = (sample_rate / 14) * bytes_per_sample * channels; } idcin->current_audio_chunk = 0; } idcin->next_chunk_is_video = 1; idcin->first_pkt_pos = avio_tell(s->pb); return 0; }
static int swf_write_video(AVFormatContext *s, AVCodecContext *enc, const uint8_t *buf, int size) { SWFContext *swf = s->priv_data; AVIOContext *pb = s->pb; /* Flash Player limit */ if (swf->swf_frame_number == 16000) av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n"); if (enc->codec_id == CODEC_ID_VP6F || enc->codec_id == CODEC_ID_FLV1) { if (swf->video_frame_number == 0) { /* create a new video object */ put_swf_tag(s, TAG_VIDEOSTREAM); avio_wl16(pb, VIDEO_ID); swf->vframes_pos = avio_tell(pb); avio_wl16(pb, 15000); /* hard flash player limit */ avio_wl16(pb, enc->width); avio_wl16(pb, enc->height); avio_w8(pb, 0); avio_w8(pb,ff_codec_get_tag(swf_codec_tags,enc->codec_id)); put_swf_end_tag(s); /* place the video object for the first time */ put_swf_tag(s, TAG_PLACEOBJECT2); avio_w8(pb, 0x36); avio_wl16(pb, 1); avio_wl16(pb, VIDEO_ID); put_swf_matrix(pb, 1 << FRAC_BITS, 0, 0, 1 << FRAC_BITS, 0, 0); avio_wl16(pb, swf->video_frame_number); avio_write(pb, "video", 5); avio_w8(pb, 0x00); put_swf_end_tag(s); } else { /* mark the character for update */ put_swf_tag(s, TAG_PLACEOBJECT2); avio_w8(pb, 0x11); avio_wl16(pb, 1); avio_wl16(pb, swf->video_frame_number); put_swf_end_tag(s); } /* set video frame data */ put_swf_tag(s, TAG_VIDEOFRAME | TAG_LONG); avio_wl16(pb, VIDEO_ID); avio_wl16(pb, swf->video_frame_number++); avio_write(pb, buf, size); put_swf_end_tag(s); } else if (enc->codec_id == CODEC_ID_MJPEG) { if (swf->swf_frame_number > 0) { /* remove the shape */ put_swf_tag(s, TAG_REMOVEOBJECT); avio_wl16(pb, SHAPE_ID); /* shape ID */ avio_wl16(pb, 1); /* depth */ put_swf_end_tag(s); /* free the bitmap */ put_swf_tag(s, TAG_FREECHARACTER); avio_wl16(pb, BITMAP_ID); put_swf_end_tag(s); } put_swf_tag(s, TAG_JPEG2 | TAG_LONG); avio_wl16(pb, BITMAP_ID); /* ID of the image */ /* a dummy jpeg header seems to be required */ avio_wb32(pb, 0xffd8ffd9); /* write the jpeg image */ avio_write(pb, buf, size); put_swf_end_tag(s); /* draw the shape */ put_swf_tag(s, TAG_PLACEOBJECT); avio_wl16(pb, SHAPE_ID); /* shape ID */ avio_wl16(pb, 1); /* depth */ put_swf_matrix(pb, 20 << FRAC_BITS, 0, 0, 20 << FRAC_BITS, 0, 0); put_swf_end_tag(s); } swf->swf_frame_number++; /* streaming sound always should be placed just before showframe tags */ if (swf->audio_enc && av_fifo_size(swf->audio_fifo)) { int frame_size = av_fifo_size(swf->audio_fifo); put_swf_tag(s, TAG_STREAMBLOCK | TAG_LONG); avio_wl16(pb, swf->sound_samples); avio_wl16(pb, 0); // seek samples av_fifo_generic_read(swf->audio_fifo, pb, frame_size, &avio_write); put_swf_end_tag(s); /* update FIFO */ swf->sound_samples = 0; } /* output the frame */ put_swf_tag(s, TAG_SHOWFRAME); put_swf_end_tag(s); avio_flush(s->pb); return 0; }
static int caf_write_header(AVFormatContext *s) { AVIOContext *pb = s->pb; AVCodecContext *enc = s->streams[0]->codec; CAFContext *caf = s->priv_data; unsigned int codec_tag = ff_codec_get_tag(ff_codec_caf_tags, enc->codec_id); 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); } 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 tta_read_header(AVFormatContext *s, AVFormatParameters *ap) { TTAContext *c = s->priv_data; AVStream *st; int i, channels, bps, samplerate, datalen, framelen; uint64_t framepos, start_offset; if (!av_dict_get(s->metadata, "", NULL, AV_DICT_IGNORE_SUFFIX)) ff_id3v1_read(s); start_offset = avio_tell(s->pb); if (avio_rl32(s->pb) != AV_RL32("TTA1")) return -1; // not tta file avio_skip(s->pb, 2); // FIXME: flags channels = avio_rl16(s->pb); bps = avio_rl16(s->pb); samplerate = avio_rl32(s->pb); if(samplerate <= 0 || samplerate > 1000000){ av_log(s, AV_LOG_ERROR, "nonsense samplerate\n"); return -1; } datalen = avio_rl32(s->pb); if(datalen < 0){ av_log(s, AV_LOG_ERROR, "nonsense datalen\n"); return -1; } avio_skip(s->pb, 4); // header crc framelen = samplerate*256/245; c->totalframes = datalen / framelen + ((datalen % framelen) ? 1 : 0); c->currentframe = 0; if(c->totalframes >= UINT_MAX/sizeof(uint32_t)){ av_log(s, AV_LOG_ERROR, "totalframes too large\n"); return -1; } st = av_new_stream(s, 0); if (!st) return AVERROR(ENOMEM); av_set_pts_info(st, 64, 1, samplerate); st->start_time = 0; st->duration = datalen; framepos = avio_tell(s->pb) + 4*c->totalframes + 4; for (i = 0; i < c->totalframes; i++) { uint32_t size = avio_rl32(s->pb); av_add_index_entry(st, framepos, i*framelen, size, 0, AVINDEX_KEYFRAME); framepos += size; } avio_skip(s->pb, 4); // seektable crc st->codec->codec_type = AVMEDIA_TYPE_AUDIO; st->codec->codec_id = CODEC_ID_TTA; st->codec->channels = channels; st->codec->sample_rate = samplerate; st->codec->bits_per_coded_sample = bps; st->codec->extradata_size = avio_tell(s->pb) - start_offset; if(st->codec->extradata_size+FF_INPUT_BUFFER_PADDING_SIZE <= (unsigned)st->codec->extradata_size){ //this check is redundant as avio_read should fail av_log(s, AV_LOG_ERROR, "extradata_size too large\n"); return -1; } st->codec->extradata = av_mallocz(st->codec->extradata_size+FF_INPUT_BUFFER_PADDING_SIZE); avio_seek(s->pb, start_offset, SEEK_SET); avio_read(s->pb, st->codec->extradata, st->codec->extradata_size); return 0; }
static int rsd_read_header(AVFormatContext *s) { AVIOContext *pb = s->pb; int i, version, start = 0x800; AVCodecContext *codec; AVStream *st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); avio_skip(pb, 3); // "RSD" version = avio_r8(pb) - '0'; codec = st->codec; codec->codec_type = AVMEDIA_TYPE_AUDIO; codec->codec_tag = avio_rl32(pb); codec->codec_id = ff_codec_get_id(rsd_tags, codec->codec_tag); if (!codec->codec_id) { char tag_buf[5]; av_get_codec_tag_string(tag_buf, sizeof(tag_buf), codec->codec_tag); for (i=0; i < FF_ARRAY_ELEMS(rsd_unsupported_tags); i++) { if (codec->codec_tag == rsd_unsupported_tags[i]) { avpriv_request_sample(s, "Codec tag: %s", tag_buf); return AVERROR_PATCHWELCOME; } } av_log(s, AV_LOG_ERROR, "Unknown codec tag: %s\n", tag_buf); return AVERROR_INVALIDDATA; } codec->channels = avio_rl32(pb); if (!codec->channels) return AVERROR_INVALIDDATA; avio_skip(pb, 4); // Bit depth codec->sample_rate = avio_rl32(pb); if (!codec->sample_rate) return AVERROR_INVALIDDATA; avio_skip(pb, 4); // Unknown switch (codec->codec_id) { case AV_CODEC_ID_ADPCM_IMA_RAD: codec->block_align = 20 * codec->channels; if (pb->seekable) st->duration = av_get_audio_frame_duration(codec, avio_size(pb) - start); break; case AV_CODEC_ID_ADPCM_THP: /* RSD3GADP is mono, so only alloc enough memory to store the coeff table for a single channel. */ if (ff_alloc_extradata(codec, 32)) return AVERROR(ENOMEM); start = avio_rl32(pb); if (avio_read(s->pb, codec->extradata, 32) != 32) return AVERROR_INVALIDDATA; for (i = 0; i < 16; i++) AV_WB16(codec->extradata + i * 2, AV_RL16(codec->extradata + i * 2)); if (pb->seekable) st->duration = (avio_size(pb) - start) / 8 * 14; break; case AV_CODEC_ID_PCM_S16LE: case AV_CODEC_ID_PCM_S16BE: if (version != 4) start = avio_rl32(pb); if (pb->seekable) st->duration = (avio_size(pb) - start) / 2 / codec->channels; break; } avio_skip(pb, start - avio_tell(pb)); avpriv_set_pts_info(st, 64, 1, codec->sample_rate); return 0; }
static int gif_read_packet(AVFormatContext *s, AVPacket *pkt) { GIFDemuxContext *gdc = s->priv_data; AVIOContext *pb = s->pb; int packed_fields, block_label, ct_size, keyframe, frame_parsed = 0, ret; int64_t frame_start = avio_tell(pb), frame_end; unsigned char buf[6]; if ((ret = avio_read(pb, buf, 6)) == 6) { keyframe = memcmp(buf, gif87a_sig, 6) == 0 || memcmp(buf, gif89a_sig, 6) == 0; } else if (ret < 0) { return ret; } else { keyframe = 0; } if (keyframe) { parse_keyframe: /* skip 2 bytes of width and 2 of height */ if ((ret = avio_skip(pb, 4)) < 0) return ret; packed_fields = avio_r8(pb); /* skip 1 byte of Background Color Index and 1 byte of Pixel Aspect Ratio */ if ((ret = avio_skip(pb, 2)) < 0) return ret; /* global color table presence */ if (packed_fields & 0x80) { ct_size = 3 * (1 << ((packed_fields & 0x07) + 1)); if ((ret = avio_skip(pb, ct_size)) < 0) return ret; } } else { avio_seek(pb, -ret, SEEK_CUR); ret = AVERROR_EOF; } while (GIF_TRAILER != (block_label = avio_r8(pb)) && !url_feof(pb)) { if (block_label == GIF_EXTENSION_INTRODUCER) { if ((ret = gif_read_ext (s)) < 0 ) goto resync; } else if (block_label == GIF_IMAGE_SEPARATOR) { /* skip to last byte of Image Descriptor header */ if ((ret = avio_skip(pb, 8)) < 0) return ret; packed_fields = avio_r8(pb); /* local color table presence */ if (packed_fields & 0x80) { ct_size = 3 * (1 << ((packed_fields & 0x07) + 1)); if ((ret = avio_skip(pb, ct_size)) < 0) return ret; } /* read LZW Minimum Code Size */ if (avio_r8(pb) < 1) { av_log(s, AV_LOG_ERROR, "lzw minimum code size must be >= 1\n"); goto resync; } if ((ret = gif_skip_subblocks(pb)) < 0) goto resync; frame_end = avio_tell(pb); if (avio_seek(pb, frame_start, SEEK_SET) != frame_start) return AVERROR(EIO); ret = av_get_packet(pb, pkt, frame_end - frame_start); if (ret < 0) return ret; if (keyframe) pkt->flags |= AV_PKT_FLAG_KEY; pkt->stream_index = 0; pkt->duration = gdc->delay; /* Graphic Control Extension's scope is single frame. * Remove its influence. */ gdc->delay = gdc->default_delay; frame_parsed = 1; break; } else { av_log(s, AV_LOG_ERROR, "invalid block label\n"); resync: if (!keyframe) avio_seek(pb, frame_start, SEEK_SET); if ((ret = resync(pb)) < 0) return ret; frame_start = avio_tell(pb) - 6; keyframe = 1; goto parse_keyframe; } } if ((ret >= 0 && !frame_parsed) || ret == AVERROR_EOF) { /* This might happen when there is no image block * between extension blocks and GIF_TRAILER or EOF */ if (!gdc->ignore_loop && (block_label == GIF_TRAILER || url_feof(pb)) && (gdc->total_iter < 0 || ++gdc->iter_count < gdc->total_iter)) return avio_seek(pb, 0, SEEK_SET); return AVERROR_EOF; } else return ret; }
static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) { AVIOContext *pb = s->pb; AVCodecContext *enc = s->streams[pkt->stream_index]->codec; FLVContext *flv = s->priv_data; FLVStreamContext *sc = s->streams[pkt->stream_index]->priv_data; unsigned ts; int size = pkt->size; uint8_t *data = NULL; int flags = -1, flags_size, ret; if (enc->codec_id == AV_CODEC_ID_VP6F || enc->codec_id == AV_CODEC_ID_VP6A || enc->codec_id == AV_CODEC_ID_VP6 || enc->codec_id == AV_CODEC_ID_AAC) flags_size = 2; else if (enc->codec_id == AV_CODEC_ID_H264 || enc->codec_id == AV_CODEC_ID_MPEG4) flags_size = 5; else flags_size = 1; switch (enc->codec_type) { case AVMEDIA_TYPE_VIDEO: avio_w8(pb, FLV_TAG_TYPE_VIDEO); flags = enc->codec_tag; if (flags == 0) { av_log(s, AV_LOG_ERROR, "Video codec '%s' is not compatible with FLV\n", avcodec_get_name(enc->codec_id)); return AVERROR(EINVAL); } flags |= pkt->flags & AV_PKT_FLAG_KEY ? FLV_FRAME_KEY : FLV_FRAME_INTER; break; case AVMEDIA_TYPE_AUDIO: flags = get_audio_flags(s, enc); av_assert0(size); avio_w8(pb, FLV_TAG_TYPE_AUDIO); break; case AVMEDIA_TYPE_DATA: avio_w8(pb, FLV_TAG_TYPE_META); break; default: return AVERROR(EINVAL); } if (enc->codec_id == AV_CODEC_ID_H264 || enc->codec_id == AV_CODEC_ID_MPEG4) { /* check if extradata looks like mp4 formated */ if (enc->extradata_size > 0 && *(uint8_t*)enc->extradata != 1) if ((ret = ff_avc_parse_nal_units_buf(pkt->data, &data, &size)) < 0) return ret; } else if (enc->codec_id == AV_CODEC_ID_AAC && pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) { if (!s->streams[pkt->stream_index]->nb_frames) { av_log(s, AV_LOG_ERROR, "Malformed AAC bitstream detected: " "use audio bitstream filter 'aac_adtstoasc' to fix it " "('-bsf:a aac_adtstoasc' option with ffmpeg)\n"); return AVERROR_INVALIDDATA; } av_log(s, AV_LOG_WARNING, "aac bitstream error\n"); } if (flv->delay == AV_NOPTS_VALUE) flv->delay = -pkt->dts; if (pkt->dts < -flv->delay) { av_log(s, AV_LOG_WARNING, "Packets are not in the proper order with respect to DTS\n"); return AVERROR(EINVAL); } ts = pkt->dts + flv->delay; // add delay to force positive dts /* check Speex packet duration */ if (enc->codec_id == AV_CODEC_ID_SPEEX && ts - sc->last_ts > 160) av_log(s, AV_LOG_WARNING, "Warning: Speex stream has more than " "8 frames per packet. Adobe Flash " "Player cannot handle this!\n"); if (sc->last_ts < ts) sc->last_ts = ts; avio_wb24(pb, size + flags_size); avio_wb24(pb, ts); avio_w8(pb, (ts >> 24) & 0x7F); // timestamps are 32 bits _signed_ avio_wb24(pb, flv->reserved); if (enc->codec_type == AVMEDIA_TYPE_DATA) { int data_size; int metadata_size_pos = avio_tell(pb); avio_w8(pb, AMF_DATA_TYPE_STRING); put_amf_string(pb, "onTextData"); avio_w8(pb, AMF_DATA_TYPE_MIXEDARRAY); avio_wb32(pb, 2); put_amf_string(pb, "type"); avio_w8(pb, AMF_DATA_TYPE_STRING); put_amf_string(pb, "Text"); put_amf_string(pb, "text"); avio_w8(pb, AMF_DATA_TYPE_STRING); put_amf_string(pb, pkt->data); put_amf_string(pb, ""); avio_w8(pb, AMF_END_OF_OBJECT); /* write total size of tag */ data_size = avio_tell(pb) - metadata_size_pos; avio_seek(pb, metadata_size_pos - 10, SEEK_SET); avio_wb24(pb, data_size); avio_seek(pb, data_size + 10 - 3, SEEK_CUR); avio_wb32(pb, data_size + 11); } else { av_assert1(flags>=0); avio_w8(pb,flags); if (enc->codec_id == AV_CODEC_ID_VP6) avio_w8(pb,0); if (enc->codec_id == AV_CODEC_ID_VP6F || enc->codec_id == AV_CODEC_ID_VP6A) { if (enc->extradata_size) avio_w8(pb, enc->extradata[0]); else avio_w8(pb, ((FFALIGN(enc->width, 16) - enc->width) << 4) | (FFALIGN(enc->height, 16) - enc->height)); } else if (enc->codec_id == AV_CODEC_ID_AAC) avio_w8(pb, 1); // AAC raw else if (enc->codec_id == AV_CODEC_ID_H264 || enc->codec_id == AV_CODEC_ID_MPEG4) { avio_w8(pb, 1); // AVC NALU avio_wb24(pb, pkt->pts - pkt->dts); } avio_write(pb, data ? data : pkt->data, size); avio_wb32(pb, size + flags_size + 11); // previous tag size flv->duration = FFMAX(flv->duration, pkt->pts + flv->delay + pkt->duration); } av_free(data); return pb->error; }
static int xwma_read_header(AVFormatContext *s) { int64_t size; int ret = 0; uint32_t dpds_table_size = 0; uint32_t *dpds_table = 0; unsigned int tag; AVIOContext *pb = s->pb; AVStream *st; XWMAContext *xwma = s->priv_data; int i; /* The following code is mostly copied from wav.c, with some * minor alterations. */ /* check RIFF header */ tag = avio_rl32(pb); if (tag != MKTAG('R', 'I', 'F', 'F')) return -1; avio_rl32(pb); /* file size */ tag = avio_rl32(pb); if (tag != MKTAG('X', 'W', 'M', 'A')) return -1; /* parse fmt header */ tag = avio_rl32(pb); if (tag != MKTAG('f', 'm', 't', ' ')) return -1; size = avio_rl32(pb); st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); ret = ff_get_wav_header(pb, st->codec, size); if (ret < 0) return ret; st->need_parsing = AVSTREAM_PARSE_NONE; /* All xWMA files I have seen contained WMAv2 data. If there are files * using WMA Pro or some other codec, then we need to figure out the right * extradata for that. Thus, ask the user for feedback, but try to go on * anyway. */ if (st->codec->codec_id != AV_CODEC_ID_WMAV2) { avpriv_request_sample(s, "Unexpected codec (tag 0x04%x; id %d)", st->codec->codec_tag, st->codec->codec_id); } else { /* In all xWMA files I have seen, there is no extradata. But the WMA * codecs require extradata, so we provide our own fake extradata. * * First, check that there really was no extradata in the header. If * there was, then try to use it, after asking the user to provide a * sample of this unusual file. */ if (st->codec->extradata_size != 0) { /* Surprise, surprise: We *did* get some extradata. No idea * if it will work, but just go on and try it, after asking * the user for a sample. */ avpriv_request_sample(s, "Unexpected extradata (%d bytes)", st->codec->extradata_size); } else { st->codec->extradata_size = 6; st->codec->extradata = av_mallocz(6 + FF_INPUT_BUFFER_PADDING_SIZE); if (!st->codec->extradata) return AVERROR(ENOMEM); /* setup extradata with our experimentally obtained value */ st->codec->extradata[4] = 31; } } if (!st->codec->channels) { av_log(s, AV_LOG_WARNING, "Invalid channel count: %d\n", st->codec->channels); return AVERROR_INVALIDDATA; } if (!st->codec->bits_per_coded_sample) { av_log(s, AV_LOG_WARNING, "Invalid bits_per_coded_sample: %d\n", st->codec->bits_per_coded_sample); return AVERROR_INVALIDDATA; } /* set the sample rate */ avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); /* parse the remaining RIFF chunks */ for (;;) { if (pb->eof_reached) { ret = AVERROR_INVALIDDATA; goto fail; } /* read next chunk tag */ tag = avio_rl32(pb); size = avio_rl32(pb); if (tag == MKTAG('d', 'a', 't', 'a')) { /* We assume that the data chunk comes last. */ break; } else if (tag == MKTAG('d','p','d','s')) { /* Quoting the MSDN xWMA docs on the dpds chunk: "Contains the * decoded packet cumulative data size array, each element is the * number of bytes accumulated after the corresponding xWMA packet * is decoded in order." * * Each packet has size equal to st->codec->block_align, which in * all cases I saw so far was always 2230. Thus, we can use the * dpds data to compute a seeking index. */ /* Error out if there is more than one dpds chunk. */ if (dpds_table) { av_log(s, AV_LOG_ERROR, "two dpds chunks present\n"); ret = AVERROR_INVALIDDATA; goto fail; } /* Compute the number of entries in the dpds chunk. */ if (size & 3) { /* Size should be divisible by four */ av_log(s, AV_LOG_WARNING, "dpds chunk size %"PRId64" not divisible by 4\n", size); } dpds_table_size = size / 4; if (dpds_table_size == 0 || dpds_table_size >= INT_MAX / 4) { av_log(s, AV_LOG_ERROR, "dpds chunk size %"PRId64" invalid\n", size); return -1; } /* Allocate some temporary storage to keep the dpds data around. * for processing later on. */ dpds_table = av_malloc(dpds_table_size * sizeof(uint32_t)); if (!dpds_table) { return AVERROR(ENOMEM); } for (i = 0; i < dpds_table_size; ++i) { dpds_table[i] = avio_rl32(pb); size -= 4; } } avio_skip(pb, size); } /* Determine overall data length */ if (size < 0) { ret = AVERROR_INVALIDDATA; goto fail; } if (!size) { xwma->data_end = INT64_MAX; } else xwma->data_end = avio_tell(pb) + size; if (dpds_table && dpds_table_size) { int64_t cur_pos; const uint32_t bytes_per_sample = (st->codec->channels * st->codec->bits_per_coded_sample) >> 3; /* Estimate the duration from the total number of output bytes. */ const uint64_t total_decoded_bytes = dpds_table[dpds_table_size - 1]; if (!bytes_per_sample) { av_log(s, AV_LOG_ERROR, "Invalid bits_per_coded_sample %d for %d channels\n", st->codec->bits_per_coded_sample, st->codec->channels); ret = AVERROR_INVALIDDATA; goto fail; } st->duration = total_decoded_bytes / bytes_per_sample; /* Use the dpds data to build a seek table. We can only do this after * we know the offset to the data chunk, as we need that to determine * the actual offset to each input block. * Note: If we allowed ourselves to assume that the data chunk always * follows immediately after the dpds block, we could of course guess * the data block's start offset already while reading the dpds chunk. * I decided against that, just in case other chunks ever are * discovered. */ cur_pos = avio_tell(pb); for (i = 0; i < dpds_table_size; ++i) { /* From the number of output bytes that would accumulate in the * output buffer after decoding the first (i+1) packets, we compute * an offset / timestamp pair. */ av_add_index_entry(st, cur_pos + (i+1) * st->codec->block_align, /* pos */ dpds_table[i] / bytes_per_sample, /* timestamp */ st->codec->block_align, /* size */ 0, /* duration */ AVINDEX_KEYFRAME); } } else if (st->codec->bit_rate) {
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 -1; } 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 != 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 == 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); avio_wl32(pb, au_scale); /* scale */ avio_wl32(pb, au_byterate); /* rate */ avpriv_set_pts_info(s->streams[i], 64, au_scale, au_byterate); 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){ 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 != 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 (ff_put_wav_header(pb, stream) < 0) { return -1; } break; default: return -1; } ff_end_tag(pb, strf); if ((t = av_dict_get(s->streams[i]->metadata, "title", NULL, 0))) { avi_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); list2 = ff_start_tag(pb, "LIST"); ffio_wfourcc(pb, "INFO"); ff_metadata_conv(&s->metadata, ff_riff_info_conv, NULL); for (i = 0; *ff_riff_tags[i]; i++) { if ((t = av_dict_get(s->metadata, ff_riff_tags[i], NULL, AV_DICT_MATCH_CASE))) avi_write_info_tag(s->pb, t->key, t->value); } ff_end_tag(pb, list2); /* 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; }
/* first is true if we read the frame header */ static int ffm_read_data(AVFormatContext *s, uint8_t *buf, int size, int header) { FFMContext *ffm = s->priv_data; AVIOContext *pb = s->pb; int len, fill_size, size1, frame_offset, id; size1 = size; while (size > 0) { redo: len = ffm->packet_end - ffm->packet_ptr; if (len < 0) return -1; if (len > size) len = size; if (len == 0) { if (avio_tell(pb) == ffm->file_size) avio_seek(pb, ffm->packet_size, SEEK_SET); retry_read: if (pb->buffer_size != ffm->packet_size) { int64_t tell = avio_tell(pb); ffio_set_buf_size(pb, ffm->packet_size); avio_seek(pb, tell, SEEK_SET); } id = avio_rb16(pb); /* PACKET_ID */ if (id != PACKET_ID) if (ffm_resync(s, id) < 0) return -1; fill_size = avio_rb16(pb); ffm->dts = avio_rb64(pb); frame_offset = avio_rb16(pb); avio_read(pb, ffm->packet, ffm->packet_size - FFM_HEADER_SIZE); ffm->packet_end = ffm->packet + (ffm->packet_size - FFM_HEADER_SIZE - fill_size); if (ffm->packet_end < ffm->packet || frame_offset < 0) return -1; /* if first packet or resynchronization packet, we must handle it specifically */ if (ffm->first_packet || (frame_offset & 0x8000)) { if (!frame_offset) { /* This packet has no frame headers in it */ if (avio_tell(pb) >= ffm->packet_size * 3LL) { avio_seek(pb, -ffm->packet_size * 2LL, SEEK_CUR); goto retry_read; } /* This is bad, we cannot find a valid frame header */ return 0; } ffm->first_packet = 0; if ((frame_offset & 0x7fff) < FFM_HEADER_SIZE) return -1; ffm->packet_ptr = ffm->packet + (frame_offset & 0x7fff) - FFM_HEADER_SIZE; if (!header) break; } else { ffm->packet_ptr = ffm->packet; } goto redo; } memcpy(buf, ffm->packet_ptr, len); buf += len; ffm->packet_ptr += len; size -= len; header = 0; } return size1 - size; }
static int mpc_read_header(AVFormatContext *s) { MPCContext *c = s->priv_data; AVStream *st; if(avio_rl24(s->pb) != MKTAG('M', 'P', '+', 0)){ av_log(s, AV_LOG_ERROR, "Not a Musepack file\n"); return AVERROR_INVALIDDATA; } c->ver = avio_r8(s->pb); if(c->ver != 0x07 && c->ver != 0x17){ av_log(s, AV_LOG_ERROR, "Can demux Musepack SV7, got version %02X\n", c->ver); return AVERROR_INVALIDDATA; } c->fcount = avio_rl32(s->pb); if((int64_t)c->fcount * sizeof(MPCFrame) >= UINT_MAX){ av_log(s, AV_LOG_ERROR, "Too many frames, seeking is not possible\n"); return AVERROR_INVALIDDATA; } if(c->fcount){ c->frames = av_malloc(c->fcount * sizeof(MPCFrame)); if(!c->frames){ av_log(s, AV_LOG_ERROR, "Cannot allocate seektable\n"); return AVERROR(ENOMEM); } }else{ av_log(s, AV_LOG_WARNING, "Container reports no frames\n"); } c->curframe = 0; c->lastframe = -1; c->curbits = 8; c->frames_noted = 0; st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); st->codec->codec_type = AVMEDIA_TYPE_AUDIO; st->codec->codec_id = AV_CODEC_ID_MUSEPACK7; st->codec->channels = 2; st->codec->bits_per_coded_sample = 16; st->codec->extradata_size = 16; st->codec->extradata = av_mallocz(st->codec->extradata_size+FF_INPUT_BUFFER_PADDING_SIZE); avio_read(s->pb, st->codec->extradata, 16); st->codec->sample_rate = mpc_rate[st->codec->extradata[2] & 3]; avpriv_set_pts_info(st, 32, MPC_FRAMESIZE, st->codec->sample_rate); /* scan for seekpoints */ st->start_time = 0; st->duration = c->fcount; /* try to read APE tags */ if (s->pb->seekable) { int64_t pos = avio_tell(s->pb); ff_ape_parse_tag(s); if (!av_dict_get(s->metadata, "", NULL, AV_DICT_IGNORE_SUFFIX)) ff_id3v1_read(s); avio_seek(s->pb, pos, SEEK_SET); } return 0; }
static int ffm_read_header(AVFormatContext *s) { FFMContext *ffm = s->priv_data; AVStream *st; AVIOContext *pb = s->pb; AVCodecContext *codec; int i, nb_streams; uint32_t tag; /* header */ tag = avio_rl32(pb); if (tag == MKTAG('F', 'F', 'M', '2')) return ffm2_read_header(s); if (tag != MKTAG('F', 'F', 'M', '1')) goto fail; ffm->packet_size = avio_rb32(pb); if (ffm->packet_size != FFM_PACKET_SIZE) goto fail; ffm->write_index = avio_rb64(pb); /* get also filesize */ if (pb->seekable) { ffm->file_size = avio_size(pb); if (ffm->write_index && 0) adjust_write_index(s); } else { ffm->file_size = (UINT64_C(1) << 63) - 1; } nb_streams = avio_rb32(pb); avio_rb32(pb); /* total bitrate */ /* read each stream */ for(i=0;i<nb_streams;i++) { char rc_eq_buf[128]; st = avformat_new_stream(s, NULL); if (!st) goto fail; avpriv_set_pts_info(st, 64, 1, 1000000); codec = st->codec; /* generic info */ codec->codec_id = avio_rb32(pb); codec->codec_type = avio_r8(pb); /* codec_type */ codec->bit_rate = avio_rb32(pb); codec->flags = avio_rb32(pb); codec->flags2 = avio_rb32(pb); codec->debug = avio_rb32(pb); /* specific info */ switch(codec->codec_type) { case AVMEDIA_TYPE_VIDEO: codec->time_base.num = avio_rb32(pb); codec->time_base.den = avio_rb32(pb); codec->width = avio_rb16(pb); codec->height = avio_rb16(pb); codec->gop_size = avio_rb16(pb); codec->pix_fmt = avio_rb32(pb); codec->qmin = avio_r8(pb); codec->qmax = avio_r8(pb); codec->max_qdiff = avio_r8(pb); codec->qcompress = avio_rb16(pb) / 10000.0; codec->qblur = avio_rb16(pb) / 10000.0; codec->bit_rate_tolerance = avio_rb32(pb); avio_get_str(pb, INT_MAX, rc_eq_buf, sizeof(rc_eq_buf)); codec->rc_eq = av_strdup(rc_eq_buf); codec->rc_max_rate = avio_rb32(pb); codec->rc_min_rate = avio_rb32(pb); codec->rc_buffer_size = avio_rb32(pb); codec->i_quant_factor = av_int2double(avio_rb64(pb)); codec->b_quant_factor = av_int2double(avio_rb64(pb)); codec->i_quant_offset = av_int2double(avio_rb64(pb)); codec->b_quant_offset = av_int2double(avio_rb64(pb)); codec->dct_algo = avio_rb32(pb); codec->strict_std_compliance = avio_rb32(pb); codec->max_b_frames = avio_rb32(pb); codec->mpeg_quant = avio_rb32(pb); codec->intra_dc_precision = avio_rb32(pb); codec->me_method = avio_rb32(pb); codec->mb_decision = avio_rb32(pb); codec->nsse_weight = avio_rb32(pb); codec->frame_skip_cmp = avio_rb32(pb); codec->rc_buffer_aggressivity = av_int2double(avio_rb64(pb)); codec->codec_tag = avio_rb32(pb); codec->thread_count = avio_r8(pb); codec->coder_type = avio_rb32(pb); codec->me_cmp = avio_rb32(pb); codec->me_subpel_quality = avio_rb32(pb); codec->me_range = avio_rb32(pb); codec->keyint_min = avio_rb32(pb); codec->scenechange_threshold = avio_rb32(pb); codec->b_frame_strategy = avio_rb32(pb); codec->qcompress = av_int2double(avio_rb64(pb)); codec->qblur = av_int2double(avio_rb64(pb)); codec->max_qdiff = avio_rb32(pb); codec->refs = avio_rb32(pb); break; case AVMEDIA_TYPE_AUDIO: codec->sample_rate = avio_rb32(pb); codec->channels = avio_rl16(pb); codec->frame_size = avio_rl16(pb); break; default: goto fail; } if (codec->flags & CODEC_FLAG_GLOBAL_HEADER) { if (ff_get_extradata(codec, pb, avio_rb32(pb)) < 0) return AVERROR(ENOMEM); } } /* get until end of block reached */ while ((avio_tell(pb) % ffm->packet_size) != 0) avio_r8(pb); /* init packet demux */ ffm->packet_ptr = ffm->packet; ffm->packet_end = ffm->packet; ffm->frame_offset = 0; ffm->dts = 0; ffm->read_state = READ_HEADER; ffm->first_packet = 1; return 0; fail: ffm_close(s); return -1; }
static int ffm2_read_header(AVFormatContext *s) { FFMContext *ffm = s->priv_data; AVStream *st; AVIOContext *pb = s->pb; AVCodecContext *codec; int ret; int f_main = 0, f_cprv, f_stvi, f_stau; AVCodec *enc; char *buffer; ffm->packet_size = avio_rb32(pb); if (ffm->packet_size != FFM_PACKET_SIZE) { av_log(s, AV_LOG_ERROR, "Invalid packet size %d, expected size was %d\n", ffm->packet_size, FFM_PACKET_SIZE); ret = AVERROR_INVALIDDATA; goto fail; } ffm->write_index = avio_rb64(pb); /* get also filesize */ if (pb->seekable) { ffm->file_size = avio_size(pb); if (ffm->write_index && 0) adjust_write_index(s); } else { ffm->file_size = (UINT64_C(1) << 63) - 1; } while(!avio_feof(pb)) { unsigned id = avio_rb32(pb); unsigned size = avio_rb32(pb); int64_t next = avio_tell(pb) + size; char rc_eq_buf[128]; if(!id) break; switch(id) { case MKBETAG('M', 'A', 'I', 'N'): if (f_main++) { ret = AVERROR(EINVAL); goto fail; } avio_rb32(pb); /* nb_streams */ avio_rb32(pb); /* total bitrate */ break; case MKBETAG('C', 'O', 'M', 'M'): f_cprv = f_stvi = f_stau = 0; st = avformat_new_stream(s, NULL); if (!st) { ret = AVERROR(ENOMEM); goto fail; } avpriv_set_pts_info(st, 64, 1, 1000000); codec = st->codec; /* generic info */ codec->codec_id = avio_rb32(pb); codec->codec_type = avio_r8(pb); codec->bit_rate = avio_rb32(pb); codec->flags = avio_rb32(pb); codec->flags2 = avio_rb32(pb); codec->debug = avio_rb32(pb); if (codec->flags & CODEC_FLAG_GLOBAL_HEADER) { if (ff_get_extradata(codec, pb, avio_rb32(pb)) < 0) return AVERROR(ENOMEM); } break; case MKBETAG('S', 'T', 'V', 'I'): if (f_stvi++) { ret = AVERROR(EINVAL); goto fail; } codec->time_base.num = avio_rb32(pb); codec->time_base.den = avio_rb32(pb); codec->width = avio_rb16(pb); codec->height = avio_rb16(pb); codec->gop_size = avio_rb16(pb); codec->pix_fmt = avio_rb32(pb); codec->qmin = avio_r8(pb); codec->qmax = avio_r8(pb); codec->max_qdiff = avio_r8(pb); codec->qcompress = avio_rb16(pb) / 10000.0; codec->qblur = avio_rb16(pb) / 10000.0; codec->bit_rate_tolerance = avio_rb32(pb); avio_get_str(pb, INT_MAX, rc_eq_buf, sizeof(rc_eq_buf)); codec->rc_eq = av_strdup(rc_eq_buf); codec->rc_max_rate = avio_rb32(pb); codec->rc_min_rate = avio_rb32(pb); codec->rc_buffer_size = avio_rb32(pb); codec->i_quant_factor = av_int2double(avio_rb64(pb)); codec->b_quant_factor = av_int2double(avio_rb64(pb)); codec->i_quant_offset = av_int2double(avio_rb64(pb)); codec->b_quant_offset = av_int2double(avio_rb64(pb)); codec->dct_algo = avio_rb32(pb); codec->strict_std_compliance = avio_rb32(pb); codec->max_b_frames = avio_rb32(pb); codec->mpeg_quant = avio_rb32(pb); codec->intra_dc_precision = avio_rb32(pb); codec->me_method = avio_rb32(pb); codec->mb_decision = avio_rb32(pb); codec->nsse_weight = avio_rb32(pb); codec->frame_skip_cmp = avio_rb32(pb); codec->rc_buffer_aggressivity = av_int2double(avio_rb64(pb)); codec->codec_tag = avio_rb32(pb); codec->thread_count = avio_r8(pb); codec->coder_type = avio_rb32(pb); codec->me_cmp = avio_rb32(pb); codec->me_subpel_quality = avio_rb32(pb); codec->me_range = avio_rb32(pb); codec->keyint_min = avio_rb32(pb); codec->scenechange_threshold = avio_rb32(pb); codec->b_frame_strategy = avio_rb32(pb); codec->qcompress = av_int2double(avio_rb64(pb)); codec->qblur = av_int2double(avio_rb64(pb)); codec->max_qdiff = avio_rb32(pb); codec->refs = avio_rb32(pb); break; case MKBETAG('S', 'T', 'A', 'U'): if (f_stau++) { ret = AVERROR(EINVAL); goto fail; } codec->sample_rate = avio_rb32(pb); codec->channels = avio_rl16(pb); codec->frame_size = avio_rl16(pb); break; case MKBETAG('C', 'P', 'R', 'V'): if (f_cprv++) { ret = AVERROR(EINVAL); goto fail; } enc = avcodec_find_encoder(codec->codec_id); if (enc && enc->priv_data_size && enc->priv_class) { st->recommended_encoder_configuration = av_malloc(size + 1); if (!st->recommended_encoder_configuration) { ret = AVERROR(ENOMEM); goto fail; } avio_get_str(pb, size, st->recommended_encoder_configuration, size + 1); } break; case MKBETAG('S', '2', 'V', 'I'): if (f_stvi++) { ret = AVERROR(EINVAL); goto fail; } buffer = av_malloc(size); if (!buffer) { ret = AVERROR(ENOMEM); goto fail; } avio_get_str(pb, INT_MAX, buffer, size); av_set_options_string(codec, buffer, "=", ","); av_freep(&buffer); break; case MKBETAG('S', '2', 'A', 'U'): if (f_stau++) { ret = AVERROR(EINVAL); goto fail; } buffer = av_malloc(size); if (!buffer) { ret = AVERROR(ENOMEM); goto fail; } avio_get_str(pb, INT_MAX, buffer, size); av_set_options_string(codec, buffer, "=", ","); av_freep(&buffer); break; } avio_seek(pb, next, SEEK_SET); } /* get until end of block reached */ while ((avio_tell(pb) % ffm->packet_size) != 0) avio_r8(pb); /* init packet demux */ ffm->packet_ptr = ffm->packet; ffm->packet_end = ffm->packet; ffm->frame_offset = 0; ffm->dts = 0; ffm->read_state = READ_HEADER; ffm->first_packet = 1; return 0; fail: ffm_close(s); return ret; }
/* 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 = (ASFContext *)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; 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 = s->metadata ? s->metadata->count : 0; 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 (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); /* Nominal 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_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))) { put_str16(pb, tag->key); 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) { 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); 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); ff_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; 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; }
int64_t ff_text_pos(FFTextReader *r) { return avio_tell(r->pb) - r->buf_len + r->buf_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 (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(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 = 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); avio_flush(pb); return 0; }
static int fourxm_read_packet(AVFormatContext *s, AVPacket *pkt) { FourxmDemuxContext *fourxm = s->priv_data; AVIOContext *pb = s->pb; unsigned int fourcc_tag; unsigned int size; int ret = 0; unsigned int track_number; int packet_read = 0; unsigned char header[8]; int audio_frame_count; while (!packet_read) { if ((ret = avio_read(s->pb, header, 8)) < 0) return ret; fourcc_tag = AV_RL32(&header[0]); size = AV_RL32(&header[4]); if (url_feof(pb)) return AVERROR(EIO); switch (fourcc_tag) { case LIST_TAG: /* this is a good time to bump the video pts */ fourxm->video_pts ++; /* skip the LIST-* tag and move on to the next fourcc */ avio_rl32(pb); break; case ifrm_TAG: case pfrm_TAG: case cfrm_TAG: case ifr2_TAG: case pfr2_TAG: case cfr2_TAG: /* allocate 8 more bytes than 'size' to account for fourcc * and size */ if (size + 8 < size || av_new_packet(pkt, size + 8)) return AVERROR(EIO); pkt->stream_index = fourxm->video_stream_index; pkt->pts = fourxm->video_pts; pkt->pos = avio_tell(s->pb); memcpy(pkt->data, header, 8); ret = avio_read(s->pb, &pkt->data[8], size); if (ret < 0){ av_free_packet(pkt); }else packet_read = 1; break; case snd__TAG: track_number = avio_rl32(pb); avio_skip(pb, 4); size-=8; if (track_number < fourxm->track_count && fourxm->tracks[track_number].channels>0) { ret= av_get_packet(s->pb, pkt, size); if(ret<0) return AVERROR(EIO); pkt->stream_index = fourxm->tracks[track_number].stream_index; pkt->pts = fourxm->tracks[track_number].audio_pts; packet_read = 1; /* pts accounting */ audio_frame_count = size; if (fourxm->tracks[track_number].adpcm) audio_frame_count -= 2 * (fourxm->tracks[track_number].channels); audio_frame_count /= fourxm->tracks[track_number].channels; if (fourxm->tracks[track_number].adpcm){ audio_frame_count *= 2; }else audio_frame_count /= (fourxm->tracks[track_number].bits / 8); fourxm->tracks[track_number].audio_pts += audio_frame_count; } else { avio_skip(pb, size); } break; default: avio_skip(pb, size); break; } } return ret; }
static int str_read_packet(AVFormatContext *s, AVPacket *ret_pkt) { AVIOContext *pb = s->pb; StrDemuxContext *str = s->priv_data; unsigned char sector[RAW_CD_SECTOR_SIZE]; int channel; AVPacket *pkt; AVStream *st; while (1) { if (avio_read(pb, sector, RAW_CD_SECTOR_SIZE) != RAW_CD_SECTOR_SIZE) return AVERROR(EIO); channel = sector[0x11]; if (channel >= 32) return AVERROR_INVALIDDATA; switch (sector[0x12] & CDXA_TYPE_MASK) { case CDXA_TYPE_DATA: case CDXA_TYPE_VIDEO: { int current_sector = AV_RL16(§or[0x1C]); int sector_count = AV_RL16(§or[0x1E]); int frame_size = AV_RL32(§or[0x24]); if(!( frame_size>=0 && current_sector < sector_count && sector_count*VIDEO_DATA_CHUNK_SIZE >=frame_size)){ av_log(s, AV_LOG_ERROR, "Invalid parameters %d %d %d\n", current_sector, sector_count, frame_size); break; } if(str->channels[channel].video_stream_index < 0){ /* allocate a new AVStream */ st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); avpriv_set_pts_info(st, 64, 1, 15); str->channels[channel].video_stream_index = st->index; st->codec->codec_type = AVMEDIA_TYPE_VIDEO; st->codec->codec_id = AV_CODEC_ID_MDEC; st->codec->codec_tag = 0; /* no fourcc */ st->codec->width = AV_RL16(§or[0x28]); st->codec->height = AV_RL16(§or[0x2A]); } /* if this is the first sector of the frame, allocate a pkt */ pkt = &str->channels[channel].tmp_pkt; if(pkt->size != sector_count*VIDEO_DATA_CHUNK_SIZE){ if(pkt->data) av_log(s, AV_LOG_ERROR, "missmatching sector_count\n"); av_free_packet(pkt); if (av_new_packet(pkt, sector_count*VIDEO_DATA_CHUNK_SIZE)) return AVERROR(EIO); pkt->pos= avio_tell(pb) - RAW_CD_SECTOR_SIZE; pkt->stream_index = str->channels[channel].video_stream_index; } memcpy(pkt->data + current_sector*VIDEO_DATA_CHUNK_SIZE, sector + VIDEO_DATA_HEADER_SIZE, VIDEO_DATA_CHUNK_SIZE); if (current_sector == sector_count-1) { pkt->size= frame_size; *ret_pkt = *pkt; pkt->data= NULL; pkt->size= -1; pkt->buf = NULL; #if FF_API_DESTRUCT_PACKET //FF_DISABLE_DEPRECATION_WARNINGS pkt->destruct = NULL; //FF_ENABLE_DEPRECATION_WARNINGS #endif return 0; } } break; case CDXA_TYPE_AUDIO: if(str->channels[channel].audio_stream_index < 0){ int fmt = sector[0x13]; /* allocate a new AVStream */ st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); str->channels[channel].audio_stream_index = st->index; st->codec->codec_type = AVMEDIA_TYPE_AUDIO; st->codec->codec_id = AV_CODEC_ID_ADPCM_XA; st->codec->codec_tag = 0; /* no fourcc */ if (fmt & 1) { st->codec->channels = 2; st->codec->channel_layout = AV_CH_LAYOUT_STEREO; } else { st->codec->channels = 1; st->codec->channel_layout = AV_CH_LAYOUT_MONO; } st->codec->sample_rate = (fmt&4)?18900:37800; // st->codec->bit_rate = 0; //FIXME; st->codec->block_align = 128; avpriv_set_pts_info(st, 64, 18 * 224 / st->codec->channels, st->codec->sample_rate); st->start_time = 0; } pkt = ret_pkt; if (av_new_packet(pkt, 2304)) return AVERROR(EIO); memcpy(pkt->data,sector+24,2304); pkt->stream_index = str->channels[channel].audio_stream_index; pkt->duration = 1; return 0; default: av_log(s, AV_LOG_WARNING, "Unknown sector type %02X\n", sector[0x12]); /* drop the sector and move on */ break; } if (pb->eof_reached) return AVERROR(EIO); } }
static int flv_write_header(AVFormatContext *s) { AVIOContext *pb = s->pb; FLVContext *flv = s->priv_data; AVCodecContext *audio_enc = NULL, *video_enc = NULL, *data_enc = NULL; int i, metadata_count = 0; double framerate = 0.0; int64_t metadata_size_pos, data_size, metadata_count_pos; AVDictionaryEntry *tag = NULL; for (i = 0; i < s->nb_streams; i++) { AVCodecContext *enc = s->streams[i]->codec; FLVStreamContext *sc; switch (enc->codec_type) { case AVMEDIA_TYPE_VIDEO: if (s->streams[i]->avg_frame_rate.den && s->streams[i]->avg_frame_rate.num) { framerate = av_q2d(s->streams[i]->avg_frame_rate); } else { framerate = 1 / av_q2d(s->streams[i]->codec->time_base); } if (video_enc) { av_log(s, AV_LOG_ERROR, "at most one video stream is supported in flv\n"); return AVERROR(EINVAL); } video_enc = enc; if (enc->codec_tag == 0) { av_log(s, AV_LOG_ERROR, "Video codec '%s' for stream %d is not compatible with FLV\n", avcodec_get_name(enc->codec_id), i); return AVERROR(EINVAL); } break; case AVMEDIA_TYPE_AUDIO: if (audio_enc) { av_log(s, AV_LOG_ERROR, "at most one audio stream is supported in flv\n"); return AVERROR(EINVAL); } audio_enc = enc; if (get_audio_flags(s, enc) < 0) return AVERROR_INVALIDDATA; break; case AVMEDIA_TYPE_DATA: if (enc->codec_id != AV_CODEC_ID_TEXT) { av_log(s, AV_LOG_ERROR, "Data codec '%s' for stream %d is not compatible with FLV\n", avcodec_get_name(enc->codec_id), i); return AVERROR_INVALIDDATA; } data_enc = enc; break; default: av_log(s, AV_LOG_ERROR, "Codec type '%s' for stream %d is not compatible with FLV\n", av_get_media_type_string(enc->codec_type), i); return AVERROR(EINVAL); } avpriv_set_pts_info(s->streams[i], 32, 1, 1000); /* 32 bit pts in ms */ sc = av_mallocz(sizeof(FLVStreamContext)); if (!sc) return AVERROR(ENOMEM); s->streams[i]->priv_data = sc; sc->last_ts = -1; } flv->delay = AV_NOPTS_VALUE; avio_write(pb, "FLV", 3); avio_w8(pb, 1); avio_w8(pb, FLV_HEADER_FLAG_HASAUDIO * !!audio_enc + FLV_HEADER_FLAG_HASVIDEO * !!video_enc); avio_wb32(pb, 9); avio_wb32(pb, 0); for (i = 0; i < s->nb_streams; i++) if (s->streams[i]->codec->codec_tag == 5) { avio_w8(pb, 8); // message type avio_wb24(pb, 0); // include flags avio_wb24(pb, 0); // time stamp avio_wb32(pb, 0); // reserved avio_wb32(pb, 11); // size flv->reserved = 5; } /* write meta_tag */ avio_w8(pb, 18); // tag type META metadata_size_pos = avio_tell(pb); avio_wb24(pb, 0); // size of data part (sum of all parts below) avio_wb24(pb, 0); // timestamp avio_wb32(pb, 0); // reserved /* now data of data_size size */ /* first event name as a string */ avio_w8(pb, AMF_DATA_TYPE_STRING); put_amf_string(pb, "onMetaData"); // 12 bytes /* mixed array (hash) with size and string/type/data tuples */ avio_w8(pb, AMF_DATA_TYPE_MIXEDARRAY); metadata_count_pos = avio_tell(pb); metadata_count = 5 * !!video_enc + 5 * !!audio_enc + 1 * !!data_enc + 2; // +2 for duration and file size avio_wb32(pb, metadata_count); put_amf_string(pb, "duration"); flv->duration_offset= avio_tell(pb); // fill in the guessed duration, it'll be corrected later if incorrect put_amf_double(pb, s->duration / AV_TIME_BASE); if (video_enc) { put_amf_string(pb, "width"); put_amf_double(pb, video_enc->width); put_amf_string(pb, "height"); put_amf_double(pb, video_enc->height); put_amf_string(pb, "videodatarate"); put_amf_double(pb, video_enc->bit_rate / 1024.0); put_amf_string(pb, "framerate"); put_amf_double(pb, framerate); put_amf_string(pb, "videocodecid"); put_amf_double(pb, video_enc->codec_tag); } if (audio_enc) { put_amf_string(pb, "audiodatarate"); put_amf_double(pb, audio_enc->bit_rate / 1024.0); put_amf_string(pb, "audiosamplerate"); put_amf_double(pb, audio_enc->sample_rate); put_amf_string(pb, "audiosamplesize"); put_amf_double(pb, audio_enc->codec_id == AV_CODEC_ID_PCM_U8 ? 8 : 16); put_amf_string(pb, "stereo"); put_amf_bool(pb, audio_enc->channels == 2); put_amf_string(pb, "audiocodecid"); put_amf_double(pb, audio_enc->codec_tag); } if (data_enc) { put_amf_string(pb, "datastream"); put_amf_double(pb, 0.0); } while ((tag = av_dict_get(s->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) { if( !strcmp(tag->key, "width") ||!strcmp(tag->key, "height") ||!strcmp(tag->key, "videodatarate") ||!strcmp(tag->key, "framerate") ||!strcmp(tag->key, "videocodecid") ||!strcmp(tag->key, "audiodatarate") ||!strcmp(tag->key, "audiosamplerate") ||!strcmp(tag->key, "audiosamplesize") ||!strcmp(tag->key, "stereo") ||!strcmp(tag->key, "audiocodecid") ||!strcmp(tag->key, "duration") ||!strcmp(tag->key, "onMetaData") ){ av_log(s, AV_LOG_DEBUG, "Ignoring metadata for %s\n", tag->key); continue; } put_amf_string(pb, tag->key); avio_w8(pb, AMF_DATA_TYPE_STRING); put_amf_string(pb, tag->value); metadata_count++; } put_amf_string(pb, "filesize"); flv->filesize_offset = avio_tell(pb); put_amf_double(pb, 0); // delayed write put_amf_string(pb, ""); avio_w8(pb, AMF_END_OF_OBJECT); /* write total size of tag */ data_size = avio_tell(pb) - metadata_size_pos - 10; avio_seek(pb, metadata_count_pos, SEEK_SET); avio_wb32(pb, metadata_count); avio_seek(pb, metadata_size_pos, SEEK_SET); avio_wb24(pb, data_size); avio_skip(pb, data_size + 10 - 3); avio_wb32(pb, data_size + 11); for (i = 0; i < s->nb_streams; i++) { AVCodecContext *enc = s->streams[i]->codec; if (enc->codec_id == AV_CODEC_ID_AAC || enc->codec_id == AV_CODEC_ID_H264 || enc->codec_id == AV_CODEC_ID_MPEG4) { int64_t pos; avio_w8(pb, enc->codec_type == AVMEDIA_TYPE_VIDEO ? FLV_TAG_TYPE_VIDEO : FLV_TAG_TYPE_AUDIO); avio_wb24(pb, 0); // size patched later avio_wb24(pb, 0); // ts avio_w8(pb, 0); // ts ext avio_wb24(pb, 0); // streamid pos = avio_tell(pb); if (enc->codec_id == AV_CODEC_ID_AAC) { avio_w8(pb, get_audio_flags(s, enc)); avio_w8(pb, 0); // AAC sequence header avio_write(pb, enc->extradata, enc->extradata_size); } else { avio_w8(pb, enc->codec_tag | FLV_FRAME_KEY); // flags avio_w8(pb, 0); // AVC sequence header avio_wb24(pb, 0); // composition time ff_isom_write_avcc(pb, enc->extradata, enc->extradata_size); } data_size = avio_tell(pb) - pos; avio_seek(pb, -data_size - 10, SEEK_CUR); avio_wb24(pb, data_size); avio_skip(pb, data_size + 10 - 3); avio_wb32(pb, data_size + 11); // previous tag size } } return 0; }
static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) { AVIOContext *pb = s->pb; AVCodecContext *enc = s->streams[pkt->stream_index]->codec; FLVContext *flv = s->priv_data; FLVStreamContext *sc = s->streams[pkt->stream_index]->priv_data; unsigned ts; int size = pkt->size; uint8_t *data = NULL; int flags = 0, flags_size; if (enc->codec_id == AV_CODEC_ID_VP6 || enc->codec_id == AV_CODEC_ID_VP6F || enc->codec_id == AV_CODEC_ID_AAC) flags_size = 2; else if (enc->codec_id == AV_CODEC_ID_H264) flags_size = 5; else flags_size = 1; switch (enc->codec_type) { case AVMEDIA_TYPE_VIDEO: avio_w8(pb, FLV_TAG_TYPE_VIDEO); flags = enc->codec_tag; if (flags == 0) { av_log(s, AV_LOG_ERROR, "video codec %X not compatible with flv\n", enc->codec_id); return -1; } flags |= pkt->flags & AV_PKT_FLAG_KEY ? FLV_FRAME_KEY : FLV_FRAME_INTER; break; case AVMEDIA_TYPE_AUDIO: flags = get_audio_flags(s, enc); assert(size); avio_w8(pb, FLV_TAG_TYPE_AUDIO); break; case AVMEDIA_TYPE_DATA: avio_w8(pb, FLV_TAG_TYPE_META); break; default: return AVERROR(EINVAL); } if (enc->codec_id == AV_CODEC_ID_H264) /* check if extradata looks like MP4 */ if (enc->extradata_size > 0 && *(uint8_t*)enc->extradata != 1) if (ff_avc_parse_nal_units_buf(pkt->data, &data, &size) < 0) return -1; if (flv->delay == AV_NOPTS_VALUE) flv->delay = -pkt->dts; if (pkt->dts < -flv->delay) { av_log(s, AV_LOG_WARNING, "Packets are not in the proper order with respect to DTS\n"); return AVERROR(EINVAL); } ts = pkt->dts + flv->delay; // add delay to force positive dts /* check Speex packet duration */ if (enc->codec_id == AV_CODEC_ID_SPEEX && ts - sc->last_ts > 160) av_log(s, AV_LOG_WARNING, "Warning: Speex stream has more than " "8 frames per packet. Adobe Flash " "Player cannot handle this!\n"); if (sc->last_ts < ts) sc->last_ts = ts; avio_wb24(pb, size + flags_size); avio_wb24(pb, ts); avio_w8(pb, (ts >> 24) & 0x7F); // timestamps are 32 bits _signed_ avio_wb24(pb, flv->reserved); if (enc->codec_type == AVMEDIA_TYPE_DATA) { int data_size; int metadata_size_pos = avio_tell(pb); avio_w8(pb, AMF_DATA_TYPE_STRING); put_amf_string(pb, "onTextData"); avio_w8(pb, AMF_DATA_TYPE_MIXEDARRAY); avio_wb32(pb, 2); put_amf_string(pb, "type"); avio_w8(pb, AMF_DATA_TYPE_STRING); put_amf_string(pb, "Text"); put_amf_string(pb, "text"); avio_w8(pb, AMF_DATA_TYPE_STRING); put_amf_string(pb, pkt->data); put_amf_string(pb, ""); avio_w8(pb, AMF_END_OF_OBJECT); /* write total size of tag */ data_size = avio_tell(pb) - metadata_size_pos; avio_seek(pb, metadata_size_pos - 10, SEEK_SET); avio_wb24(pb, data_size); avio_seek(pb, data_size + 10 - 3, SEEK_CUR); avio_wb32(pb, data_size + 11); } else { avio_w8(pb,flags); if (enc->codec_id == AV_CODEC_ID_VP6) avio_w8(pb, 0); if (enc->codec_id == AV_CODEC_ID_VP6F) avio_w8(pb, enc->extradata_size ? enc->extradata[0] : 0); else if (enc->codec_id == AV_CODEC_ID_AAC) avio_w8(pb, 1); // AAC raw else if (enc->codec_id == AV_CODEC_ID_H264) { avio_w8(pb, 1); // AVC NALU avio_wb24(pb, pkt->pts - pkt->dts); } avio_write(pb, data ? data : pkt->data, size); avio_wb32(pb, size + flags_size + 11); // previous tag size flv->duration = FFMAX(flv->duration, pkt->pts + flv->delay + pkt->duration); } avio_flush(pb); av_free(data); return pb->error; }
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]; av_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_dbl2int(codec->i_quant_factor)); avio_wb64(pb, av_dbl2int(codec->b_quant_factor)); avio_wb64(pb, av_dbl2int(codec->i_quant_offset)); avio_wb64(pb, av_dbl2int(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->luma_elim_threshold); avio_wb32(pb, codec->chroma_elim_threshold); 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_dbl2int(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_dbl2int(codec->qcompress)); avio_wb64(pb, av_dbl2int(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 pmp_header(AVFormatContext *s, AVFormatParameters *ap) { PMPContext *pmp = s->priv_data; AVIOContext *pb = s->pb; int tb_num, tb_den; int index_cnt; int audio_codec_id = CODEC_ID_NONE; int srate, channels; int i; uint64_t pos; AVStream *vst = av_new_stream(s, 0); if (!vst) return AVERROR(ENOMEM); vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; avio_skip(pb, 8); switch (avio_rl32(pb)) { case 0: vst->codec->codec_id = CODEC_ID_MPEG4; break; case 1: vst->codec->codec_id = CODEC_ID_H264; break; default: av_log(s, AV_LOG_ERROR, "Unsupported video format\n"); break; } index_cnt = avio_rl32(pb); vst->codec->width = avio_rl32(pb); vst->codec->height = avio_rl32(pb); tb_num = avio_rl32(pb); tb_den = avio_rl32(pb); av_set_pts_info(vst, 32, tb_num, tb_den); vst->nb_frames = index_cnt; vst->duration = index_cnt; switch (avio_rl32(pb)) { case 0: audio_codec_id = CODEC_ID_MP3; break; case 1: av_log(s, AV_LOG_ERROR, "AAC not yet correctly supported\n"); audio_codec_id = CODEC_ID_AAC; break; default: av_log(s, AV_LOG_ERROR, "Unsupported audio format\n"); break; } pmp->num_streams = avio_rl16(pb) + 1; avio_skip(pb, 10); srate = avio_rl32(pb); channels = avio_rl32(pb) + 1; for (i = 1; i < pmp->num_streams; i++) { AVStream *ast = av_new_stream(s, i); if (!ast) return AVERROR(ENOMEM); ast->codec->codec_type = AVMEDIA_TYPE_AUDIO; ast->codec->codec_id = audio_codec_id; ast->codec->channels = channels; ast->codec->sample_rate = srate; av_set_pts_info(ast, 32, 1, srate); } pos = avio_tell(pb) + 4*index_cnt; for (i = 0; i < index_cnt; i++) { int size = avio_rl32(pb); int flags = size & 1 ? AVINDEX_KEYFRAME : 0; size >>= 1; av_add_index_entry(vst, pos, i, size, 0, flags); pos += size; } 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; }
static void write_fat(AVIOContext *pb, int start_sector, int nb_sectors, int shift) { int i; for (i = 0; i < nb_sectors; i++) { avio_wl32(pb, start_sector + (i << shift)); } // pad left sector pointer size write_pad(pb, WTV_SECTOR_SIZE - ((nb_sectors << 2) % WTV_SECTOR_SIZE)); } static int64_t write_fat_sector(AVFormatContext *s, int64_t start_pos, int nb_sectors, int sector_bits, int depth) { int64_t start_sector = start_pos >> WTV_SECTOR_BITS; int shift = sector_bits - WTV_SECTOR_BITS; int64_t fat = avio_tell(s->pb); write_fat(s->pb, start_sector, nb_sectors, shift); if (depth == 2) { int64_t start_sector1 = fat >> WTV_SECTOR_BITS; int nb_sectors1 = ((nb_sectors << 2) + WTV_SECTOR_SIZE - 1) / WTV_SECTOR_SIZE; int64_t fat1 = avio_tell(s->pb); write_fat(s->pb, start_sector1, nb_sectors1, 0); return fat1; } return fat; } static void write_table_entries_events(AVFormatContext *s)
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 == CODEC_ID_MP3) { if (!enc->frame_size) { av_log(s, AV_LOG_ERROR, "audio frame size not set\n"); return -1; } 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 == CODEC_ID_VP6F || enc->codec_id == CODEC_ID_FLV1 || enc->codec_id == 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 == CODEC_ID_VP6F) version = 8; /* version 8 and above support VP6 codec */ else if (swf->video_enc && swf->video_enc->codec_id == 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 == 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 == 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; }
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; }
static int read_header(AVFormatContext *s) { BRSTMDemuxContext *b = s->priv_data; int bom, major, minor, codec, chunk; int64_t h1offset, pos, toffset; uint32_t size, asize, start = 0; AVStream *st; int ret = AVERROR_EOF; int loop = 0; int bfstm = !strcmp("bfstm", s->iformat->name); st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); st->codec->codec_type = AVMEDIA_TYPE_AUDIO; avio_skip(s->pb, 4); bom = avio_rb16(s->pb); if (bom != 0xFEFF && bom != 0xFFFE) { av_log(s, AV_LOG_ERROR, "invalid byte order: %X\n", bom); return AVERROR_INVALIDDATA; } if (bom == 0xFFFE) b->little_endian = 1; if (!bfstm) { major = avio_r8(s->pb); minor = avio_r8(s->pb); avio_skip(s->pb, 4); // size of file size = read16(s); if (size < 14) return AVERROR_INVALIDDATA; avio_skip(s->pb, size - 14); pos = avio_tell(s->pb); if (avio_rl32(s->pb) != MKTAG('H','E','A','D')) return AVERROR_INVALIDDATA; } else { uint32_t info_offset = 0; uint16_t section_count, header_size, i; header_size = read16(s); // 6 avio_skip(s->pb, 4); // Unknown constant 0x00030000 avio_skip(s->pb, 4); // size of file section_count = read16(s); avio_skip(s->pb, 2); // padding for (i = 0; avio_tell(s->pb) < header_size && !(start && info_offset) && i < section_count; i++) { uint16_t flag = read16(s); avio_skip(s->pb, 2); switch (flag) { case 0x4000: info_offset = read32(s); /*info_size =*/ read32(s); break; case 0x4001: avio_skip(s->pb, 4); // seek offset avio_skip(s->pb, 4); // seek size break; case 0x4002: start = read32(s) + 8; avio_skip(s->pb, 4); //data_size = read32(s); break; case 0x4003: avio_skip(s->pb, 4); // REGN offset avio_skip(s->pb, 4); // REGN size break; } } if (!info_offset || !start) return AVERROR_INVALIDDATA; avio_skip(s->pb, info_offset - avio_tell(s->pb)); pos = avio_tell(s->pb); if (avio_rl32(s->pb) != MKTAG('I','N','F','O')) return AVERROR_INVALIDDATA; } size = read32(s); if (size < 192) return AVERROR_INVALIDDATA; avio_skip(s->pb, 4); // unknown h1offset = read32(s); if (h1offset > size) return AVERROR_INVALIDDATA; avio_skip(s->pb, 12); toffset = read32(s) + 16LL; if (toffset > size) return AVERROR_INVALIDDATA; avio_skip(s->pb, pos + h1offset + 8 - avio_tell(s->pb)); codec = avio_r8(s->pb); switch (codec) { case 0: codec = AV_CODEC_ID_PCM_S8_PLANAR; break; case 1: codec = b->little_endian ? AV_CODEC_ID_PCM_S16LE_PLANAR : AV_CODEC_ID_PCM_S16BE_PLANAR; break; case 2: codec = b->little_endian ? AV_CODEC_ID_ADPCM_THP_LE : AV_CODEC_ID_ADPCM_THP; break; default: avpriv_request_sample(s, "codec %d", codec); return AVERROR_PATCHWELCOME; } loop = avio_r8(s->pb); // loop flag st->codec->codec_id = codec; st->codec->channels = avio_r8(s->pb); if (!st->codec->channels) return AVERROR_INVALIDDATA; avio_skip(s->pb, 1); // padding st->codec->sample_rate = bfstm ? read32(s) : read16(s); if (!st->codec->sample_rate) return AVERROR_INVALIDDATA; if (!bfstm) avio_skip(s->pb, 2); // padding if (loop) { if (av_dict_set_int(&s->metadata, "loop_start", av_rescale(read32(s), AV_TIME_BASE, st->codec->sample_rate), 0) < 0) return AVERROR(ENOMEM); } else { avio_skip(s->pb, 4); } st->start_time = 0; st->duration = read32(s); avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); if (!bfstm) start = read32(s); b->current_block = 0; b->block_count = read32(s); if (b->block_count > UINT16_MAX) { av_log(s, AV_LOG_WARNING, "too many blocks: %u\n", b->block_count); return AVERROR_INVALIDDATA; } b->block_size = read32(s); if (b->block_size > UINT32_MAX / st->codec->channels) return AVERROR_INVALIDDATA; b->samples_per_block = read32(s); b->last_block_used_bytes = read32(s); b->last_block_samples = read32(s); b->last_block_size = read32(s); if (b->last_block_size > UINT32_MAX / st->codec->channels) return AVERROR_INVALIDDATA; if (b->last_block_used_bytes > b->last_block_size) return AVERROR_INVALIDDATA; if (codec == AV_CODEC_ID_ADPCM_THP || codec == AV_CODEC_ID_ADPCM_THP_LE) { int ch; avio_skip(s->pb, pos + toffset - avio_tell(s->pb)); if (!bfstm) toffset = read32(s) + 16LL; else toffset = toffset + read32(s) + st->codec->channels * 8 - 8; if (toffset > size) return AVERROR_INVALIDDATA; avio_skip(s->pb, pos + toffset - avio_tell(s->pb)); b->table = av_mallocz(32 * st->codec->channels); if (!b->table) return AVERROR(ENOMEM); for (ch = 0; ch < st->codec->channels; ch++) { if (avio_read(s->pb, b->table + ch * 32, 32) != 32) { ret = AVERROR_INVALIDDATA; goto fail; } avio_skip(s->pb, bfstm ? 14 : 24); } } if (size < (avio_tell(s->pb) - pos)) { ret = AVERROR_INVALIDDATA; goto fail; } avio_skip(s->pb, size - (avio_tell(s->pb) - pos)); while (!avio_feof(s->pb)) { chunk = avio_rl32(s->pb); size = read32(s); if (size < 8) { ret = AVERROR_INVALIDDATA; goto fail; } size -= 8; switch (chunk) { case MKTAG('S','E','E','K'): case MKTAG('A','D','P','C'): if (codec != AV_CODEC_ID_ADPCM_THP && codec != AV_CODEC_ID_ADPCM_THP_LE) goto skip; asize = b->block_count * st->codec->channels * 4; if (size < asize) { ret = AVERROR_INVALIDDATA; goto fail; } if (b->adpc) { av_log(s, AV_LOG_WARNING, "skipping additional ADPC chunk\n"); goto skip; } else { b->adpc = av_mallocz(asize); if (!b->adpc) { ret = AVERROR(ENOMEM); goto fail; } if (bfstm && codec != AV_CODEC_ID_ADPCM_THP_LE) { // Big-endian BFSTMs have little-endian SEEK tables // for some strange reason. int i; for (i = 0; i < asize; i += 2) { b->adpc[i+1] = avio_r8(s->pb); b->adpc[i] = avio_r8(s->pb); } } else { avio_read(s->pb, b->adpc, asize); } avio_skip(s->pb, size - asize); } break; case MKTAG('D','A','T','A'): if ((start < avio_tell(s->pb)) || (!b->adpc && (codec == AV_CODEC_ID_ADPCM_THP || codec == AV_CODEC_ID_ADPCM_THP_LE))) { ret = AVERROR_INVALIDDATA; goto fail; } avio_skip(s->pb, start - avio_tell(s->pb)); if (bfstm && (codec == AV_CODEC_ID_ADPCM_THP || codec == AV_CODEC_ID_ADPCM_THP_LE)) avio_skip(s->pb, 24); b->data_start = avio_tell(s->pb); if (!bfstm && (major != 1 || minor)) avpriv_request_sample(s, "Version %d.%d", major, minor); return 0; default: av_log(s, AV_LOG_WARNING, "skipping unknown chunk: %X\n", chunk); skip: avio_skip(s->pb, size); } } fail: read_close(s); return ret; }
int n; for (n = 0; n < ogg->nstreams; n++) { av_freep(&ogg->streams[n].buf); av_freep(&ogg->streams[n].private); } ogg->curidx = -1; ogg->nstreams = 0; } idx = ogg_new_stream (s, serial); if (idx < 0) return -1; } os = ogg->streams + idx; os->page_pos = avio_tell(bc) - 27; if(os->psize > 0) ogg_new_buf(ogg, idx); if (avio_read (bc, os->segments, nsegs) < nsegs) return -1; os->nsegs = nsegs; os->segp = 0; size = 0; for (i = 0; i < nsegs; i++) size += os->segments[i]; if (flags & OGG_FLAG_CONT || os->incomplete){
static int iff_read_header(AVFormatContext *s, AVFormatParameters *ap) { IffDemuxContext *iff = s->priv_data; AVIOContext *pb = s->pb; AVStream *st; uint32_t chunk_id, data_size; int compression = -1; st = av_new_stream(s, 0); if (!st) return AVERROR(ENOMEM); st->codec->channels = 1; avio_skip(pb, 8); // codec_tag used by ByteRun1 decoder to distinguish progressive (PBM) and interlaced (ILBM) content st->codec->codec_tag = avio_rl32(pb); while(!pb->eof_reached) { uint64_t orig_pos; int res; const char *metadata_tag = NULL; chunk_id = avio_rl32(pb); data_size = avio_rb32(pb); orig_pos = avio_tell(pb); switch(chunk_id) { case ID_VHDR: st->codec->codec_type = AVMEDIA_TYPE_AUDIO; if (data_size < 14) return AVERROR_INVALIDDATA; avio_skip(pb, 12); st->codec->sample_rate = avio_rb16(pb); if (data_size >= 16) { avio_skip(pb, 1); compression = avio_r8(pb); } break; case ID_BODY: iff->body_pos = avio_tell(pb); iff->body_size = data_size; break; case ID_CHAN: if (data_size < 4) return AVERROR_INVALIDDATA; st->codec->channels = (avio_rb32(pb) < 6) ? 1 : 2; break; case ID_CMAP: st->codec->extradata_size = data_size; st->codec->extradata = av_malloc(data_size); if (!st->codec->extradata) return AVERROR(ENOMEM); if (avio_read(pb, st->codec->extradata, data_size) < 0) return AVERROR(EIO); break; case ID_BMHD: st->codec->codec_type = AVMEDIA_TYPE_VIDEO; if (data_size <= 8) return AVERROR_INVALIDDATA; st->codec->width = avio_rb16(pb); st->codec->height = avio_rb16(pb); avio_skip(pb, 4); // x, y offset st->codec->bits_per_coded_sample = avio_r8(pb); if (data_size >= 11) { avio_skip(pb, 1); // masking compression = avio_r8(pb); } if (data_size >= 16) { avio_skip(pb, 3); // paddding, transparent st->sample_aspect_ratio.num = avio_r8(pb); st->sample_aspect_ratio.den = avio_r8(pb); } break; case ID_ANNO: case ID_TEXT: metadata_tag = "comment"; break; case ID_AUTH: metadata_tag = "artist"; break; case ID_COPYRIGHT: metadata_tag = "copyright"; break; case ID_NAME: metadata_tag = "title"; break; } if (metadata_tag) { if ((res = get_metadata(s, metadata_tag, data_size)) < 0) { av_log(s, AV_LOG_ERROR, "cannot allocate metadata tag %s!", metadata_tag); return res; } } avio_skip(pb, data_size - (avio_tell(pb) - orig_pos) + (data_size & 1)); } avio_seek(pb, iff->body_pos, SEEK_SET); switch(st->codec->codec_type) { case AVMEDIA_TYPE_AUDIO: av_set_pts_info(st, 32, 1, st->codec->sample_rate); switch(compression) { case COMP_NONE: st->codec->codec_id = CODEC_ID_PCM_S8; break; case COMP_FIB: st->codec->codec_id = CODEC_ID_8SVX_FIB; break; case COMP_EXP: st->codec->codec_id = CODEC_ID_8SVX_EXP; break; default: av_log(s, AV_LOG_ERROR, "unknown compression method\n"); return -1; } st->codec->bits_per_coded_sample = 8; st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * st->codec->bits_per_coded_sample; st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample; break; case AVMEDIA_TYPE_VIDEO: switch (compression) { case BITMAP_RAW: st->codec->codec_id = CODEC_ID_IFF_ILBM; break; case BITMAP_BYTERUN1: st->codec->codec_id = CODEC_ID_IFF_BYTERUN1; break; default: av_log(s, AV_LOG_ERROR, "unknown compression method\n"); return AVERROR_INVALIDDATA; } break; default: return -1; } return 0; }
/* * Process EA file header * Returns 1 if the EA file is valid and successfully opened, 0 otherwise */ static int process_ea_header(AVFormatContext *s) { uint32_t blockid, size = 0; EaDemuxContext *ea = s->priv_data; AVIOContext *pb = s->pb; int i; for (i=0; i<5 && (!ea->audio_codec || !ea->video_codec); i++) { unsigned int startpos = avio_tell(pb); int err = 0; blockid = avio_rl32(pb); size = avio_rl32(pb); if (i == 0) ea->big_endian = size > 0x000FFFFF; if (ea->big_endian) size = av_bswap32(size); switch (blockid) { case ISNh_TAG: if (avio_rl32(pb) != EACS_TAG) { av_log (s, AV_LOG_ERROR, "unknown 1SNh headerid\n"); return 0; } err = process_audio_header_eacs(s); break; case SCHl_TAG : case SHEN_TAG : blockid = avio_rl32(pb); if (blockid == GSTR_TAG) { avio_skip(pb, 4); } else if ((blockid & 0xFFFF)!=PT00_TAG) { av_log (s, AV_LOG_ERROR, "unknown SCHl headerid\n"); return 0; } err = process_audio_header_elements(s); break; case SEAD_TAG: err = process_audio_header_sead(s); break; case MVIh_TAG : err = process_video_header_cmv(s); break; case kVGT_TAG: ea->video_codec = CODEC_ID_TGV; break; case mTCD_TAG : err = process_video_header_mdec(s); break; case MPCh_TAG: ea->video_codec = CODEC_ID_MPEG2VIDEO; break; case pQGT_TAG: case TGQs_TAG: ea->video_codec = CODEC_ID_TGQ; break; case pIQT_TAG: ea->video_codec = CODEC_ID_TQI; break; case MADk_TAG : ea->video_codec = CODEC_ID_MAD; break; case MVhd_TAG : err = process_video_header_vp6(s); break; } if (err < 0) { av_log(s, AV_LOG_ERROR, "error parsing header: %i\n", err); return err; } avio_seek(pb, startpos + size, SEEK_SET); } avio_seek(pb, 0, SEEK_SET); return 1; }