/** * read rl2 header data and setup the avstreams * @param s demuxer context * @param ap format parameters * @return 0 on success, AVERROR otherwise */ static av_cold int rl2_read_header(AVFormatContext *s, AVFormatParameters *ap) { AVIOContext *pb = s->pb; AVStream *st; unsigned int frame_count; unsigned int audio_frame_counter = 0; unsigned int video_frame_counter = 0; unsigned int back_size; unsigned short sound_rate; unsigned short rate; unsigned short channels; unsigned short def_sound_size; unsigned int signature; unsigned int pts_den = 11025; /* video only case */ unsigned int pts_num = 1103; unsigned int* chunk_offset = NULL; int* chunk_size = NULL; int* audio_size = NULL; int i; int ret = 0; avio_skip(pb,4); /* skip FORM tag */ back_size = avio_rl32(pb); /**< get size of the background frame */ signature = avio_rb32(pb); avio_skip(pb, 4); /* data size */ frame_count = avio_rl32(pb); /* disallow back_sizes and frame_counts that may lead to overflows later */ if(back_size > INT_MAX/2 || frame_count > INT_MAX / sizeof(uint32_t)) return AVERROR_INVALIDDATA; avio_skip(pb, 2); /* encoding mentod */ sound_rate = avio_rl16(pb); rate = avio_rl16(pb); channels = avio_rl16(pb); def_sound_size = avio_rl16(pb); /** setup video stream */ st = avformat_new_stream(s, NULL); if(!st) return AVERROR(ENOMEM); st->codec->codec_type = AVMEDIA_TYPE_VIDEO; st->codec->codec_id = CODEC_ID_RL2; st->codec->codec_tag = 0; /* no fourcc */ st->codec->width = 320; st->codec->height = 200; /** allocate and fill extradata */ st->codec->extradata_size = EXTRADATA1_SIZE; if(signature == RLV3_TAG && back_size > 0) st->codec->extradata_size += back_size; st->codec->extradata = av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); if(!st->codec->extradata) return AVERROR(ENOMEM); if(avio_read(pb,st->codec->extradata,st->codec->extradata_size) != st->codec->extradata_size) return AVERROR(EIO); /** setup audio stream if present */ if(sound_rate){ pts_num = def_sound_size; pts_den = rate; st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); st->codec->codec_type = AVMEDIA_TYPE_AUDIO; st->codec->codec_id = CODEC_ID_PCM_U8; st->codec->codec_tag = 1; st->codec->channels = channels; st->codec->bits_per_coded_sample = 8; st->codec->sample_rate = rate; 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 / 8; av_set_pts_info(st,32,1,rate); } av_set_pts_info(s->streams[0], 32, pts_num, pts_den); chunk_size = av_malloc(frame_count * sizeof(uint32_t)); audio_size = av_malloc(frame_count * sizeof(uint32_t)); chunk_offset = av_malloc(frame_count * sizeof(uint32_t)); if(!chunk_size || !audio_size || !chunk_offset){ av_free(chunk_size); av_free(audio_size); av_free(chunk_offset); return AVERROR(ENOMEM); } /** read offset and size tables */ for(i=0; i < frame_count;i++) chunk_size[i] = avio_rl32(pb); for(i=0; i < frame_count;i++) chunk_offset[i] = avio_rl32(pb); for(i=0; i < frame_count;i++) audio_size[i] = avio_rl32(pb) & 0xFFFF; /** build the sample index */ for(i=0;i<frame_count;i++){ if(chunk_size[i] < 0 || audio_size[i] > chunk_size[i]){ ret = AVERROR_INVALIDDATA; break; } if(sound_rate && audio_size[i]){ av_add_index_entry(s->streams[1], chunk_offset[i], audio_frame_counter,audio_size[i], 0, AVINDEX_KEYFRAME); audio_frame_counter += audio_size[i] / channels; } av_add_index_entry(s->streams[0], chunk_offset[i] + audio_size[i], video_frame_counter,chunk_size[i]-audio_size[i],0,AVINDEX_KEYFRAME); ++video_frame_counter; } av_free(chunk_size); av_free(audio_size); av_free(chunk_offset); return ret; }
static int xwma_read_header(AVFormatContext *s, AVFormatParameters *ap) { int64_t size, av_uninit(data_size); int ret; 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 != CODEC_ID_WMAV2) { av_log(s, AV_LOG_WARNING, "unexpected codec (tag 0x04%x; id %d)\n", st->codec->codec_tag, st->codec->codec_id); av_log_ask_for_sample(s, NULL); } 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. */ av_log(s, AV_LOG_WARNING, "unexpected extradata (%d bytes)\n", st->codec->extradata_size); av_log_ask_for_sample(s, NULL); } 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; } } /* set the sample rate */ av_set_pts_info(st, 64, 1, st->codec->sample_rate); /* parse the remaining RIFF chunks */ for (;;) { if (pb->eof_reached) return -1; /* 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"); return -1; } /* 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) return -1; 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]; 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 read_header(AVFormatContext *s, AVFormatParameters *ap) { ByteIOContext *pb = s->pb; CaffContext *caf = s->priv_data; AVStream *st; uint32_t tag = 0; int found_data, ret; int64_t size; url_fskip(pb, 8); /* magic, version, file flags */ /* audio description chunk */ if (get_be32(pb) != MKBETAG('d','e','s','c')) { av_log(s, AV_LOG_ERROR, "desc chunk not present\n"); return AVERROR_INVALIDDATA; } size = get_be64(pb); if (size != 32) return AVERROR_INVALIDDATA; ret = read_desc_chunk(s); if (ret) return ret; st = s->streams[0]; /* parse each chunk */ found_data = 0; while (!url_feof(pb)) { /* stop at data chunk if seeking is not supported or data chunk size is unknown */ if (found_data && (caf->data_size < 0 || url_is_streamed(pb))) break; tag = get_be32(pb); size = get_be64(pb); if (url_feof(pb)) break; switch (tag) { case MKBETAG('d','a','t','a'): url_fskip(pb, 4); /* edit count */ caf->data_start = url_ftell(pb); caf->data_size = size < 0 ? -1 : size - 4; if (caf->data_size > 0 && !url_is_streamed(pb)) url_fskip(pb, caf->data_size); found_data = 1; break; /* magic cookie chunk */ case MKBETAG('k','u','k','i'): if (read_kuki_chunk(s, size)) return AVERROR_INVALIDDATA; break; /* packet table chunk */ case MKBETAG('p','a','k','t'): if (read_pakt_chunk(s, size)) return AVERROR_INVALIDDATA; break; case MKBETAG('i','n','f','o'): read_info_chunk(s, size); break; default: #define _(x) ((x) >= ' ' ? (x) : ' ') av_log(s, AV_LOG_WARNING, "skipping CAF chunk: %08X (%c%c%c%c)\n", tag, _(tag>>24), _((tag>>16)&0xFF), _((tag>>8)&0xFF), _(tag&0xFF)); #undef _ case MKBETAG('f','r','e','e'): if (size < 0) return AVERROR_INVALIDDATA; url_fskip(pb, size); break; } } if (!found_data) return AVERROR_INVALIDDATA; if (caf->bytes_per_packet > 0 && caf->frames_per_packet > 0) { if (caf->data_size > 0) st->nb_frames = (caf->data_size / caf->bytes_per_packet) * caf->frames_per_packet; } else if (st->nb_index_entries) { st->codec->bit_rate = st->codec->sample_rate * caf->data_size * 8 / st->duration; } else { av_log(s, AV_LOG_ERROR, "Missing packet table. It is required when " "block size or frame size are variable.\n"); return AVERROR_INVALIDDATA; } s->file_size = url_fsize(pb); s->file_size = FFMAX(0, s->file_size); av_set_pts_info(st, 64, 1, st->codec->sample_rate); st->start_time = 0; /* position the stream at the start of data */ if (caf->data_size >= 0) url_fseek(pb, caf->data_start, SEEK_SET); return 0; }
static int read_header(AVFormatContext *s, AVFormatParameters *ap) { BinkDemuxContext *bink = s->priv_data; AVIOContext *pb = s->pb; uint32_t fps_num, fps_den; AVStream *vst, *ast; unsigned int i; uint32_t pos, next_pos; uint16_t flags; int keyframe; vst = av_new_stream(s, 0); if (!vst) return AVERROR(ENOMEM); vst->codec->codec_tag = avio_rl32(pb); bink->file_size = avio_rl32(pb) + 8; vst->duration = avio_rl32(pb); if (vst->duration > 1000000) { av_log(s, AV_LOG_ERROR, "invalid header: more than 1000000 frames\n"); return AVERROR(EIO); } if (avio_rl32(pb) > bink->file_size) { av_log(s, AV_LOG_ERROR, "invalid header: largest frame size greater than file size\n"); return AVERROR(EIO); } avio_seek(pb, 4, SEEK_CUR); vst->codec->width = avio_rl32(pb); vst->codec->height = avio_rl32(pb); fps_num = avio_rl32(pb); fps_den = avio_rl32(pb); if (fps_num == 0 || fps_den == 0) { av_log(s, AV_LOG_ERROR, "invalid header: invalid fps (%d/%d)\n", fps_num, fps_den); return AVERROR(EIO); } av_set_pts_info(vst, 64, fps_den, fps_num); vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; vst->codec->codec_id = CODEC_ID_BINKVIDEO; vst->codec->extradata = av_mallocz(4 + FF_INPUT_BUFFER_PADDING_SIZE); vst->codec->extradata_size = 4; avio_read(pb, vst->codec->extradata, 4); bink->num_audio_tracks = avio_rl32(pb); if (bink->num_audio_tracks > BINK_MAX_AUDIO_TRACKS) { av_log(s, AV_LOG_ERROR, "invalid header: more than "AV_STRINGIFY(BINK_MAX_AUDIO_TRACKS)" audio tracks (%d)\n", bink->num_audio_tracks); return AVERROR(EIO); } if (bink->num_audio_tracks) { avio_seek(pb, 4 * bink->num_audio_tracks, SEEK_CUR); for (i = 0; i < bink->num_audio_tracks; i++) { ast = av_new_stream(s, 1); if (!ast) return AVERROR(ENOMEM); ast->codec->codec_type = AVMEDIA_TYPE_AUDIO; ast->codec->codec_tag = vst->codec->codec_tag; ast->codec->sample_rate = avio_rl16(pb); av_set_pts_info(ast, 64, 1, ast->codec->sample_rate); flags = avio_rl16(pb); ast->codec->codec_id = flags & BINK_AUD_USEDCT ? CODEC_ID_BINKAUDIO_DCT : CODEC_ID_BINKAUDIO_RDFT; ast->codec->channels = flags & BINK_AUD_STEREO ? 2 : 1; } for (i = 0; i < bink->num_audio_tracks; i++) s->streams[i + 1]->id = avio_rl32(pb); } /* frame index table */ next_pos = avio_rl32(pb); for (i = 0; i < vst->duration; i++) { pos = next_pos; if (i == vst->duration - 1) { next_pos = bink->file_size; keyframe = 0; } else { next_pos = avio_rl32(pb); keyframe = pos & 1; } pos &= ~1; next_pos &= ~1; if (next_pos <= pos) { av_log(s, AV_LOG_ERROR, "invalid frame index table\n"); return AVERROR(EIO); } av_add_index_entry(vst, pos, i, next_pos - pos, 0, keyframe ? AVINDEX_KEYFRAME : 0); } avio_seek(pb, 4, SEEK_CUR); bink->current_track = -1; return 0; }
static int avi_write_header(AVFormatContext *s) { AVIContext *avi = s->priv_data; ByteIOContext *pb = &s->pb; int bitrate, n, i, nb_frames, au_byterate, au_ssize, au_scale; AVCodecContext *stream, *video_enc; offset_t list1, list2, strh, strf; /* header list */ avi->riff_id = 0; list1 = avi_start_new_riff(avi, pb, "AVI ", "hdrl"); /* avi header */ put_tag(pb, "avih"); put_le32(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 == CODEC_TYPE_VIDEO) video_enc = stream; } nb_frames = 0; if(video_enc){ put_le32(pb, (uint32_t)(int64_t_C(1000000) * video_enc->frame_rate_base / video_enc->frame_rate)); } else { put_le32(pb, 0); } put_le32(pb, bitrate / 8); /* XXX: not quite exact */ put_le32(pb, 0); /* padding */ put_le32(pb, AVIF_TRUSTCKTYPE | AVIF_HASINDEX | AVIF_ISINTERLEAVED); /* flags */ avi->frames_hdr_all = url_ftell(pb); /* remember this offset to fill later */ put_le32(pb, nb_frames); /* nb frames, filled later */ put_le32(pb, 0); /* initial frame */ put_le32(pb, s->nb_streams); /* nb streams */ put_le32(pb, 1024 * 1024); /* suggested buffer size */ if(video_enc){ put_le32(pb, video_enc->width); put_le32(pb, video_enc->height); } else { put_le32(pb, 0); put_le32(pb, 0); } put_le32(pb, 0); /* reserved */ put_le32(pb, 0); /* reserved */ put_le32(pb, 0); /* reserved */ put_le32(pb, 0); /* reserved */ /* stream list */ for(i=0;i<n;i++) { list2 = start_tag(pb, "LIST"); put_tag(pb, "strl"); stream = &s->streams[i]->codec; /* FourCC should really be set by the codec itself */ if (! stream->codec_tag) { stream->codec_tag = codec_get_bmp_tag(stream->codec_id); } /* stream generic header */ strh = start_tag(pb, "strh"); switch(stream->codec_type) { case CODEC_TYPE_VIDEO: put_tag(pb, "vids"); put_le32(pb, stream->codec_tag); put_le32(pb, 0); /* flags */ put_le16(pb, 0); /* priority */ put_le16(pb, 0); /* language */ put_le32(pb, 0); /* initial frame */ put_le32(pb, stream->frame_rate_base); /* scale */ put_le32(pb, stream->frame_rate); /* rate */ av_set_pts_info(s->streams[i], 64, stream->frame_rate_base, stream->frame_rate); put_le32(pb, 0); /* start */ avi->frames_hdr_strm[i] = url_ftell(pb); /* remember this offset to fill later */ put_le32(pb, nb_frames); /* length, XXX: fill later */ put_le32(pb, 1024 * 1024); /* suggested buffer size */ put_le32(pb, -1); /* quality */ put_le32(pb, stream->width * stream->height * 3); /* sample size */ put_le16(pb, 0); put_le16(pb, 0); put_le16(pb, stream->width); put_le16(pb, stream->height); break; case CODEC_TYPE_AUDIO: put_tag(pb, "auds"); put_le32(pb, 1); /* tag */ put_le32(pb, 0); /* flags */ put_le16(pb, 0); /* priority */ put_le16(pb, 0); /* language */ put_le32(pb, 0); /* initial frame */ parse_specific_params(stream, &au_byterate, &au_ssize, &au_scale); put_le32(pb, au_scale); /* scale */ put_le32(pb, au_byterate); /* rate */ // av_set_pts_info(&s->streams[i], 64, au_scale, au_byterate); put_le32(pb, 0); /* start */ avi->frames_hdr_strm[i] = url_ftell(pb); /* remember this offset to fill later */ put_le32(pb, 0); /* length, XXX: filled later */ put_le32(pb, 12 * 1024); /* suggested buffer size */ put_le32(pb, -1); /* quality */ put_le32(pb, au_ssize); /* sample size */ put_le32(pb, 0); put_le32(pb, 0); break; default: av_abort(); } end_tag(pb, strh); strf = start_tag(pb, "strf"); switch(stream->codec_type) { case CODEC_TYPE_VIDEO: put_bmp_header(pb, stream, codec_bmp_tags, 0); break; case CODEC_TYPE_AUDIO: if (put_wav_header(pb, stream) < 0) { av_free(avi); return -1; } break; default: av_abort(); } end_tag(pb, strf); if (!url_is_streamed(pb)) { 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. */ avi->indexes[i].entry = avi->indexes[i].ents_allocated = 0; avi->indexes[i].indx_start = start_tag(pb, "JUNK"); put_le16(pb, 4); /* wLongsPerEntry */ put_byte(pb, 0); /* bIndexSubType (0 == frame index) */ put_byte(pb, 0); /* bIndexType (0 == AVI_INDEX_OF_INDEXES) */ put_le32(pb, 0); /* nEntriesInUse (will fill out later on) */ put_tag(pb, avi_stream2fourcc(&tag[0], i, stream->codec_type)); /* dwChunkId */ put_le64(pb, 0); /* dwReserved[3] put_le32(pb, 0); Must be 0. */ for (j=0; j < AVI_MASTER_INDEX_SIZE * 2; j++) put_le64(pb, 0); end_tag(pb, avi->indexes[i].indx_start); } end_tag(pb, list2); } if (!url_is_streamed(pb)) { /* AVI could become an OpenDML one, if it grows beyond 2Gb range */ avi->odml_list = start_tag(pb, "JUNK"); put_tag(pb, "odml"); put_tag(pb, "dmlh"); put_le32(pb, 248); for (i = 0; i < 248; i+= 4) put_le32(pb, 0); end_tag(pb, avi->odml_list); } end_tag(pb, list1); avi->movi_list = start_tag(pb, "LIST"); put_tag(pb, "movi"); put_flush_packet(pb); return 0; }
static int read_header(AVFormatContext *s, AVFormatParameters *ap) { int i, header_remaining; ASSContext *ass = s->priv_data; ByteIOContext *pb = s->pb; AVStream *st; int allocated[2]= {0}; uint8_t *p, **dst[2]= {0}; int pos[2]= {0}; st = av_new_stream(s, 0); if (!st) return -1; av_set_pts_info(st, 64, 1, 100); st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; st->codec->codec_id= CODEC_ID_SSA; header_remaining= INT_MAX; dst[0] = &st->codec->extradata; dst[1] = &ass->event_buffer; while(!url_feof(pb)) { uint8_t line[MAX_LINESIZE]; get_line(pb, line, sizeof(line)); if(!memcmp(line, "[Events]", 8)) header_remaining= 2; else if(line[0]=='[') header_remaining= INT_MAX; i= header_remaining==0; if(i && get_pts(line) == AV_NOPTS_VALUE) continue; p = av_fast_realloc(*(dst[i]), &allocated[i], pos[i]+MAX_LINESIZE); if(!p) goto fail; *(dst[i])= p; memcpy(p + pos[i], line, strlen(line)+1); pos[i] += strlen(line); if(i) ass->event_count++; else header_remaining--; } st->codec->extradata_size= pos[0]; if(ass->event_count >= UINT_MAX / sizeof(*ass->event)) goto fail; ass->event= av_malloc(ass->event_count * sizeof(*ass->event)); p= ass->event_buffer; for(i=0; i<ass->event_count; i++) { ass->event[i]= p; while(*p && *p != '\n') p++; p++; } qsort(ass->event, ass->event_count, sizeof(*ass->event), (void*)event_cmp); return 0; fail: read_close(s); return -1; }
static int roq_read_header(AVFormatContext *s, AVFormatParameters *ap) { RoqDemuxContext *roq = s->priv_data; ByteIOContext *pb = s->pb; AVStream *st; unsigned char preamble[RoQ_CHUNK_PREAMBLE_SIZE]; int i; unsigned int chunk_size; unsigned int chunk_type; /* get the main header */ if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) != RoQ_CHUNK_PREAMBLE_SIZE) return AVERROR(EIO); roq->framerate = AV_RL16(&preamble[6]); roq->frame_pts_inc = 90000 / roq->framerate; /* init private context parameters */ roq->width = roq->height = roq->audio_channels = roq->video_pts = roq->audio_frame_count = 0; /* scan the first n chunks searching for A/V parameters */ for (i = 0; i < RoQ_CHUNKS_TO_SCAN; i++) { if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) != RoQ_CHUNK_PREAMBLE_SIZE) return AVERROR(EIO); chunk_type = AV_RL16(&preamble[0]); chunk_size = AV_RL32(&preamble[2]); switch (chunk_type) { case RoQ_INFO: /* fetch the width and height; reuse the preamble bytes */ if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) != RoQ_CHUNK_PREAMBLE_SIZE) return AVERROR(EIO); roq->width = AV_RL16(&preamble[0]); roq->height = AV_RL16(&preamble[2]); break; case RoQ_QUAD_CODEBOOK: case RoQ_QUAD_VQ: /* ignore during this scan */ url_fseek(pb, chunk_size, SEEK_CUR); break; case RoQ_SOUND_MONO: roq->audio_channels = 1; url_fseek(pb, chunk_size, SEEK_CUR); break; case RoQ_SOUND_STEREO: roq->audio_channels = 2; url_fseek(pb, chunk_size, SEEK_CUR); break; default: av_log(s, AV_LOG_ERROR, " unknown RoQ chunk type (%04X)\n", AV_RL16(&preamble[0])); return AVERROR_INVALIDDATA; break; } /* if all necessary parameters have been gathered, exit early */ if ((roq->width && roq->height) && roq->audio_channels) break; } /* seek back to the first chunk */ url_fseek(pb, RoQ_CHUNK_PREAMBLE_SIZE, SEEK_SET); /* initialize the decoders */ st = av_new_stream(s, 0); if (!st) return AVERROR(ENOMEM); /* set the pts reference (1 pts = 1/90000) */ av_set_pts_info(st, 33, 1, 90000); roq->video_stream_index = st->index; st->codec->codec_type = CODEC_TYPE_VIDEO; st->codec->codec_id = CODEC_ID_ROQ; st->codec->codec_tag = 0; /* no fourcc */ st->codec->width = roq->width; st->codec->height = roq->height; if (roq->audio_channels) { st = av_new_stream(s, 0); if (!st) return AVERROR(ENOMEM); av_set_pts_info(st, 33, 1, 90000); roq->audio_stream_index = st->index; st->codec->codec_type = CODEC_TYPE_AUDIO; st->codec->codec_id = CODEC_ID_ROQ_DPCM; st->codec->codec_tag = 0; /* no tag */ st->codec->channels = roq->audio_channels; st->codec->sample_rate = RoQ_AUDIO_SAMPLE_RATE; st->codec->bits_per_sample = 16; st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * st->codec->bits_per_sample; st->codec->block_align = st->codec->channels * st->codec->bits_per_sample; } return 0; }
static int img_read_header(AVFormatContext *s1, AVFormatParameters *ap) { VideoData *s = s1->priv_data; int first_index, last_index; AVStream *st; s1->ctx_flags |= AVFMTCTX_NOHEADER; st = av_new_stream(s1, 0); if (!st) { return AVERROR(ENOMEM); } av_strlcpy(s->path, s1->filename, sizeof(s->path)); s->img_number = 0; s->img_count = 0; /* find format */ if (s1->iformat->flags & AVFMT_NOFILE) s->is_pipe = 0; else{ s->is_pipe = 1; st->need_parsing = AVSTREAM_PARSE_FULL; } if (!ap->time_base.num) { av_set_pts_info(st, 60, 1, 25); } else { av_set_pts_info(st, 60, ap->time_base.num, ap->time_base.den); } if(ap->width && ap->height){ st->codec->width = ap->width; st->codec->height= ap->height; } if (!s->is_pipe) { if (find_image_range(&first_index, &last_index, s->path) < 0) return AVERROR(ENOENT); s->img_first = first_index; s->img_last = last_index; s->img_number = first_index; /* compute duration */ st->start_time = 0; st->duration = last_index - first_index + 1; } if(s1->video_codec_id){ st->codec->codec_type = CODEC_TYPE_VIDEO; st->codec->codec_id = s1->video_codec_id; }else if(s1->audio_codec_id){ st->codec->codec_type = CODEC_TYPE_AUDIO; st->codec->codec_id = s1->audio_codec_id; }else{ st->codec->codec_type = CODEC_TYPE_VIDEO; st->codec->codec_id = av_str2id(img_tags, s->path); } if(st->codec->codec_type == CODEC_TYPE_VIDEO && ap->pix_fmt != PIX_FMT_NONE) st->codec->pix_fmt = ap->pix_fmt; return 0; }
static int aiff_write_header(AVFormatContext *s) { AIFFOutputContext *aiff = s->priv_data; ByteIOContext *pb = s->pb; AVCodecContext *enc = s->streams[0]->codec; AVExtFloat sample_rate; int aifc = 0; /* First verify if format is ok */ if (!enc->codec_tag) return -1; if (enc->codec_tag != MKTAG('N','O','N','E')) aifc = 1; /* FORM AIFF header */ put_tag(pb, "FORM"); aiff->form = url_ftell(pb); put_be32(pb, 0); /* file length */ put_tag(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 */ put_tag(pb, "FVER"); put_be32(pb, 4); put_be32(pb, 0xA2805140); } /* Common chunk */ put_tag(pb, "COMM"); put_be32(pb, aifc ? 24 : 18); /* size */ put_be16(pb, enc->channels); /* Number of channels */ aiff->frames = url_ftell(pb); put_be32(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; put_be16(pb, enc->bits_per_coded_sample); /* Sample size */ sample_rate = av_dbl2ext((double)enc->sample_rate); put_buffer(pb, (uint8_t*)&sample_rate, sizeof(sample_rate)); if (aifc) { put_le32(pb, enc->codec_tag); put_be16(pb, 0); } /* Sound data chunk */ put_tag(pb, "SSND"); aiff->ssnd = url_ftell(pb); /* Sound chunk size */ put_be32(pb, 0); /* Sound samples data size */ put_be32(pb, 0); /* Data offset */ put_be32(pb, 0); /* Block-size (block align) */ av_set_pts_info(s->streams[0], 64, 1, s->streams[0]->codec->sample_rate); /* Data is starting here */ put_flush_packet(pb); return 0; }
static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) { int ret, i, type, size, pts, flags, is_audio; AVStream *st; for(;;){ url_fskip(&s->pb, 4); /* size of previous packet */ type = get_byte(&s->pb); size = get_be24(&s->pb); pts = get_be24(&s->pb); // av_log(s, AV_LOG_DEBUG, "type:%d, size:%d, pts:%d\n", type, size, pts); if (url_feof(&s->pb)) return AVERROR_IO; url_fskip(&s->pb, 4); /* reserved */ flags = 0; if(size == 0) continue; if (type == 8) { is_audio=1; flags = get_byte(&s->pb); size--; } else if (type == 9) { is_audio=0; flags = get_byte(&s->pb); size--; } else { /* skip packet */ av_log(s, AV_LOG_ERROR, "skipping flv packet: type %d, size %d, flags %d\n", type, size, flags); url_fskip(&s->pb, size); continue; } /* now find stream */ for(i=0;i<s->nb_streams;i++) { st = s->streams[i]; if (st->id == is_audio) break; } if(i == s->nb_streams){ st = av_new_stream(s, is_audio); if (!st) return AVERROR_NOMEM; av_set_pts_info(st, 24, 1, 1000); /* 24 bit pts in ms */ st->codec.frame_rate_base= 1; st->codec.frame_rate= 1000; } if(st->discard){ url_fskip(&s->pb, size); continue; } break; } if(is_audio){ if(st->codec.sample_rate == 0){ st->codec.codec_type = CODEC_TYPE_AUDIO; st->codec.channels = (flags&1)+1; if((flags >> 4) == 5) st->codec.sample_rate= 8000; else st->codec.sample_rate = (44100<<((flags>>2)&3))>>3; switch(flags >> 4){/* 0: uncompressed 1: ADPCM 2: mp3 5: Nellymoser 8kHz mono 6: Nellymoser*/ case 2: st->codec.codec_id = CODEC_ID_MP3; break; default: st->codec.codec_tag= (flags >> 4); } }
static int read_header(AVFormatContext *s, AVFormatParameters *ap) { JVDemuxContext *jv = s->priv_data; AVIOContext *pb = s->pb; AVStream *vst, *ast; int64_t audio_pts = 0; int64_t offset; int i; avio_skip(pb, 80); ast = av_new_stream(s, 0); vst = av_new_stream(s, 1); if (!ast || !vst) return AVERROR(ENOMEM); vst->codec->codec_type = CODEC_TYPE_VIDEO; vst->codec->codec_id = CODEC_ID_JV; vst->codec->codec_tag = 0; /* no fourcc */ vst->codec->width = avio_rl16(pb); vst->codec->height = avio_rl16(pb); vst->nb_frames = ast->nb_index_entries = avio_rl16(pb); av_set_pts_info(vst, 64, avio_rl16(pb), 1000); avio_skip(pb, 4); ast->codec->codec_type = CODEC_TYPE_AUDIO; ast->codec->codec_id = CODEC_ID_PCM_U8; ast->codec->codec_tag = 0; /* no fourcc */ ast->codec->sample_rate = avio_rl16(pb); ast->codec->channels = 1; av_set_pts_info(ast, 64, 1, ast->codec->sample_rate); avio_skip(pb, 10); ast->index_entries = av_malloc(ast->nb_index_entries * sizeof(*ast->index_entries)); if (!ast->index_entries) return AVERROR(ENOMEM); jv->frames = av_malloc(ast->nb_index_entries * sizeof(JVFrame)); if (!jv->frames) return AVERROR(ENOMEM); offset = 0x68 + ast->nb_index_entries * 16; for(i = 0; i < ast->nb_index_entries; i++) { AVIndexEntry *e = ast->index_entries + i; JVFrame *jvf = jv->frames + i; /* total frame size including audio, video, palette data and padding */ e->size = avio_rl32(pb); e->timestamp = i; e->pos = offset; offset += e->size; jvf->audio_size = avio_rl32(pb); jvf->video_size = avio_rl32(pb); jvf->palette_size = avio_r8(pb) ? 768 : 0; jvf->video_size = FFMIN(FFMAX(jvf->video_size, 0), INT_MAX - JV_PREAMBLE_SIZE - jvf->palette_size); if (avio_r8(pb)) av_log(s, AV_LOG_WARNING, "unsupported audio codec\n"); jvf->video_type = avio_r8(pb); avio_skip(pb, 1); e->timestamp = jvf->audio_size ? audio_pts : AV_NOPTS_VALUE; audio_pts += jvf->audio_size; e->flags = jvf->video_type != 1 ? AVINDEX_KEYFRAME : 0; } jv->state = JV_AUDIO; return 0; }
static int grab_read_header(AVFormatContext *s1, AVFormatParameters *ap) { VideoData *s = s1->priv_data; AVStream *st; int width, height; int video_fd, frame_size; int ret, frame_rate, frame_rate_base; int desired_palette, desired_depth; struct video_tuner tuner; struct video_audio audio; struct video_picture pict; const char *video_device; int j; if (ap->width <= 0 || ap->height <= 0 || ap->time_base.den <= 0) { av_log(s1, AV_LOG_ERROR, "Bad capture size (%dx%d) or wrong time base (%d)\n", ap->width, ap->height, ap->time_base.den); return -1; } width = ap->width; height = ap->height; frame_rate = ap->time_base.den; frame_rate_base = ap->time_base.num; if((unsigned)width > 32767 || (unsigned)height > 32767) { av_log(s1, AV_LOG_ERROR, "Capture size is out of range: %dx%d\n", width, height); return -1; } st = av_new_stream(s1, 0); if (!st) return -ENOMEM; av_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ s->width = width; s->height = height; s->frame_rate = frame_rate; s->frame_rate_base = frame_rate_base; video_device = ap->device; if (!video_device) video_device = "/dev/video"; video_fd = open(video_device, O_RDWR); if (video_fd < 0) { perror(video_device); goto fail; } if (ioctl(video_fd,VIDIOCGCAP, &s->video_cap) < 0) { perror("VIDIOCGCAP"); goto fail; } if (!(s->video_cap.type & VID_TYPE_CAPTURE)) { av_log(s1, AV_LOG_ERROR, "Fatal: grab device does not handle capture\n"); goto fail; } desired_palette = -1; desired_depth = -1; if (ap->pix_fmt == PIX_FMT_YUV420P) { desired_palette = VIDEO_PALETTE_YUV420P; desired_depth = 12; } else if (ap->pix_fmt == PIX_FMT_YUV422) { desired_palette = VIDEO_PALETTE_YUV422; desired_depth = 16; } else if (ap->pix_fmt == PIX_FMT_BGR24) { desired_palette = VIDEO_PALETTE_RGB24; desired_depth = 24; } /* set tv standard */ if (ap->standard && !ioctl(video_fd, VIDIOCGTUNER, &tuner)) { if (!strcasecmp(ap->standard, "pal")) tuner.mode = VIDEO_MODE_PAL; else if (!strcasecmp(ap->standard, "secam")) tuner.mode = VIDEO_MODE_SECAM; else tuner.mode = VIDEO_MODE_NTSC; ioctl(video_fd, VIDIOCSTUNER, &tuner); } /* unmute audio */ audio.audio = 0; ioctl(video_fd, VIDIOCGAUDIO, &audio); memcpy(&s->audio_saved, &audio, sizeof(audio)); audio.flags &= ~VIDEO_AUDIO_MUTE; ioctl(video_fd, VIDIOCSAUDIO, &audio); ioctl(video_fd, VIDIOCGPICT, &pict); #if 0 printf("v4l: colour=%d hue=%d brightness=%d constrast=%d whiteness=%d\n", pict.colour, pict.hue, pict.brightness, pict.contrast, pict.whiteness); #endif /* try to choose a suitable video format */ pict.palette = desired_palette; pict.depth= desired_depth; if (desired_palette == -1 || (ret = ioctl(video_fd, VIDIOCSPICT, &pict)) < 0) { pict.palette=VIDEO_PALETTE_YUV420P; pict.depth=12; ret = ioctl(video_fd, VIDIOCSPICT, &pict); if (ret < 0) { pict.palette=VIDEO_PALETTE_YUV422; pict.depth=16; ret = ioctl(video_fd, VIDIOCSPICT, &pict); if (ret < 0) { pict.palette=VIDEO_PALETTE_RGB24; pict.depth=24; ret = ioctl(video_fd, VIDIOCSPICT, &pict); if (ret < 0) pict.palette=VIDEO_PALETTE_GREY; pict.depth=8; ret = ioctl(video_fd, VIDIOCSPICT, &pict); if (ret < 0) goto fail1; } } } ret = ioctl(video_fd,VIDIOCGMBUF,&s->gb_buffers); if (ret < 0) { /* try to use read based access */ struct video_window win; int val; win.x = 0; win.y = 0; win.width = width; win.height = height; win.chromakey = -1; win.flags = 0; ioctl(video_fd, VIDIOCSWIN, &win); s->frame_format = pict.palette; val = 1; ioctl(video_fd, VIDIOCCAPTURE, &val); s->time_frame = av_gettime() * s->frame_rate / s->frame_rate_base; s->use_mmap = 0; /* ATI All In Wonder automatic activation */ if (!strcmp(s->video_cap.name, "Km")) { if (aiw_init(s) < 0) goto fail; s->aiw_enabled = 1; /* force 420P format because convertion from YUV422 to YUV420P is done in this driver (ugly) */ s->frame_format = VIDEO_PALETTE_YUV420P; } } else { s->video_buf = mmap(0,s->gb_buffers.size,PROT_READ|PROT_WRITE,MAP_SHARED,video_fd,0); if ((unsigned char*)-1 == s->video_buf) { perror("mmap"); goto fail; } s->gb_frame = 0; s->time_frame = av_gettime() * s->frame_rate / s->frame_rate_base; /* start to grab the first frame */ s->gb_buf.frame = s->gb_frame % s->gb_buffers.frames; s->gb_buf.height = height; s->gb_buf.width = width; s->gb_buf.format = pict.palette; ret = ioctl(video_fd, VIDIOCMCAPTURE, &s->gb_buf); if (ret < 0) { if (errno != EAGAIN) { fail1: av_log(s1, AV_LOG_ERROR, "Fatal: grab device does not support suitable format\n"); } else { av_log(s1, AV_LOG_ERROR,"Fatal: grab device does not receive any video signal\n"); } goto fail; } for (j = 1; j < s->gb_buffers.frames; j++) { s->gb_buf.frame = j; ioctl(video_fd, VIDIOCMCAPTURE, &s->gb_buf); } s->frame_format = s->gb_buf.format; s->use_mmap = 1; } switch(s->frame_format) { case VIDEO_PALETTE_YUV420P: frame_size = (width * height * 3) / 2; st->codec->pix_fmt = PIX_FMT_YUV420P; break; case VIDEO_PALETTE_YUV422: frame_size = width * height * 2; st->codec->pix_fmt = PIX_FMT_YUV422; break; case VIDEO_PALETTE_RGB24: frame_size = width * height * 3; st->codec->pix_fmt = PIX_FMT_BGR24; /* NOTE: v4l uses BGR24, not RGB24 ! */ break; case VIDEO_PALETTE_GREY: frame_size = width * height * 1; st->codec->pix_fmt = PIX_FMT_GRAY8; break; default: goto fail; } s->fd = video_fd; s->frame_size = frame_size; st->codec->codec_type = CODEC_TYPE_VIDEO; st->codec->codec_id = CODEC_ID_RAWVIDEO; st->codec->width = width; st->codec->height = height; st->codec->time_base.den = frame_rate; st->codec->time_base.num = frame_rate_base; st->codec->bit_rate = frame_size * 1/av_q2d(st->codec->time_base) * 8; return 0; fail: if (video_fd >= 0) close(video_fd); av_free(st); return AVERROR_IO; }
static int roq_read_packet(AVFormatContext *s, AVPacket *pkt) { RoqDemuxContext *roq = s->priv_data; AVIOContext *pb = s->pb; int ret = 0; unsigned int chunk_size; unsigned int chunk_type; unsigned int codebook_size; unsigned char preamble[RoQ_CHUNK_PREAMBLE_SIZE]; int packet_read = 0; int64_t codebook_offset; while (!packet_read) { if (url_feof(s->pb)) return AVERROR(EIO); /* get the next chunk preamble */ if ((ret = avio_read(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE)) != RoQ_CHUNK_PREAMBLE_SIZE) return AVERROR(EIO); chunk_type = AV_RL16(&preamble[0]); chunk_size = AV_RL32(&preamble[2]); if(chunk_size > INT_MAX) return AVERROR_INVALIDDATA; switch (chunk_type) { case RoQ_INFO: if (!roq->width || !roq->height) { AVStream *st = s->streams[roq->video_stream_index]; if (avio_read(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) != RoQ_CHUNK_PREAMBLE_SIZE) return AVERROR(EIO); st->codec->width = roq->width = AV_RL16(preamble); st->codec->height = roq->height = AV_RL16(preamble + 2); break; } /* don't care about this chunk anymore */ avio_skip(pb, RoQ_CHUNK_PREAMBLE_SIZE); break; case RoQ_QUAD_CODEBOOK: /* packet needs to contain both this codebook and next VQ chunk */ codebook_offset = avio_tell(pb) - RoQ_CHUNK_PREAMBLE_SIZE; codebook_size = chunk_size; avio_skip(pb, codebook_size); if (avio_read(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) != RoQ_CHUNK_PREAMBLE_SIZE) return AVERROR(EIO); chunk_size = AV_RL32(&preamble[2]) + RoQ_CHUNK_PREAMBLE_SIZE * 2 + codebook_size; /* rewind */ avio_seek(pb, codebook_offset, SEEK_SET); /* load up the packet */ ret= av_get_packet(pb, pkt, chunk_size); if (ret != chunk_size) return AVERROR(EIO); pkt->stream_index = roq->video_stream_index; pkt->pts = roq->video_pts++; packet_read = 1; break; case RoQ_SOUND_MONO: case RoQ_SOUND_STEREO: if (roq->audio_stream_index == -1) { AVStream *st = av_new_stream(s, 1); if (!st) return AVERROR(ENOMEM); av_set_pts_info(st, 32, 1, RoQ_AUDIO_SAMPLE_RATE); roq->audio_stream_index = st->index; st->codec->codec_type = AVMEDIA_TYPE_AUDIO; st->codec->codec_id = CODEC_ID_ROQ_DPCM; st->codec->codec_tag = 0; /* no tag */ st->codec->channels = roq->audio_channels = chunk_type == RoQ_SOUND_STEREO ? 2 : 1; st->codec->sample_rate = RoQ_AUDIO_SAMPLE_RATE; st->codec->bits_per_coded_sample = 16; 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; } case RoQ_QUAD_VQ: /* load up the packet */ if (av_new_packet(pkt, chunk_size + RoQ_CHUNK_PREAMBLE_SIZE)) return AVERROR(EIO); /* copy over preamble */ memcpy(pkt->data, preamble, RoQ_CHUNK_PREAMBLE_SIZE); if (chunk_type == RoQ_QUAD_VQ) { pkt->stream_index = roq->video_stream_index; pkt->pts = roq->video_pts++; } else { pkt->stream_index = roq->audio_stream_index; pkt->pts = roq->audio_frame_count; roq->audio_frame_count += (chunk_size / roq->audio_channels); } pkt->pos= avio_tell(pb); ret = avio_read(pb, pkt->data + RoQ_CHUNK_PREAMBLE_SIZE, chunk_size); if (ret != chunk_size) ret = AVERROR(EIO); packet_read = 1; break; default: av_log(s, AV_LOG_ERROR, " unknown RoQ chunk (%04X)\n", chunk_type); return AVERROR_INVALIDDATA; break; } } return ret; }
static int ffm_write_header(AVFormatContext *s) { FFMContext *ffm = s->priv_data; AVStream *st; ByteIOContext *pb = s->pb; AVCodecContext *codec; int bit_rate, i; ffm->packet_size = FFM_PACKET_SIZE; /* header */ put_le32(pb, MKTAG('F', 'F', 'M', '1')); put_be32(pb, ffm->packet_size); /* XXX: store write position in other file ? */ put_be64(pb, ffm->packet_size); /* current write position */ put_be32(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; } put_be32(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 */ put_be32(pb, codec->codec_id); put_byte(pb, codec->codec_type); put_be32(pb, codec->bit_rate); put_be32(pb, st->quality); put_be32(pb, codec->flags); put_be32(pb, codec->flags2); put_be32(pb, codec->debug); /* specific info */ switch(codec->codec_type) { case CODEC_TYPE_VIDEO: put_be32(pb, codec->time_base.num); put_be32(pb, codec->time_base.den); put_be16(pb, codec->width); put_be16(pb, codec->height); put_be16(pb, codec->gop_size); put_be32(pb, codec->pix_fmt); put_byte(pb, codec->qmin); put_byte(pb, codec->qmax); put_byte(pb, codec->max_qdiff); put_be16(pb, (int) (codec->qcompress * 10000.0)); put_be16(pb, (int) (codec->qblur * 10000.0)); put_be32(pb, codec->bit_rate_tolerance); put_strz(pb, codec->rc_eq); put_be32(pb, codec->rc_max_rate); put_be32(pb, codec->rc_min_rate); put_be32(pb, codec->rc_buffer_size); put_be64(pb, av_dbl2int(codec->i_quant_factor)); put_be64(pb, av_dbl2int(codec->b_quant_factor)); put_be64(pb, av_dbl2int(codec->i_quant_offset)); put_be64(pb, av_dbl2int(codec->b_quant_offset)); put_be32(pb, codec->dct_algo); put_be32(pb, codec->strict_std_compliance); put_be32(pb, codec->max_b_frames); put_be32(pb, codec->luma_elim_threshold); put_be32(pb, codec->chroma_elim_threshold); put_be32(pb, codec->mpeg_quant); put_be32(pb, codec->intra_dc_precision); put_be32(pb, codec->me_method); put_be32(pb, codec->mb_decision); put_be32(pb, codec->nsse_weight); put_be32(pb, codec->frame_skip_cmp); put_be64(pb, av_dbl2int(codec->rc_buffer_aggressivity)); put_be32(pb, codec->codec_tag); break; case CODEC_TYPE_AUDIO: put_be32(pb, codec->sample_rate); put_le16(pb, codec->channels); put_le16(pb, codec->frame_size); break; default: return -1; } if (codec->flags & CODEC_FLAG_GLOBAL_HEADER) { put_be32(pb, codec->extradata_size); put_buffer(pb, codec->extradata, codec->extradata_size); } } /* flush until end of block reached */ while ((url_ftell(pb) % ffm->packet_size) != 0) put_byte(pb, 0); put_flush_packet(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->pts = 0; ffm->first_packet = 1; return 0; }
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 */ av_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_avi_metadata_conv, NULL); for (i = 0; *ff_avi_tags[i]; i++) { if ((t = av_dict_get(s->metadata, ff_avi_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; }
static int wsvqa_read_header(AVFormatContext *s, AVFormatParameters *ap) { WsVqaDemuxContext *wsvqa = s->priv_data; AVIOContext *pb = s->pb; AVStream *st; unsigned char *header; unsigned char scratch[VQA_PREAMBLE_SIZE]; unsigned int chunk_tag; unsigned int chunk_size; /* initialize the video decoder stream */ st = av_new_stream(s, 0); if (!st) return AVERROR(ENOMEM); av_set_pts_info(st, 33, 1, VQA_FRAMERATE); wsvqa->video_stream_index = st->index; st->codec->codec_type = AVMEDIA_TYPE_VIDEO; st->codec->codec_id = CODEC_ID_WS_VQA; st->codec->codec_tag = 0; /* no fourcc */ /* skip to the start of the VQA header */ url_fseek(pb, 20, SEEK_SET); /* the VQA header needs to go to the decoder */ st->codec->extradata_size = VQA_HEADER_SIZE; st->codec->extradata = av_mallocz(VQA_HEADER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE); header = (unsigned char *)st->codec->extradata; if (avio_read(pb, st->codec->extradata, VQA_HEADER_SIZE) != VQA_HEADER_SIZE) { av_free(st->codec->extradata); return AVERROR(EIO); } st->codec->width = AV_RL16(&header[6]); st->codec->height = AV_RL16(&header[8]); /* initialize the audio decoder stream for VQA v1 or nonzero samplerate */ if (AV_RL16(&header[24]) || (AV_RL16(&header[0]) == 1 && AV_RL16(&header[2]) == 1)) { st = av_new_stream(s, 0); if (!st) return AVERROR(ENOMEM); av_set_pts_info(st, 33, 1, VQA_FRAMERATE); st->codec->codec_type = AVMEDIA_TYPE_AUDIO; if (AV_RL16(&header[0]) == 1) st->codec->codec_id = CODEC_ID_WESTWOOD_SND1; else st->codec->codec_id = CODEC_ID_ADPCM_IMA_WS; st->codec->codec_tag = 0; /* no tag */ st->codec->sample_rate = AV_RL16(&header[24]); if (!st->codec->sample_rate) st->codec->sample_rate = 22050; st->codec->channels = header[26]; if (!st->codec->channels) st->codec->channels = 1; st->codec->bits_per_coded_sample = 16; st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * st->codec->bits_per_coded_sample / 4; st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample; wsvqa->audio_stream_index = st->index; wsvqa->audio_samplerate = st->codec->sample_rate; wsvqa->audio_channels = st->codec->channels; wsvqa->audio_frame_counter = 0; } /* there are 0 or more chunks before the FINF chunk; iterate until * FINF has been skipped and the file will be ready to be demuxed */ do { if (avio_read(pb, scratch, VQA_PREAMBLE_SIZE) != VQA_PREAMBLE_SIZE) { av_free(st->codec->extradata); return AVERROR(EIO); } chunk_tag = AV_RB32(&scratch[0]); chunk_size = AV_RB32(&scratch[4]); /* catch any unknown header tags, for curiousity */ switch (chunk_tag) { case CINF_TAG: case CINH_TAG: case CIND_TAG: case PINF_TAG: case PINH_TAG: case PIND_TAG: case FINF_TAG: case CMDS_TAG: break; default: av_log (s, AV_LOG_ERROR, " note: unknown chunk seen (%c%c%c%c)\n", scratch[0], scratch[1], scratch[2], scratch[3]); break; } url_fseek(pb, chunk_size, SEEK_CUR); } while (chunk_tag != FINF_TAG); return 0; }
/** * Initialize the x11 grab device demuxer (public device demuxer API). * * @param s1 Context from avformat core * @param ap Parameters from avformat core * @return <ul> * <li>AVERROR(ENOMEM) no memory left</li> * <li>AVERROR(EIO) other failure case</li> * <li>0 success</li> * </ul> */ static int x11grab_read_header(AVFormatContext *s1, AVFormatParameters *ap) { struct x11_grab *x11grab = s1->priv_data; Display *dpy; AVStream *st = NULL; enum PixelFormat input_pixfmt; XImage *image; int x_off = 0; int y_off = 0; int screen; int use_shm; char *dpyname, *offset; int ret = 0; AVRational framerate; dpyname = av_strdup(s1->filename); offset = strchr(dpyname, '+'); if (offset) { sscanf(offset, "%d,%d", &x_off, &y_off); x11grab->draw_mouse = !strstr(offset, "nomouse"); *offset= 0; } if ((ret = av_parse_video_size(&x11grab->width, &x11grab->height, x11grab->video_size)) < 0) { av_log(s1, AV_LOG_ERROR, "Couldn't parse video size.\n"); goto out; } if ((ret = av_parse_video_rate(&framerate, x11grab->framerate)) < 0) { av_log(s1, AV_LOG_ERROR, "Could not parse framerate: %s.\n", x11grab->framerate); goto out; } av_log(s1, AV_LOG_INFO, "device: %s -> display: %s x: %d y: %d width: %d height: %d\n", s1->filename, dpyname, x_off, y_off, x11grab->width, x11grab->height); dpy = XOpenDisplay(dpyname); av_freep(&dpyname); if(!dpy) { av_log(s1, AV_LOG_ERROR, "Could not open X display.\n"); ret = AVERROR(EIO); goto out; } st = av_new_stream(s1, 0); if (!st) { ret = AVERROR(ENOMEM); goto out; } av_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ screen = DefaultScreen(dpy); if (x11grab->follow_mouse) { int screen_w, screen_h; Window w; screen_w = DisplayWidth(dpy, screen); screen_h = DisplayHeight(dpy, screen); XQueryPointer(dpy, RootWindow(dpy, screen), &w, &w, &x_off, &y_off, &ret, &ret, &ret); x_off -= x11grab->width / 2; y_off -= x11grab->height / 2; x_off = FFMIN(FFMAX(x_off, 0), screen_w - x11grab->width); y_off = FFMIN(FFMAX(y_off, 0), screen_h - x11grab->height); av_log(s1, AV_LOG_INFO, "followmouse is enabled, resetting grabbing region to x: %d y: %d\n", x_off, y_off); } use_shm = XShmQueryExtension(dpy); av_log(s1, AV_LOG_INFO, "shared memory extension%s found\n", use_shm ? "" : " not"); if(use_shm) { int scr = XDefaultScreen(dpy); image = XShmCreateImage(dpy, DefaultVisual(dpy, scr), DefaultDepth(dpy, scr), ZPixmap, NULL, &x11grab->shminfo, x11grab->width, x11grab->height); x11grab->shminfo.shmid = shmget(IPC_PRIVATE, image->bytes_per_line * image->height, IPC_CREAT|0777); if (x11grab->shminfo.shmid == -1) { av_log(s1, AV_LOG_ERROR, "Fatal: Can't get shared memory!\n"); ret = AVERROR(ENOMEM); goto out; } x11grab->shminfo.shmaddr = image->data = shmat(x11grab->shminfo.shmid, 0, 0); x11grab->shminfo.readOnly = False; if (!XShmAttach(dpy, &x11grab->shminfo)) { av_log(s1, AV_LOG_ERROR, "Fatal: Failed to attach shared memory!\n"); /* needs some better error subroutine :) */ ret = AVERROR(EIO); goto out; } } else { image = XGetImage(dpy, RootWindow(dpy, screen), x_off,y_off, x11grab->width, x11grab->height, AllPlanes, ZPixmap); } switch (image->bits_per_pixel) { case 8: av_log (s1, AV_LOG_DEBUG, "8 bit palette\n"); input_pixfmt = PIX_FMT_PAL8; break; case 16: if ( image->red_mask == 0xf800 && image->green_mask == 0x07e0 && image->blue_mask == 0x001f ) { av_log (s1, AV_LOG_DEBUG, "16 bit RGB565\n"); input_pixfmt = PIX_FMT_RGB565; } else if (image->red_mask == 0x7c00 && image->green_mask == 0x03e0 && image->blue_mask == 0x001f ) { av_log(s1, AV_LOG_DEBUG, "16 bit RGB555\n"); input_pixfmt = PIX_FMT_RGB555; } else { av_log(s1, AV_LOG_ERROR, "RGB ordering at image depth %i not supported ... aborting\n", image->bits_per_pixel); av_log(s1, AV_LOG_ERROR, "color masks: r 0x%.6lx g 0x%.6lx b 0x%.6lx\n", image->red_mask, image->green_mask, image->blue_mask); ret = AVERROR(EIO); goto out; } break; case 24: if ( image->red_mask == 0xff0000 && image->green_mask == 0x00ff00 && image->blue_mask == 0x0000ff ) { input_pixfmt = PIX_FMT_BGR24; } else if ( image->red_mask == 0x0000ff && image->green_mask == 0x00ff00 && image->blue_mask == 0xff0000 ) { input_pixfmt = PIX_FMT_RGB24; } else { av_log(s1, AV_LOG_ERROR,"rgb ordering at image depth %i not supported ... aborting\n", image->bits_per_pixel); av_log(s1, AV_LOG_ERROR, "color masks: r 0x%.6lx g 0x%.6lx b 0x%.6lx\n", image->red_mask, image->green_mask, image->blue_mask); ret = AVERROR(EIO); goto out; } break; case 32: input_pixfmt = PIX_FMT_RGB32; break; default: av_log(s1, AV_LOG_ERROR, "image depth %i not supported ... aborting\n", image->bits_per_pixel); ret = AVERROR(EINVAL); goto out; } x11grab->frame_size = x11grab->width * x11grab->height * image->bits_per_pixel/8; x11grab->dpy = dpy; x11grab->time_base = (AVRational){framerate.den, framerate.num}; x11grab->time_frame = av_gettime() / av_q2d(x11grab->time_base); x11grab->x_off = x_off; x11grab->y_off = y_off; x11grab->image = image; x11grab->use_shm = use_shm; st->codec->codec_type = AVMEDIA_TYPE_VIDEO; st->codec->codec_id = CODEC_ID_RAWVIDEO; st->codec->width = x11grab->width; st->codec->height = x11grab->height; st->codec->pix_fmt = input_pixfmt; st->codec->time_base = x11grab->time_base; st->codec->bit_rate = x11grab->frame_size * 1/av_q2d(x11grab->time_base) * 8; out: return ret; }
static int avi_write_header(AVFormatContext *s) { AVIContext *avi = s->priv_data; ByteIOContext *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; AVRational temp, dar; int num, den; /* header list */ avi->riff_id = 0; list1 = avi_start_new_riff(avi, pb, "AVI ", "hdrl"); /* avi header */ put_tag(pb, "avih"); put_le32(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 == CODEC_TYPE_VIDEO) video_enc = stream; } nb_frames = 0; if(video_enc){ put_le32(pb, (uint32_t)(INT64_C(1000000) * video_enc->time_base.num / video_enc->time_base.den)); } else { put_le32(pb, 0); } put_le32(pb, bitrate / 8); /* XXX: not quite exact */ put_le32(pb, 0); /* padding */ if (url_is_streamed(pb)) put_le32(pb, AVIF_TRUSTCKTYPE | AVIF_ISINTERLEAVED); /* flags */ else put_le32(pb, AVIF_TRUSTCKTYPE | AVIF_HASINDEX | AVIF_ISINTERLEAVED); /* flags */ avi->frames_hdr_all = url_ftell(pb); /* remember this offset to fill later */ put_le32(pb, nb_frames); /* nb frames, filled later */ put_le32(pb, 0); /* initial frame */ put_le32(pb, s->nb_streams); /* nb streams */ put_le32(pb, 1024 * 1024); /* suggested buffer size */ if(video_enc){ put_le32(pb, video_enc->width); put_le32(pb, video_enc->height); } else { put_le32(pb, 0); put_le32(pb, 0); } put_le32(pb, 0); /* reserved */ put_le32(pb, 0); /* reserved */ put_le32(pb, 0); /* reserved */ put_le32(pb, 0); /* reserved */ /* stream list */ for(i=0;i<n;i++) { list2 = start_tag(pb, "LIST"); put_tag(pb, "strl"); stream = s->streams[i]->codec; /* stream generic header */ strh = start_tag(pb, "strh"); switch(stream->codec_type) { case CODEC_TYPE_VIDEO: put_tag(pb, "vids"); break; case CODEC_TYPE_AUDIO: put_tag(pb, "auds"); break; // case CODEC_TYPE_TEXT : put_tag(pb, "txts"); break; case CODEC_TYPE_DATA : put_tag(pb, "dats"); break; } if(stream->codec_type == CODEC_TYPE_VIDEO) put_le32(pb, stream->codec_tag); else put_le32(pb, 1); put_le32(pb, 0); /* flags */ put_le16(pb, 0); /* priority */ put_le16(pb, 0); /* language */ put_le32(pb, 0); /* initial frame */ ff_parse_specific_params(stream, &au_byterate, &au_ssize, &au_scale); put_le32(pb, au_scale); /* scale */ put_le32(pb, au_byterate); /* rate */ av_set_pts_info(s->streams[i], 64, au_scale, au_byterate); put_le32(pb, 0); /* start */ avi->frames_hdr_strm[i] = url_ftell(pb); /* remember this offset to fill later */ if (url_is_streamed(pb)) put_le32(pb, AVI_MAX_RIFF_SIZE); /* FIXME: this may be broken, but who cares */ else put_le32(pb, 0); /* length, XXX: filled later */ /* suggested buffer size */ //FIXME set at the end to largest chunk if(stream->codec_type == CODEC_TYPE_VIDEO) put_le32(pb, 1024 * 1024); else if(stream->codec_type == CODEC_TYPE_AUDIO) put_le32(pb, 12 * 1024); else put_le32(pb, 0); put_le32(pb, -1); /* quality */ put_le32(pb, au_ssize); /* sample size */ put_le32(pb, 0); put_le16(pb, stream->width); put_le16(pb, stream->height); end_tag(pb, strh); if(stream->codec_type != CODEC_TYPE_DATA){ strf = start_tag(pb, "strf"); switch(stream->codec_type) { case CODEC_TYPE_VIDEO: put_bmp_header(pb, stream, codec_bmp_tags, 0); break; case CODEC_TYPE_AUDIO: if (put_wav_header(pb, stream) < 0) { return -1; } break; default: return -1; } end_tag(pb, strf); } if (!url_is_streamed(pb)) { 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. */ avi->indexes[i].entry = avi->indexes[i].ents_allocated = 0; avi->indexes[i].indx_start = start_tag(pb, "JUNK"); put_le16(pb, 4); /* wLongsPerEntry */ put_byte(pb, 0); /* bIndexSubType (0 == frame index) */ put_byte(pb, 0); /* bIndexType (0 == AVI_INDEX_OF_INDEXES) */ put_le32(pb, 0); /* nEntriesInUse (will fill out later on) */ put_tag(pb, avi_stream2fourcc(&tag[0], i, stream->codec_type)); /* dwChunkId */ put_le64(pb, 0); /* dwReserved[3] put_le32(pb, 0); Must be 0. */ for (j=0; j < AVI_MASTER_INDEX_SIZE * 2; j++) put_le64(pb, 0); end_tag(pb, avi->indexes[i].indx_start); } if( stream->codec_type == CODEC_TYPE_VIDEO && s->streams[i]->sample_aspect_ratio.num>0 && s->streams[i]->sample_aspect_ratio.den>0){ int vprp= start_tag(pb, "vprp"); temp.num = stream->width; temp.den = stream->height;//{stream->width, stream->height}; dar = av_mul_q(s->streams[i]->sample_aspect_ratio, temp); av_reduce(&num, &den, dar.num, dar.den, 0xFFFF); put_le32(pb, 0); //video format = unknown put_le32(pb, 0); //video standard= unknown put_le32(pb, lrintf(1.0/av_q2d(stream->time_base))); put_le32(pb, stream->width ); put_le32(pb, stream->height); put_le16(pb, den); put_le16(pb, num); put_le32(pb, stream->width ); put_le32(pb, stream->height); put_le32(pb, 1); //progressive FIXME put_le32(pb, stream->height); put_le32(pb, stream->width ); put_le32(pb, stream->height); put_le32(pb, stream->width ); put_le32(pb, 0); put_le32(pb, 0); put_le32(pb, 0); put_le32(pb, 0); end_tag(pb, vprp); } end_tag(pb, list2); } if (!url_is_streamed(pb)) { /* AVI could become an OpenDML one, if it grows beyond 2Gb range */ avi->odml_list = start_tag(pb, "JUNK"); put_tag(pb, "odml"); put_tag(pb, "dmlh"); put_le32(pb, 248); for (i = 0; i < 248; i+= 4) put_le32(pb, 0); end_tag(pb, avi->odml_list); } end_tag(pb, list1); list2 = start_tag(pb, "LIST"); put_tag(pb, "INFO"); avi_write_info_tag(pb, "INAM", s->title); avi_write_info_tag(pb, "IART", s->author); avi_write_info_tag(pb, "ICOP", s->copyright); avi_write_info_tag(pb, "ICMT", s->comment); avi_write_info_tag(pb, "IPRD", s->album); avi_write_info_tag(pb, "IGNR", s->genre); if (s->track) { char str_track[4]; snprintf(str_track, 4, "%d", s->track); avi_write_info_tag(pb, "IPRT", str_track); } if(!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)) avi_write_info_tag(pb, "ISFT", LIBAVFORMAT_IDENT); end_tag(pb, list2); /* some padding for easier tag editing */ list2 = start_tag(pb, "JUNK"); for (i = 0; i < 1016; i += 4) put_le32(pb, 0); end_tag(pb, list2); avi->movi_list = start_tag(pb, "LIST"); put_tag(pb, "movi"); put_flush_packet(pb); return 0; }
static int ipmovie_read_header(AVFormatContext *s, AVFormatParameters *ap) { IPMVEContext *ipmovie = s->priv_data; AVIOContext *pb = s->pb; AVPacket pkt; AVStream *st; unsigned char chunk_preamble[CHUNK_PREAMBLE_SIZE]; int chunk_type; uint8_t signature_buffer[sizeof(signature)]; avio_read(pb, signature_buffer, sizeof(signature_buffer)); while (memcmp(signature_buffer, signature, sizeof(signature))) { memmove(signature_buffer, signature_buffer + 1, sizeof(signature_buffer) - 1); signature_buffer[sizeof(signature_buffer) - 1] = avio_r8(pb); if (url_feof(pb)) return AVERROR_EOF; } /* initialize private context members */ ipmovie->video_pts = ipmovie->audio_frame_count = 0; ipmovie->audio_chunk_offset = ipmovie->video_chunk_offset = ipmovie->decode_map_chunk_offset = 0; /* on the first read, this will position the stream at the first chunk */ ipmovie->next_chunk_offset = avio_tell(pb) + 4; /* process the first chunk which should be CHUNK_INIT_VIDEO */ if (process_ipmovie_chunk(ipmovie, pb, &pkt) != CHUNK_INIT_VIDEO) return AVERROR_INVALIDDATA; /* peek ahead to the next chunk-- if it is an init audio chunk, process * it; if it is the first video chunk, this is a silent file */ if (avio_read(pb, chunk_preamble, CHUNK_PREAMBLE_SIZE) != CHUNK_PREAMBLE_SIZE) return AVERROR(EIO); chunk_type = AV_RL16(&chunk_preamble[2]); avio_seek(pb, -CHUNK_PREAMBLE_SIZE, SEEK_CUR); if (chunk_type == CHUNK_VIDEO) ipmovie->audio_type = CODEC_ID_NONE; /* no audio */ else if (process_ipmovie_chunk(ipmovie, pb, &pkt) != CHUNK_INIT_AUDIO) return AVERROR_INVALIDDATA; /* initialize the stream decoders */ st = av_new_stream(s, 0); if (!st) return AVERROR(ENOMEM); av_set_pts_info(st, 63, 1, 1000000); ipmovie->video_stream_index = st->index; st->codec->codec_type = AVMEDIA_TYPE_VIDEO; st->codec->codec_id = CODEC_ID_INTERPLAY_VIDEO; st->codec->codec_tag = 0; /* no fourcc */ st->codec->width = ipmovie->video_width; st->codec->height = ipmovie->video_height; st->codec->bits_per_coded_sample = ipmovie->video_bpp; /* palette considerations */ st->codec->palctrl = &ipmovie->palette_control; if (ipmovie->audio_type) { st = av_new_stream(s, 0); if (!st) return AVERROR(ENOMEM); av_set_pts_info(st, 32, 1, ipmovie->audio_sample_rate); ipmovie->audio_stream_index = st->index; st->codec->codec_type = AVMEDIA_TYPE_AUDIO; st->codec->codec_id = ipmovie->audio_type; st->codec->codec_tag = 0; /* no tag */ st->codec->channels = ipmovie->audio_channels; st->codec->sample_rate = ipmovie->audio_sample_rate; st->codec->bits_per_coded_sample = ipmovie->audio_bits; st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * st->codec->bits_per_coded_sample; if (st->codec->codec_id == CODEC_ID_INTERPLAY_DPCM) st->codec->bit_rate /= 2; st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample; } return 0; }
static int grab_read_header(AVFormatContext *s1, AVFormatParameters *ap) { VideoData *s = s1->priv_data; AVStream *st; int width, height; int video_fd, frame_size; int ret, frame_rate, frame_rate_base; int desired_palette, desired_depth; struct video_tuner tuner; struct video_audio audio; struct video_picture pict; int j; int vformat_num = sizeof(video_formats) / sizeof(video_formats[0]); if (ap->width <= 0 || ap->height <= 0 || ap->time_base.den <= 0) { av_log(s1, AV_LOG_ERROR, "Bad capture size (%dx%d) or wrong time base (%d)\n", ap->width, ap->height, ap->time_base.den); return -1; } width = ap->width; height = ap->height; frame_rate = ap->time_base.den; frame_rate_base = ap->time_base.num; if((unsigned)width > 32767 || (unsigned)height > 32767) { av_log(s1, AV_LOG_ERROR, "Capture size is out of range: %dx%d\n", width, height); return -1; } st = av_new_stream(s1, 0); if (!st) return AVERROR(ENOMEM); av_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ s->width = width; s->height = height; s->frame_rate = frame_rate; s->frame_rate_base = frame_rate_base; video_fd = open(s1->filename, O_RDWR); if (video_fd < 0) { av_log(s1, AV_LOG_ERROR, "%s: %s\n", s1->filename, strerror(errno)); goto fail; } if (ioctl(video_fd,VIDIOCGCAP, &s->video_cap) < 0) { av_log(s1, AV_LOG_ERROR, "VIDIOCGCAP: %s\n", strerror(errno)); goto fail; } if (!(s->video_cap.type & VID_TYPE_CAPTURE)) { av_log(s1, AV_LOG_ERROR, "Fatal: grab device does not handle capture\n"); goto fail; } desired_palette = -1; desired_depth = -1; for (j = 0; j < vformat_num; j++) { if (ap->pix_fmt == video_formats[j].pix_fmt) { desired_palette = video_formats[j].palette; desired_depth = video_formats[j].depth; break; } } /* set tv standard */ if (ap->standard && !ioctl(video_fd, VIDIOCGTUNER, &tuner)) { if (!strcasecmp(ap->standard, "pal")) tuner.mode = VIDEO_MODE_PAL; else if (!strcasecmp(ap->standard, "secam")) tuner.mode = VIDEO_MODE_SECAM; else tuner.mode = VIDEO_MODE_NTSC; ioctl(video_fd, VIDIOCSTUNER, &tuner); } /* unmute audio */ audio.audio = 0; ioctl(video_fd, VIDIOCGAUDIO, &audio); memcpy(&s->audio_saved, &audio, sizeof(audio)); audio.flags &= ~VIDEO_AUDIO_MUTE; ioctl(video_fd, VIDIOCSAUDIO, &audio); ioctl(video_fd, VIDIOCGPICT, &pict); #if 0 printf("v4l: colour=%d hue=%d brightness=%d constrast=%d whiteness=%d\n", pict.colour, pict.hue, pict.brightness, pict.contrast, pict.whiteness); #endif /* try to choose a suitable video format */ pict.palette = desired_palette; pict.depth= desired_depth; if (desired_palette == -1 || (ret = ioctl(video_fd, VIDIOCSPICT, &pict)) < 0) { for (j = 0; j < vformat_num; j++) { pict.palette = video_formats[j].palette; pict.depth = video_formats[j].depth; if (-1 != ioctl(video_fd, VIDIOCSPICT, &pict)) break; } if (j >= vformat_num) goto fail1; } ret = ioctl(video_fd,VIDIOCGMBUF,&s->gb_buffers); if (ret < 0) { /* try to use read based access */ struct video_window win; int val; win.x = 0; win.y = 0; win.width = width; win.height = height; win.chromakey = -1; win.flags = 0; ioctl(video_fd, VIDIOCSWIN, &win); s->frame_format = pict.palette; val = 1; ioctl(video_fd, VIDIOCCAPTURE, &val); s->time_frame = av_gettime() * s->frame_rate / s->frame_rate_base; s->use_mmap = 0; } else { s->video_buf = mmap(0,s->gb_buffers.size,PROT_READ|PROT_WRITE,MAP_SHARED,video_fd,0); if ((unsigned char*)-1 == s->video_buf) { s->video_buf = mmap(0,s->gb_buffers.size,PROT_READ|PROT_WRITE,MAP_PRIVATE,video_fd,0); if ((unsigned char*)-1 == s->video_buf) { av_log(s1, AV_LOG_ERROR, "mmap: %s\n", strerror(errno)); goto fail; } } s->gb_frame = 0; s->time_frame = av_gettime() * s->frame_rate / s->frame_rate_base; /* start to grab the first frame */ s->gb_buf.frame = s->gb_frame % s->gb_buffers.frames; s->gb_buf.height = height; s->gb_buf.width = width; s->gb_buf.format = pict.palette; ret = ioctl(video_fd, VIDIOCMCAPTURE, &s->gb_buf); if (ret < 0) { if (errno != EAGAIN) { fail1: av_log(s1, AV_LOG_ERROR, "Fatal: grab device does not support suitable format\n"); } else { av_log(s1, AV_LOG_ERROR,"Fatal: grab device does not receive any video signal\n"); } goto fail; } for (j = 1; j < s->gb_buffers.frames; j++) { s->gb_buf.frame = j; ioctl(video_fd, VIDIOCMCAPTURE, &s->gb_buf); } s->frame_format = s->gb_buf.format; s->use_mmap = 1; } for (j = 0; j < vformat_num; j++) { if (s->frame_format == video_formats[j].palette) { frame_size = width * height * video_formats[j].depth / 8; st->codec->pix_fmt = video_formats[j].pix_fmt; break; } } if (j >= vformat_num) goto fail; s->fd = video_fd; s->frame_size = frame_size; st->codec->codec_type = CODEC_TYPE_VIDEO; st->codec->codec_id = CODEC_ID_RAWVIDEO; st->codec->width = width; st->codec->height = height; st->codec->time_base.den = frame_rate; st->codec->time_base.num = frame_rate_base; st->codec->bit_rate = frame_size * 1/av_q2d(st->codec->time_base) * 8; return 0; fail: if (video_fd >= 0) close(video_fd); return AVERROR(EIO); }
static int flic_read_header(AVFormatContext *s, AVFormatParameters *ap) { FlicDemuxContext *flic = s->priv_data; AVIOContext *pb = s->pb; unsigned char header[FLIC_HEADER_SIZE]; AVStream *st, *ast; int speed; int magic_number; unsigned char preamble[FLIC_PREAMBLE_SIZE]; flic->frame_number = 0; /* load the whole header and pull out the width and height */ if (avio_read(pb, header, FLIC_HEADER_SIZE) != FLIC_HEADER_SIZE) return AVERROR(EIO); magic_number = AV_RL16(&header[4]); speed = AV_RL32(&header[0x10]); if (speed == 0) speed = FLIC_DEFAULT_SPEED; /* initialize the decoder streams */ st = av_new_stream(s, 0); if (!st) return AVERROR(ENOMEM); flic->video_stream_index = st->index; st->codec->codec_type = AVMEDIA_TYPE_VIDEO; st->codec->codec_id = CODEC_ID_FLIC; st->codec->codec_tag = 0; /* no fourcc */ st->codec->width = AV_RL16(&header[0x08]); st->codec->height = AV_RL16(&header[0x0A]); if (!st->codec->width || !st->codec->height) { /* Ugly hack needed for the following sample: */ /* http://samples.libav.org/fli-flc/fli-bugs/specular.flc */ av_log(s, AV_LOG_WARNING, "File with no specified width/height. Trying 640x480.\n"); st->codec->width = 640; st->codec->height = 480; } /* send over the whole 128-byte FLIC header */ st->codec->extradata_size = FLIC_HEADER_SIZE; st->codec->extradata = av_malloc(FLIC_HEADER_SIZE); memcpy(st->codec->extradata, header, FLIC_HEADER_SIZE); /* peek at the preamble to detect TFTD videos - they seem to always start with an audio chunk */ if (avio_read(pb, preamble, FLIC_PREAMBLE_SIZE) != FLIC_PREAMBLE_SIZE) { av_log(s, AV_LOG_ERROR, "Failed to peek at preamble\n"); return AVERROR(EIO); } avio_seek(pb, -FLIC_PREAMBLE_SIZE, SEEK_CUR); /* Time to figure out the framerate: * If the first preamble's magic number is 0xAAAA then this file is from * X-COM: Terror from the Deep. If on the other hand there is a FLIC chunk * magic number at offset 0x10 assume this file is from Magic Carpet instead. * If neither of the above is true then this is a normal FLIC file. */ if (AV_RL16(&preamble[4]) == FLIC_TFTD_CHUNK_AUDIO) { /* TFTD videos have an extra 22050 Hz 8-bit mono audio stream */ ast = av_new_stream(s, 1); if (!ast) return AVERROR(ENOMEM); flic->audio_stream_index = ast->index; /* all audio frames are the same size, so use the size of the first chunk for block_align */ ast->codec->block_align = AV_RL32(&preamble[0]); ast->codec->codec_type = AVMEDIA_TYPE_AUDIO; ast->codec->codec_id = CODEC_ID_PCM_U8; ast->codec->codec_tag = 0; ast->codec->sample_rate = FLIC_TFTD_SAMPLE_RATE; ast->codec->channels = 1; ast->codec->sample_fmt = AV_SAMPLE_FMT_U8; ast->codec->bit_rate = st->codec->sample_rate * 8; ast->codec->bits_per_coded_sample = 8; ast->codec->channel_layout = AV_CH_LAYOUT_MONO; ast->codec->extradata_size = 0; /* Since the header information is incorrect we have to figure out the * framerate using block_align and the fact that the audio is 22050 Hz. * We usually have two cases: 2205 -> 10 fps and 1470 -> 15 fps */ av_set_pts_info(st, 64, ast->codec->block_align, FLIC_TFTD_SAMPLE_RATE); av_set_pts_info(ast, 64, 1, FLIC_TFTD_SAMPLE_RATE); } else if (AV_RL16(&header[0x10]) == FLIC_CHUNK_MAGIC_1) { av_set_pts_info(st, 64, FLIC_MC_SPEED, 70); /* rewind the stream since the first chunk is at offset 12 */ avio_seek(pb, 12, SEEK_SET); /* send over abbreviated FLIC header chunk */ av_free(st->codec->extradata); st->codec->extradata_size = 12; st->codec->extradata = av_malloc(12); memcpy(st->codec->extradata, header, 12); } else if (magic_number == FLIC_FILE_MAGIC_1) { av_set_pts_info(st, 64, speed, 70); } else if ((magic_number == FLIC_FILE_MAGIC_2) || (magic_number == FLIC_FILE_MAGIC_3)) { av_set_pts_info(st, 64, speed, 1000); } else { av_log(s, AV_LOG_INFO, "Invalid or unsupported magic chunk in file\n"); return AVERROR_INVALIDDATA; } return 0; }
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_seek(pb, 8, SEEK_CUR); // codec_tag used by ByteRun1 decoder to distinguish progressive (PBM) and interlaced (ILBM) content st->codec->codec_tag = avio_rl32(pb); while(!url_feof(pb)) { 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_seek(pb, 12, SEEK_CUR); st->codec->sample_rate = avio_rb16(pb); if (data_size >= 16) { avio_seek(pb, 1, SEEK_CUR); 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_seek(pb, 4, SEEK_CUR); // x, y offset st->codec->bits_per_coded_sample = avio_r8(pb); if (data_size >= 11) { avio_seek(pb, 1, SEEK_CUR); // masking compression = avio_r8(pb); } if (data_size >= 16) { avio_seek(pb, 3, SEEK_CUR); // 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_seek(pb, data_size - (avio_tell(pb) - orig_pos) + (data_size & 1), SEEK_CUR); } 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; }
static int smacker_read_header(AVFormatContext *s, AVFormatParameters *ap) { ByteIOContext *pb = &s->pb; SmackerContext *smk = (SmackerContext *)s->priv_data; AVStream *st, *ast[7]; int i, ret; int tbase; /* read and check header */ smk->magic = get_le32(pb); if (smk->magic != MKTAG('S', 'M', 'K', '2') && smk->magic != MKTAG('S', 'M', 'K', '4')) return -1; smk->width = get_le32(pb); smk->height = get_le32(pb); smk->frames = get_le32(pb); smk->pts_inc = (int32_t)get_le32(pb); smk->flags = get_le32(pb); for(i = 0; i < 7; i++) smk->audio[i] = get_le32(pb); smk->treesize = get_le32(pb); if(smk->treesize >= UINT_MAX/4){ // smk->treesize + 16 must not overflow (this check is probably redundant) av_log(s, AV_LOG_ERROR, "treesize too large\n"); return -1; } //FIXME remove extradata "rebuilding" smk->mmap_size = get_le32(pb); smk->mclr_size = get_le32(pb); smk->full_size = get_le32(pb); smk->type_size = get_le32(pb); for(i = 0; i < 7; i++) smk->rates[i] = get_le32(pb); smk->pad = get_le32(pb); /* setup data */ if(smk->frames > 0xFFFFFF) { av_log(s, AV_LOG_ERROR, "Too many frames: %i\n", smk->frames); return -1; } smk->frm_size = av_malloc(smk->frames * 4); smk->frm_flags = av_malloc(smk->frames); smk->is_ver4 = (smk->magic != MKTAG('S', 'M', 'K', '2')); /* read frame info */ for(i = 0; i < smk->frames; i++) { smk->frm_size[i] = get_le32(pb); } for(i = 0; i < smk->frames; i++) { smk->frm_flags[i] = get_byte(pb); } /* init video codec */ st = av_new_stream(s, 0); if (!st) return -1; smk->videoindex = st->index; st->codec->width = smk->width; st->codec->height = smk->height; st->codec->pix_fmt = PIX_FMT_PAL8; st->codec->codec_type = CODEC_TYPE_VIDEO; st->codec->codec_id = CODEC_ID_SMACKVIDEO; st->codec->codec_tag = smk->magic; /* Smacker uses 100000 as internal timebase */ if(smk->pts_inc < 0) smk->pts_inc = -smk->pts_inc; else smk->pts_inc *= 100; tbase = 100000; av_reduce(&tbase, &smk->pts_inc, tbase, smk->pts_inc, (1UL<<31)-1); av_set_pts_info(st, 33, smk->pts_inc, tbase); /* handle possible audio streams */ for(i = 0; i < 7; i++) { smk->indexes[i] = -1; if((smk->rates[i] & 0xFFFFFF) && !(smk->rates[i] & SMK_AUD_BINKAUD)){ ast[i] = av_new_stream(s, 0); smk->indexes[i] = ast[i]->index; ast[i]->codec->codec_type = CODEC_TYPE_AUDIO; ast[i]->codec->codec_id = (smk->rates[i] & SMK_AUD_PACKED) ? CODEC_ID_SMACKAUDIO : CODEC_ID_PCM_U8; ast[i]->codec->codec_tag = MKTAG('S', 'M', 'K', 'A'); ast[i]->codec->channels = (smk->rates[i] & SMK_AUD_STEREO) ? 2 : 1; ast[i]->codec->sample_rate = smk->rates[i] & 0xFFFFFF; ast[i]->codec->bits_per_sample = (smk->rates[i] & SMK_AUD_16BITS) ? 16 : 8; if(ast[i]->codec->bits_per_sample == 16 && ast[i]->codec->codec_id == CODEC_ID_PCM_U8) ast[i]->codec->codec_id = CODEC_ID_PCM_S16LE; av_set_pts_info(ast[i], 64, 1, ast[i]->codec->sample_rate * ast[i]->codec->channels * ast[i]->codec->bits_per_sample / 8); } } /* load trees to extradata, they will be unpacked by decoder */ st->codec->extradata = av_malloc(smk->treesize + 16); st->codec->extradata_size = smk->treesize + 16; if(!st->codec->extradata){ av_log(s, AV_LOG_ERROR, "Cannot allocate %i bytes of extradata\n", smk->treesize + 16); av_free(smk->frm_size); av_free(smk->frm_flags); return -1; } ret = get_buffer(pb, st->codec->extradata + 16, st->codec->extradata_size - 16); if(ret != st->codec->extradata_size - 16){ av_free(smk->frm_size); av_free(smk->frm_flags); return AVERROR_IO; } ((int32_t*)st->codec->extradata)[0] = le2me_32(smk->mmap_size); ((int32_t*)st->codec->extradata)[1] = le2me_32(smk->mclr_size); ((int32_t*)st->codec->extradata)[2] = le2me_32(smk->full_size); ((int32_t*)st->codec->extradata)[3] = le2me_32(smk->type_size); smk->curstream = -1; smk->nextpos = url_ftell(pb); return 0; }
static int flv_write_header( AVFormatContext *s ) { LogStr("Init"); ByteIOContext *pb = s->pb; FLVContext *flv = s->priv_data; AVCodecContext *audio_enc = NULL, *video_enc = NULL; int i; double framerate = 0.0; int metadata_size_pos, data_size; for (i = 0; i < s->nb_streams; i++) { AVCodecContext *enc = s->streams[i]->codec; if (enc->codec_type == CODEC_TYPE_VIDEO) { if (s->streams[i]->r_frame_rate.den && s->streams[i]->r_frame_rate.num) { framerate = av_q2d(s->streams[i]->r_frame_rate); } else { framerate = 1 / av_q2d(s->streams[i]->codec->time_base); } video_enc = enc; if (enc->codec_tag == 0) { av_log(enc, AV_LOG_ERROR, "video codec not compatible with flv\n"); LogStr("Exit"); return -1; } } else { audio_enc = enc; if (get_audio_flags(enc) < 0) { LogStr("Exit"); return -1; } } av_set_pts_info(s->streams[i], 32, 1, 1000); /* 32 bit pts in ms */ } put_tag(pb, "FLV"); put_byte(pb, 1); put_byte(pb, FLV_HEADER_FLAG_HASAUDIO * !!audio_enc + FLV_HEADER_FLAG_HASVIDEO * !!video_enc); put_be32(pb, 9); put_be32(pb, 0); for (i = 0; i < s->nb_streams; i++) { if (s->streams[i]->codec->codec_tag == 5) { put_byte(pb, 8); // message type put_be24(pb, 0); // include flags put_be24(pb, 0); // time stamp put_be32(pb, 0); // reserved put_be32(pb, 11); // size flv->reserved = 5; } } /* write meta_tag */ put_byte(pb, 18); // tag type META metadata_size_pos = url_ftell(pb); put_be24(pb, 0); // size of data part (sum of all parts below) put_be24(pb, 0); // time stamp put_be32(pb, 0); // reserved /* now data of data_size size */ /* first event name as a string */ put_byte(pb, AMF_DATA_TYPE_STRING); put_amf_string(pb, "onMetaData"); // 12 bytes /* mixed array (hash) with size and string/type/data tuples */ put_byte(pb, AMF_DATA_TYPE_MIXEDARRAY); put_be32(pb, 5 * !!video_enc + 4 * !!audio_enc + 2); // +2 for duration and file size put_amf_string(pb, "duration"); flv->duration_offset = url_ftell(pb); put_amf_double(pb, 0); // delayed write 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, s->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, "audiosamplerate"); put_amf_double(pb, audio_enc->sample_rate); put_amf_string(pb, "audiosamplesize"); put_amf_double(pb, audio_enc->codec_id == CODEC_ID_PCM_S8 ? 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); } put_amf_string(pb, "filesize"); flv->filesize_offset = url_ftell(pb); put_amf_double(pb, 0); // delayed write put_amf_string(pb, ""); put_byte(pb, AMF_END_OF_OBJECT); /* write total size of tag */ data_size = url_ftell(pb) - metadata_size_pos - 10; url_fseek(pb, metadata_size_pos, SEEK_SET); put_be24(pb, data_size); url_fseek(pb, data_size + 10 - 3, SEEK_CUR); put_be32(pb, data_size + 11); for (i = 0; i < s->nb_streams; i++) { AVCodecContext *enc = s->streams[i]->codec; if (enc->codec_id == CODEC_ID_AAC || enc->codec_id == CODEC_ID_H264) { offset_t pos; put_byte(pb, enc->codec_type == CODEC_TYPE_VIDEO ? FLV_TAG_TYPE_VIDEO : FLV_TAG_TYPE_AUDIO); put_be24(pb, 0); // size patched later put_be24(pb, 0); // ts put_byte(pb, 0); // ts ext put_be24(pb, 0); // streamid pos = url_ftell(pb); if (enc->codec_id == CODEC_ID_AAC) { put_byte(pb, get_audio_flags(enc)); put_byte(pb, 0); // AAC sequence header put_buffer(pb, enc->extradata, enc->extradata_size); } else { put_byte(pb, enc->codec_tag | FLV_FRAME_KEY); // flags put_byte(pb, 0); // AVC sequence header put_be24(pb, 0); // composition time ff_isom_write_avcc(pb, enc->extradata, enc->extradata_size); } data_size = url_ftell(pb) - pos; url_fseek(pb, -data_size - 10, SEEK_CUR); put_be24(pb, data_size); url_fseek(pb, data_size + 10 - 3, SEEK_CUR); put_be32(pb, data_size + 11); // previous tag size } } LogStr("Exit"); return 0; }
static int flac_read_header(AVFormatContext *s, AVFormatParameters *ap) { int ret, metadata_last=0, metadata_type, metadata_size, found_streaminfo=0; uint8_t header[4]; uint8_t *buffer=NULL; AVStream *st = av_new_stream(s, 0); if (!st) return AVERROR(ENOMEM); st->codec->codec_type = AVMEDIA_TYPE_AUDIO; st->codec->codec_id = CODEC_ID_FLAC; st->need_parsing = AVSTREAM_PARSE_FULL; /* the parameters will be extracted from the compressed bitstream */ /* if fLaC marker is not found, assume there is no header */ if (avio_rl32(s->pb) != MKTAG('f','L','a','C')) { url_fseek(s->pb, -4, SEEK_CUR); return 0; } /* process metadata blocks */ while (!url_feof(s->pb) && !metadata_last) { avio_read(s->pb, header, 4); ff_flac_parse_block_header(header, &metadata_last, &metadata_type, &metadata_size); switch (metadata_type) { /* allocate and read metadata block for supported types */ case FLAC_METADATA_TYPE_STREAMINFO: case FLAC_METADATA_TYPE_VORBIS_COMMENT: buffer = av_mallocz(metadata_size + FF_INPUT_BUFFER_PADDING_SIZE); if (!buffer) { return AVERROR(ENOMEM); } if (avio_read(s->pb, buffer, metadata_size) != metadata_size) { av_freep(&buffer); return AVERROR(EIO); } break; /* skip metadata block for unsupported types */ default: ret = url_fseek(s->pb, metadata_size, SEEK_CUR); if (ret < 0) return ret; } if (metadata_type == FLAC_METADATA_TYPE_STREAMINFO) { FLACStreaminfo si; /* STREAMINFO can only occur once */ if (found_streaminfo) { av_freep(&buffer); return AVERROR_INVALIDDATA; } if (metadata_size != FLAC_STREAMINFO_SIZE) { av_freep(&buffer); return AVERROR_INVALIDDATA; } found_streaminfo = 1; st->codec->extradata = buffer; st->codec->extradata_size = metadata_size; buffer = NULL; /* get codec params from STREAMINFO header */ ff_flac_parse_streaminfo(st->codec, &si, st->codec->extradata); /* set time base and duration */ if (si.samplerate > 0) { av_set_pts_info(st, 64, 1, si.samplerate); if (si.samples > 0) st->duration = si.samples; } } else { /* STREAMINFO must be the first block */ if (!found_streaminfo) { av_freep(&buffer); return AVERROR_INVALIDDATA; } /* process supported blocks other than STREAMINFO */ if (metadata_type == FLAC_METADATA_TYPE_VORBIS_COMMENT) { if (ff_vorbis_comment(s, &s->metadata, buffer, metadata_size)) { av_log(s, AV_LOG_WARNING, "error parsing VorbisComment metadata\n"); } } av_freep(&buffer); } } return 0; }
static int vfw_read_header(AVFormatContext *s, AVFormatParameters *ap) { struct vfw_ctx *ctx = s->priv_data; AVCodecContext *codec; AVStream *st; int devnum; int bisize; BITMAPINFO *bi; CAPTUREPARMS cparms; DWORD biCompression; WORD biBitCount; int width; int height; int ret; if (!strcmp(s->filename, "list")) { for (devnum = 0; devnum <= 9; devnum++) { char driver_name[256]; char driver_ver[256]; ret = capGetDriverDescription(devnum, driver_name, sizeof(driver_name), driver_ver, sizeof(driver_ver)); if (ret) { av_log(s, AV_LOG_INFO, "Driver %d\n", devnum); av_log(s, AV_LOG_INFO, " %s\n", driver_name); av_log(s, AV_LOG_INFO, " %s\n", driver_ver); } } return AVERROR(EIO); } if(!ap->time_base.den) { av_log(s, AV_LOG_ERROR, "A time base must be specified.\n"); return AVERROR(EIO); } ctx->hwnd = capCreateCaptureWindow(NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, 0); if(!ctx->hwnd) { av_log(s, AV_LOG_ERROR, "Could not create capture window.\n"); return AVERROR(EIO); } /* If atoi fails, devnum==0 and the default device is used */ devnum = atoi(s->filename); ret = SendMessage(ctx->hwnd, WM_CAP_DRIVER_CONNECT, devnum, 0); if(!ret) { av_log(s, AV_LOG_ERROR, "Could not connect to device.\n"); DestroyWindow(ctx->hwnd); return AVERROR(ENODEV); } SendMessage(ctx->hwnd, WM_CAP_SET_OVERLAY, 0, 0); SendMessage(ctx->hwnd, WM_CAP_SET_PREVIEW, 0, 0); ret = SendMessage(ctx->hwnd, WM_CAP_SET_CALLBACK_VIDEOSTREAM, 0, (LPARAM) videostream_cb); if(!ret) { av_log(s, AV_LOG_ERROR, "Could not set video stream callback.\n"); goto fail_io; } SetWindowLongPtr(ctx->hwnd, GWLP_USERDATA, (LONG_PTR) s); st = av_new_stream(s, 0); if(!st) { vfw_read_close(s); return AVERROR(ENOMEM); } /* Set video format */ bisize = SendMessage(ctx->hwnd, WM_CAP_GET_VIDEOFORMAT, 0, 0); if(!bisize) goto fail_io; bi = av_malloc(bisize); if(!bi) { vfw_read_close(s); return AVERROR(ENOMEM); } ret = SendMessage(ctx->hwnd, WM_CAP_GET_VIDEOFORMAT, bisize, (LPARAM) bi); if(!ret) goto fail_bi; dump_bih(s, &bi->bmiHeader); width = ap->width ? ap->width : bi->bmiHeader.biWidth ; height = ap->height ? ap->height : bi->bmiHeader.biHeight; bi->bmiHeader.biWidth = width ; bi->bmiHeader.biHeight = height; if (0) { /* For testing yet unsupported compressions * Copy these values from user-supplied verbose information */ bi->bmiHeader.biWidth = 320; bi->bmiHeader.biHeight = 240; bi->bmiHeader.biPlanes = 1; bi->bmiHeader.biBitCount = 12; bi->bmiHeader.biCompression = MKTAG('I','4','2','0'); bi->bmiHeader.biSizeImage = 115200; dump_bih(s, &bi->bmiHeader); } ret = SendMessage(ctx->hwnd, WM_CAP_SET_VIDEOFORMAT, bisize, (LPARAM) bi); if(!ret) { av_log(s, AV_LOG_ERROR, "Could not set Video Format.\n"); goto fail_bi; } biCompression = bi->bmiHeader.biCompression; biBitCount = bi->bmiHeader.biBitCount; av_free(bi); /* Set sequence setup */ ret = SendMessage(ctx->hwnd, WM_CAP_GET_SEQUENCE_SETUP, sizeof(cparms), (LPARAM) &cparms); if(!ret) goto fail_io; dump_captureparms(s, &cparms); cparms.fYield = 1; // Spawn a background thread cparms.dwRequestMicroSecPerFrame = (ap->time_base.num*1000000) / ap->time_base.den; cparms.fAbortLeftMouse = 0; cparms.fAbortRightMouse = 0; cparms.fCaptureAudio = 0; cparms.vKeyAbort = 0; ret = SendMessage(ctx->hwnd, WM_CAP_SET_SEQUENCE_SETUP, sizeof(cparms), (LPARAM) &cparms); if(!ret) goto fail_io; codec = st->codec; codec->time_base = ap->time_base; codec->codec_type = AVMEDIA_TYPE_VIDEO; codec->width = width; codec->height = height; codec->pix_fmt = vfw_pixfmt(biCompression, biBitCount); if(codec->pix_fmt == PIX_FMT_NONE) { codec->codec_id = vfw_codecid(biCompression); if(codec->codec_id == CODEC_ID_NONE) { av_log(s, AV_LOG_ERROR, "Unknown compression type. " "Please report verbose (-v 9) debug information.\n"); vfw_read_close(s); return AVERROR_PATCHWELCOME; } codec->bits_per_coded_sample = biBitCount; } else { codec->codec_id = CODEC_ID_RAWVIDEO; if(biCompression == BI_RGB) { codec->bits_per_coded_sample = biBitCount; codec->extradata = av_malloc(9 + FF_INPUT_BUFFER_PADDING_SIZE); if (codec->extradata) { codec->extradata_size = 9; memcpy(codec->extradata, "BottomUp", 9); } } } av_set_pts_info(st, 32, 1, 1000); ctx->mutex = CreateMutex(NULL, 0, NULL); if(!ctx->mutex) { av_log(s, AV_LOG_ERROR, "Could not create Mutex.\n" ); goto fail_io; } ctx->event = CreateEvent(NULL, 1, 0, NULL); if(!ctx->event) { av_log(s, AV_LOG_ERROR, "Could not create Event.\n" ); goto fail_io; } ret = SendMessage(ctx->hwnd, WM_CAP_SEQUENCE_NOFILE, 0, 0); if(!ret) { av_log(s, AV_LOG_ERROR, "Could not start capture sequence.\n" ); goto fail_io; } return 0; fail_bi: av_free(bi); fail_io: vfw_read_close(s); return AVERROR(EIO); }
/* aiff input */ static int aiff_read_header(AVFormatContext *s, AVFormatParameters *ap) { int size, filesize; int64_t offset = 0; uint32_t tag; unsigned version = AIFF_C_VERSION1; AVIOContext *pb = s->pb; AVStream * st; AIFFInputContext *aiff = s->priv_data; /* check FORM header */ filesize = get_tag(pb, &tag); if (filesize < 0 || tag != MKTAG('F', 'O', 'R', 'M')) return AVERROR_INVALIDDATA; /* AIFF data type */ tag = avio_rl32(pb); if (tag == MKTAG('A', 'I', 'F', 'F')) /* Got an AIFF file */ version = AIFF; else if (tag != MKTAG('A', 'I', 'F', 'C')) /* An AIFF-C file then */ return AVERROR_INVALIDDATA; filesize -= 4; st = av_new_stream(s, 0); if (!st) return AVERROR(ENOMEM); while (filesize > 0) { /* parse different chunks */ size = get_tag(pb, &tag); if (size < 0) return size; filesize -= size + 8; switch (tag) { case MKTAG('C', 'O', 'M', 'M'): /* Common chunk */ /* Then for the complete header info */ st->nb_frames = get_aiff_header(pb, st->codec, size, version); if (st->nb_frames < 0) return st->nb_frames; if (offset > 0) // COMM is after SSND goto got_sound; break; case MKTAG('F', 'V', 'E', 'R'): /* Version chunk */ version = avio_rb32(pb); break; case MKTAG('N', 'A', 'M', 'E'): /* Sample name chunk */ get_meta(s, "title" , size); break; case MKTAG('A', 'U', 'T', 'H'): /* Author chunk */ get_meta(s, "author" , size); break; case MKTAG('(', 'c', ')', ' '): /* Copyright chunk */ get_meta(s, "copyright", size); break; case MKTAG('A', 'N', 'N', 'O'): /* Annotation chunk */ get_meta(s, "comment" , size); break; case MKTAG('S', 'S', 'N', 'D'): /* Sampled sound chunk */ aiff->data_end = avio_tell(pb) + size; offset = avio_rb32(pb); /* Offset of sound data */ avio_rb32(pb); /* BlockSize... don't care */ offset += avio_tell(pb); /* Compute absolute data offset */ if (st->codec->block_align) /* Assume COMM already parsed */ goto got_sound; if (!pb->seekable) { av_log(s, AV_LOG_ERROR, "file is not seekable\n"); return -1; } avio_skip(pb, size - 8); break; case MKTAG('w', 'a', 'v', 'e'): if ((uint64_t)size > (1<<30)) return -1; st->codec->extradata = av_mallocz(size + FF_INPUT_BUFFER_PADDING_SIZE); if (!st->codec->extradata) return AVERROR(ENOMEM); st->codec->extradata_size = size; avio_read(pb, st->codec->extradata, size); break; default: /* Jump */ if (size & 1) /* Always even aligned */ size++; avio_skip(pb, size); } } if (!st->codec->block_align) { av_log(s, AV_LOG_ERROR, "could not find COMM tag\n"); return -1; } got_sound: /* Now positioned, get the sound data start and end */ if (st->nb_frames) s->file_size = st->nb_frames * st->codec->block_align; av_set_pts_info(st, 64, 1, st->codec->sample_rate); st->start_time = 0; st->duration = st->codec->frame_size ? st->nb_frames * st->codec->frame_size : st->nb_frames; /* Position the stream at the first block */ avio_seek(pb, offset, SEEK_SET); return 0; }
static int flv_write_header(AVFormatContext *s) { AVIOContext *pb = s->pb; FLVContext *flv = s->priv_data; AVCodecContext *audio_enc = NULL, *video_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; if (enc->codec_type == AVMEDIA_TYPE_VIDEO) { if (s->streams[i]->r_frame_rate.den && s->streams[i]->r_frame_rate.num) { framerate = av_q2d(s->streams[i]->r_frame_rate); } else { framerate = 1/av_q2d(s->streams[i]->codec->time_base); } video_enc = enc; if(enc->codec_tag == 0) { av_log(enc, AV_LOG_ERROR, "video codec not compatible with flv\n"); return -1; } } else if (enc->codec_type == AVMEDIA_TYPE_AUDIO) { audio_enc = enc; if(get_audio_flags(enc)<0) return -1; } av_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; } 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); // time stamp 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 + 2; // +2 for duration and file size avio_wb32(pb, metadata_count); put_amf_string(pb, "duration"); flv->duration_offset= avio_tell(pb); put_amf_double(pb, s->duration / AV_TIME_BASE); // fill in the guessed duration, it'll be corrected later if incorrect 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 == 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); } 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 == CODEC_ID_AAC || enc->codec_id == CODEC_ID_H264 || enc->codec_id == 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 == CODEC_ID_AAC) { avio_w8(pb, get_audio_flags(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 nuv_header(AVFormatContext *s, AVFormatParameters *ap) { NUVContext *ctx = s->priv_data; AVIOContext *pb = s->pb; char id_string[12]; double aspect, fps; int is_mythtv, width, height, v_packs, a_packs; int stream_nr = 0; AVStream *vst = NULL, *ast = NULL; avio_read(pb, id_string, 12); is_mythtv = !memcmp(id_string, "MythTVVideo", 12); avio_skip(pb, 5); // version string avio_skip(pb, 3); // padding width = avio_rl32(pb); height = avio_rl32(pb); avio_rl32(pb); // unused, "desiredwidth" avio_rl32(pb); // unused, "desiredheight" avio_r8(pb); // 'P' == progressive, 'I' == interlaced avio_skip(pb, 3); // padding aspect = av_int2dbl(avio_rl64(pb)); if (aspect > 0.9999 && aspect < 1.0001) aspect = 4.0 / 3.0; fps = av_int2dbl(avio_rl64(pb)); // number of packets per stream type, -1 means unknown, e.g. streaming v_packs = avio_rl32(pb); a_packs = avio_rl32(pb); avio_rl32(pb); // text avio_rl32(pb); // keyframe distance (?) if (v_packs) { ctx->v_id = stream_nr++; vst = avformat_new_stream(s, NULL); if (!vst) return AVERROR(ENOMEM); vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; vst->codec->codec_id = CODEC_ID_NUV; vst->codec->width = width; vst->codec->height = height; vst->codec->bits_per_coded_sample = 10; vst->sample_aspect_ratio = av_d2q(aspect * height / width, 10000); vst->r_frame_rate = av_d2q(fps, 60000); av_set_pts_info(vst, 32, 1, 1000); } else ctx->v_id = -1; if (a_packs) { ctx->a_id = stream_nr++; ast = avformat_new_stream(s, NULL); if (!ast) return AVERROR(ENOMEM); ast->codec->codec_type = AVMEDIA_TYPE_AUDIO; ast->codec->codec_id = CODEC_ID_PCM_S16LE; ast->codec->channels = 2; ast->codec->sample_rate = 44100; ast->codec->bit_rate = 2 * 2 * 44100 * 8; ast->codec->block_align = 2 * 2; ast->codec->bits_per_coded_sample = 16; av_set_pts_info(ast, 32, 1, 1000); } else ctx->a_id = -1; get_codec_data(pb, vst, ast, is_mythtv); ctx->rtjpg_video = vst && vst->codec->codec_id == CODEC_ID_NUV; return 0; }
/* write the header (used two times if non streamed) */ static int asf_write_header1(AVFormatContext *s, int64_t file_size, int64_t data_chunk_size) { ASFContext *asf = s->priv_data; ByteIOContext *pb = s->pb; AVMetadataTag *title, *author, *copyright, *comment; 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; title = av_metadata_get(s->metadata, "title" , NULL, 0); author = av_metadata_get(s->metadata, "author" , NULL, 0); copyright = av_metadata_get(s->metadata, "copyright", NULL, 0); comment = av_metadata_get(s->metadata, "comment" , NULL, 0); duration = asf->duration + PREROLL_TIME * 10000; has_title = title || author || copyright || comment; metadata_count = s->metadata ? s->metadata->count : 0; bit_rate = 0; for(n=0;n<s->nb_streams;n++) { enc = s->streams[n]->codec; av_set_pts_info(s->streams[n], 32, 1, 1000); /* 32 bit pts in ms */ bit_rate += enc->bit_rate; } if (asf->is_streamed) { put_chunk(s, 0x4824, 0, 0xc00); /* start of stream (length will be patched later) */ } put_guid(pb, &ff_asf_header); put_le64(pb, -1); /* header length, will be patched after */ put_le32(pb, 3 + has_title + !!metadata_count + s->nb_streams); /* number of chunks in header */ put_byte(pb, 1); /* ??? */ put_byte(pb, 2); /* ??? */ /* file header */ header_offset = url_ftell(pb); hpos = put_header(pb, &ff_asf_file_header); put_guid(pb, &ff_asf_my_guid); put_le64(pb, file_size); file_time = 0; put_le64(pb, unix_to_file_time(file_time)); put_le64(pb, asf->nb_packets); /* number of packets */ put_le64(pb, duration); /* end time stamp (in 100ns units) */ put_le64(pb, asf->duration); /* duration (in 100ns units) */ put_le64(pb, PREROLL_TIME); /* start time stamp */ put_le32(pb, (asf->is_streamed || url_is_streamed(pb)) ? 3 : 2); /* ??? */ put_le32(pb, asf->packet_size); /* packet size */ put_le32(pb, asf->packet_size); /* packet size */ put_le32(pb, bit_rate); /* Nominal data rate in bps */ end_header(pb, hpos); /* unknown headers */ hpos = put_header(pb, &ff_asf_head1_guid); put_guid(pb, &ff_asf_head2_guid); put_le32(pb, 6); put_le16(pb, 0); end_header(pb, hpos); /* title and other infos */ if (has_title) { hpos = put_header(pb, &ff_asf_comment_header); put_le16(pb, title ? 2 * (strlen(title->value ) + 1) : 0); put_le16(pb, author ? 2 * (strlen(author->value ) + 1) : 0); put_le16(pb, copyright ? 2 * (strlen(copyright->value) + 1) : 0); put_le16(pb, comment ? 2 * (strlen(comment->value ) + 1) : 0); put_le16(pb, 0); if (title ) put_str16_nolen(pb, title->value ); if (author ) put_str16_nolen(pb, author->value ); if (copyright) put_str16_nolen(pb, copyright->value); if (comment ) put_str16_nolen(pb, comment->value ); end_header(pb, hpos); } if (metadata_count) { AVMetadataTag *tag = NULL; hpos = put_header(pb, &ff_asf_extended_content_header); put_le16(pb, metadata_count); while ((tag = av_metadata_get(s->metadata, "", tag, AV_METADATA_IGNORE_SUFFIX))) { put_le16(pb, 2*(strlen(tag->key) + 3) + 1); put_le16(pb, 'W'); put_le16(pb, 'M'); put_le16(pb, '/'); put_str16_nolen(pb, tag->key); put_le16(pb, 0); put_le16(pb, 2*strlen(tag->value) + 1); put_str16_nolen(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 CODEC_TYPE_AUDIO: wav_extra_size = 0; extra_size = 18 + wav_extra_size; extra_size2 = 8; break; default: case CODEC_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 == CODEC_TYPE_AUDIO) { put_guid(pb, &ff_asf_audio_stream); put_guid(pb, &ff_asf_audio_conceal_spread); } else { put_guid(pb, &ff_asf_video_stream); put_guid(pb, &ff_asf_video_conceal_none); } put_le64(pb, 0); /* ??? */ es_pos = url_ftell(pb); put_le32(pb, extra_size); /* wav header len */ put_le32(pb, extra_size2); /* additional data len */ put_le16(pb, n + 1); /* stream number */ put_le32(pb, 0); /* ??? */ if (enc->codec_type == CODEC_TYPE_AUDIO) { /* WAVEFORMATEX header */ int wavsize = put_wav_header(pb, enc); if ((enc->codec_id != CODEC_ID_MP3) && (enc->codec_id != CODEC_ID_MP2) && (enc->codec_id != CODEC_ID_ADPCM_IMA_WAV) && (enc->extradata_size==0)) { wavsize += 2; put_le16(pb, 0); } if (wavsize < 0) return -1; if (wavsize != extra_size) { cur_pos = url_ftell(pb); url_fseek(pb, es_pos, SEEK_SET); put_le32(pb, wavsize); /* wav header len */ url_fseek(pb, cur_pos, SEEK_SET); } /* ERROR Correction */ put_byte(pb, 0x01); if(enc->codec_id == CODEC_ID_ADPCM_G726 || !enc->block_align){ put_le16(pb, 0x0190); put_le16(pb, 0x0190); }else{ put_le16(pb, enc->block_align); put_le16(pb, enc->block_align); } put_le16(pb, 0x01); put_byte(pb, 0x00); } else { put_le32(pb, enc->width); put_le32(pb, enc->height); put_byte(pb, 2); /* ??? */ put_le16(pb, 40 + enc->extradata_size); /* size */ /* BITMAPINFOHEADER header */ put_bmp_header(pb, enc, codec_bmp_tags, 1); } end_header(pb, hpos); } /* media comments */ hpos = put_header(pb, &ff_asf_codec_comment_header); put_guid(pb, &ff_asf_codec_comment1_header); put_le32(pb, s->nb_streams); for(n=0;n<s->nb_streams;n++) { AVCodec *p; enc = s->streams[n]->codec; p = avcodec_find_encoder(enc->codec_id); if(enc->codec_type == CODEC_TYPE_AUDIO) put_le16(pb, 2); else if(enc->codec_type == CODEC_TYPE_VIDEO) put_le16(pb, 1); else put_le16(pb, -1); if(enc->codec_id == CODEC_ID_WMAV2) put_str16(pb, "Windows Media Audio V8"); else put_str16(pb, p ? p->name : enc->codec_name); put_le16(pb, 0); /* no parameters */ /* id */ if (enc->codec_type == CODEC_TYPE_AUDIO) { put_le16(pb, 2); put_le16(pb, enc->codec_tag); } else { put_le16(pb, 4); put_le32(pb, enc->codec_tag); } if(!enc->codec_tag) return -1; } end_header(pb, hpos); /* patch the header size fields */ cur_pos = url_ftell(pb); header_size = cur_pos - header_offset; if (asf->is_streamed) { header_size += 8 + 30 + 50; url_fseek(pb, header_offset - 10 - 30, SEEK_SET); put_le16(pb, header_size); url_fseek(pb, header_offset - 2 - 30, SEEK_SET); put_le16(pb, header_size); header_size -= 8 + 30 + 50; } header_size += 24 + 6; url_fseek(pb, header_offset - 14, SEEK_SET); put_le64(pb, header_size); url_fseek(pb, cur_pos, SEEK_SET); /* movie chunk, followed by packets of packet_size */ asf->data_offset = cur_pos; put_guid(pb, &ff_asf_data_header); put_le64(pb, data_chunk_size); put_guid(pb, &ff_asf_my_guid); put_le64(pb, asf->nb_packets); /* nb packets */ put_byte(pb, 1); /* ??? */ put_byte(pb, 1); /* ??? */ return 0; }