/* Returns the number of sound data frames or negative on error */ static unsigned int get_aiff_header(AVIOContext *pb, AVCodecContext *codec, int size, unsigned version) { int exp; uint64_t val; double sample_rate; unsigned int num_frames; if (size & 1) size++; codec->codec_type = AVMEDIA_TYPE_AUDIO; codec->channels = avio_rb16(pb); num_frames = avio_rb32(pb); codec->bits_per_coded_sample = avio_rb16(pb); exp = avio_rb16(pb); val = avio_rb64(pb); sample_rate = ldexp(val, exp - 16383 - 63); codec->sample_rate = sample_rate; size -= 18; /* Got an AIFF-C? */ if (version == AIFF_C_VERSION1) { codec->codec_tag = avio_rl32(pb); codec->codec_id = ff_codec_get_id(ff_codec_aiff_tags, codec->codec_tag); switch (codec->codec_id) { case CODEC_ID_PCM_S16BE: codec->codec_id = aiff_codec_get_id(codec->bits_per_coded_sample); codec->bits_per_coded_sample = av_get_bits_per_sample(codec->codec_id); break; case CODEC_ID_ADPCM_IMA_QT: codec->block_align = 34*codec->channels; codec->frame_size = 64; break; case CODEC_ID_MACE3: codec->block_align = 2*codec->channels; codec->frame_size = 6; break; case CODEC_ID_MACE6: codec->block_align = 1*codec->channels; codec->frame_size = 6; break; case CODEC_ID_GSM: codec->block_align = 33; codec->frame_size = 160; break; case CODEC_ID_QCELP: codec->block_align = 35; codec->frame_size= 160; break; default: break; } size -= 4; } else { /* Need the codec type */ codec->codec_id = aiff_codec_get_id(codec->bits_per_coded_sample); codec->bits_per_coded_sample = av_get_bits_per_sample(codec->codec_id); } /* Block align needs to be computed in all cases, as the definition * is specific to applications -> here we use the WAVE format definition */ if (!codec->block_align) codec->block_align = (codec->bits_per_coded_sample * codec->channels) >> 3; codec->bit_rate = (codec->frame_size ? codec->sample_rate/codec->frame_size : codec->sample_rate) * (codec->block_align << 3); /* Chunk is over */ if (size) avio_skip(pb, size); return num_frames; }
static int ffm_read_header(AVFormatContext *s) { FFMContext *ffm = s->priv_data; AVStream *st; AVIOContext *pb = s->pb; AVCodecContext *codec; int i, nb_streams; uint32_t tag; /* header */ tag = avio_rl32(pb); if (tag != MKTAG('F', 'F', 'M', '1')) goto fail; ffm->packet_size = avio_rb32(pb); if (ffm->packet_size != FFM_PACKET_SIZE) goto fail; ffm->write_index = avio_rb64(pb); /* get also filesize */ if (pb->seekable) { ffm->file_size = avio_size(pb); if (ffm->write_index) adjust_write_index(s); } else { ffm->file_size = (UINT64_C(1) << 63) - 1; } nb_streams = avio_rb32(pb); avio_rb32(pb); /* total bitrate */ /* read each stream */ for(i=0;i<nb_streams;i++) { char rc_eq_buf[128]; st = avformat_new_stream(s, NULL); if (!st) goto fail; avpriv_set_pts_info(st, 64, 1, 1000000); codec = st->codec; /* generic info */ codec->codec_id = avio_rb32(pb); codec->codec_type = avio_r8(pb); /* codec_type */ codec->bit_rate = avio_rb32(pb); codec->flags = avio_rb32(pb); codec->flags2 = avio_rb32(pb); codec->debug = avio_rb32(pb); /* specific info */ switch(codec->codec_type) { case AVMEDIA_TYPE_VIDEO: codec->time_base.num = avio_rb32(pb); codec->time_base.den = avio_rb32(pb); codec->width = avio_rb16(pb); codec->height = avio_rb16(pb); codec->gop_size = avio_rb16(pb); codec->pix_fmt = avio_rb32(pb); codec->qmin = avio_r8(pb); codec->qmax = avio_r8(pb); codec->max_qdiff = avio_r8(pb); codec->qcompress = avio_rb16(pb) / 10000.0; codec->qblur = avio_rb16(pb) / 10000.0; codec->bit_rate_tolerance = avio_rb32(pb); avio_get_str(pb, INT_MAX, rc_eq_buf, sizeof(rc_eq_buf)); codec->rc_eq = av_strdup(rc_eq_buf); codec->rc_max_rate = avio_rb32(pb); codec->rc_min_rate = avio_rb32(pb); codec->rc_buffer_size = avio_rb32(pb); codec->i_quant_factor = av_int2double(avio_rb64(pb)); codec->b_quant_factor = av_int2double(avio_rb64(pb)); codec->i_quant_offset = av_int2double(avio_rb64(pb)); codec->b_quant_offset = av_int2double(avio_rb64(pb)); codec->dct_algo = avio_rb32(pb); codec->strict_std_compliance = avio_rb32(pb); codec->max_b_frames = avio_rb32(pb); codec->mpeg_quant = avio_rb32(pb); codec->intra_dc_precision = avio_rb32(pb); codec->me_method = avio_rb32(pb); codec->mb_decision = avio_rb32(pb); codec->nsse_weight = avio_rb32(pb); codec->frame_skip_cmp = avio_rb32(pb); codec->rc_buffer_aggressivity = av_int2double(avio_rb64(pb)); codec->codec_tag = avio_rb32(pb); codec->thread_count = avio_r8(pb); codec->coder_type = avio_rb32(pb); codec->me_cmp = avio_rb32(pb); codec->me_subpel_quality = avio_rb32(pb); codec->me_range = avio_rb32(pb); codec->keyint_min = avio_rb32(pb); codec->scenechange_threshold = avio_rb32(pb); codec->b_frame_strategy = avio_rb32(pb); codec->qcompress = av_int2double(avio_rb64(pb)); codec->qblur = av_int2double(avio_rb64(pb)); codec->max_qdiff = avio_rb32(pb); codec->refs = avio_rb32(pb); break; case AVMEDIA_TYPE_AUDIO: codec->sample_rate = avio_rb32(pb); codec->channels = avio_rl16(pb); codec->frame_size = avio_rl16(pb); break; default: goto fail; } if (codec->flags & CODEC_FLAG_GLOBAL_HEADER) { codec->extradata_size = avio_rb32(pb); codec->extradata = av_malloc(codec->extradata_size); if (!codec->extradata) return AVERROR(ENOMEM); avio_read(pb, codec->extradata, codec->extradata_size); } } /* get until end of block reached */ while ((avio_tell(pb) % ffm->packet_size) != 0) avio_r8(pb); /* init packet demux */ ffm->packet_ptr = ffm->packet; ffm->packet_end = ffm->packet; ffm->frame_offset = 0; ffm->dts = 0; ffm->read_state = READ_HEADER; ffm->first_packet = 1; return 0; fail: ffm_close(s); return -1; }
static int sox_read_header(AVFormatContext *s) { AVIOContext *pb = s->pb; unsigned header_size, comment_size; double sample_rate, sample_rate_frac; AVStream *st; st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); st->codec->codec_type = AVMEDIA_TYPE_AUDIO; if (avio_rl32(pb) == SOX_TAG) { st->codec->codec_id = CODEC_ID_PCM_S32LE; header_size = avio_rl32(pb); avio_skip(pb, 8); /* sample count */ sample_rate = av_int2double(avio_rl64(pb)); st->codec->channels = avio_rl32(pb); comment_size = avio_rl32(pb); } else { st->codec->codec_id = CODEC_ID_PCM_S32BE; header_size = avio_rb32(pb); avio_skip(pb, 8); /* sample count */ sample_rate = av_int2double(avio_rb64(pb)); st->codec->channels = avio_rb32(pb); comment_size = avio_rb32(pb); } if (comment_size > 0xFFFFFFFFU - SOX_FIXED_HDR - 4U) { av_log(s, AV_LOG_ERROR, "invalid comment size (%u)\n", comment_size); return -1; } if (sample_rate <= 0 || sample_rate > INT_MAX) { av_log(s, AV_LOG_ERROR, "invalid sample rate (%f)\n", sample_rate); return -1; } sample_rate_frac = sample_rate - floor(sample_rate); if (sample_rate_frac) av_log(s, AV_LOG_WARNING, "truncating fractional part of sample rate (%f)\n", sample_rate_frac); if ((header_size + 4) & 7 || header_size < SOX_FIXED_HDR + comment_size || st->codec->channels > 65535) /* Reserve top 16 bits */ { av_log(s, AV_LOG_ERROR, "invalid header\n"); return -1; } if (comment_size && comment_size < UINT_MAX) { char *comment = av_malloc(comment_size+1); if(!comment) return AVERROR(ENOMEM); if (avio_read(pb, comment, comment_size) != comment_size) { av_freep(&comment); return AVERROR(EIO); } comment[comment_size] = 0; av_dict_set(&s->metadata, "comment", comment, AV_DICT_DONT_STRDUP_VAL); } avio_skip(pb, header_size - SOX_FIXED_HDR - comment_size); st->codec->sample_rate = sample_rate; st->codec->bits_per_coded_sample = 32; st->codec->bit_rate = st->codec->sample_rate * st->codec->bits_per_coded_sample * st->codec->channels; st->codec->block_align = st->codec->bits_per_coded_sample * st->codec->channels / 8; avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); return 0; }
static int read_header(AVFormatContext *s) { AVIOContext *pb = s->pb; CaffContext *caf = s->priv_data; AVStream *st; uint32_t tag = 0; int found_data, ret; int64_t size; avio_skip(pb, 8); /* magic, version, file flags */ /* audio description chunk */ if (avio_rb32(pb) != MKBETAG('d','e','s','c')) { av_log(s, AV_LOG_ERROR, "desc chunk not present\n"); return AVERROR_INVALIDDATA; } size = avio_rb64(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 (!pb->eof_reached) { /* stop at data chunk if seeking is not supported or data chunk size is unknown */ if (found_data && (caf->data_size < 0 || !pb->seekable)) break; tag = avio_rb32(pb); size = avio_rb64(pb); if (pb->eof_reached) break; switch (tag) { case MKBETAG('d','a','t','a'): avio_skip(pb, 4); /* edit count */ caf->data_start = avio_tell(pb); caf->data_size = size < 0 ? -1 : size - 4; if (caf->data_size > 0 && pb->seekable) avio_skip(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; avio_skip(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; } avpriv_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) avio_seek(pb, caf->data_start, SEEK_SET); return 0; }
/* Returns the number of sound data frames or negative on error */ static unsigned int get_aiff_header(AVFormatContext *s, int size, unsigned version) { AVIOContext *pb = s->pb; AVCodecContext *codec = s->streams[0]->codec; AIFFInputContext *aiff = s->priv_data; int exp; uint64_t val; double sample_rate; unsigned int num_frames; if (size & 1) size++; codec->codec_type = AVMEDIA_TYPE_AUDIO; codec->channels = avio_rb16(pb); num_frames = avio_rb32(pb); codec->bits_per_coded_sample = avio_rb16(pb); exp = avio_rb16(pb); val = avio_rb64(pb); sample_rate = ldexp(val, exp - 16383 - 63); codec->sample_rate = sample_rate; size -= 18; /* get codec id for AIFF-C */ if (version == AIFF_C_VERSION1) { codec->codec_tag = avio_rl32(pb); codec->codec_id = ff_codec_get_id(ff_codec_aiff_tags, codec->codec_tag); size -= 4; } if (version != AIFF_C_VERSION1 || codec->codec_id == AV_CODEC_ID_PCM_S16BE) { codec->codec_id = aiff_codec_get_id(codec->bits_per_coded_sample); codec->bits_per_coded_sample = av_get_bits_per_sample(codec->codec_id); aiff->block_duration = 1; } else { switch (codec->codec_id) { case AV_CODEC_ID_PCM_F32BE: case AV_CODEC_ID_PCM_F64BE: case AV_CODEC_ID_PCM_S16LE: case AV_CODEC_ID_PCM_ALAW: case AV_CODEC_ID_PCM_MULAW: aiff->block_duration = 1; break; case AV_CODEC_ID_ADPCM_IMA_QT: codec->block_align = 34*codec->channels; break; case AV_CODEC_ID_MACE3: codec->block_align = 2*codec->channels; break; case AV_CODEC_ID_MACE6: codec->block_align = 1*codec->channels; break; case AV_CODEC_ID_GSM: codec->block_align = 33; break; default: aiff->block_duration = 1; break; } if (codec->block_align > 0) aiff->block_duration = av_get_audio_frame_duration(codec, codec->block_align); } /* Block align needs to be computed in all cases, as the definition * is specific to applications -> here we use the WAVE format definition */ if (!codec->block_align) codec->block_align = (av_get_bits_per_sample(codec->codec_id) * codec->channels) >> 3; if (aiff->block_duration) { codec->bit_rate = codec->sample_rate * (codec->block_align << 3) / aiff->block_duration; } /* Chunk is over */ if (size) avio_skip(pb, size); return num_frames; }
static int apng_read_header(AVFormatContext *s) { APNGDemuxContext *ctx = s->priv_data; AVIOContext *pb = s->pb; uint32_t len, tag; AVStream *st; int ret = AVERROR_INVALIDDATA, acTL_found = 0; /* verify PNGSIG */ if (avio_rb64(pb) != PNGSIG) return ret; /* parse IHDR (must be first chunk) */ len = avio_rb32(pb); tag = avio_rl32(pb); if (len != 13 || tag != MKTAG('I', 'H', 'D', 'R')) return ret; st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); st->codec->codec_type = AVMEDIA_TYPE_VIDEO; st->codec->codec_id = AV_CODEC_ID_APNG; st->codec->width = avio_rb32(pb); st->codec->height = avio_rb32(pb); if ((ret = av_image_check_size(st->codec->width, st->codec->height, 0, s)) < 0) return ret; /* extradata will contain every chunk up to the first fcTL (excluded) */ st->codec->extradata = av_malloc(len + 12 + FF_INPUT_BUFFER_PADDING_SIZE); if (!st->codec->extradata) return AVERROR(ENOMEM); st->codec->extradata_size = len + 12; AV_WB32(st->codec->extradata, len); AV_WL32(st->codec->extradata+4, tag); AV_WB32(st->codec->extradata+8, st->codec->width); AV_WB32(st->codec->extradata+12, st->codec->height); if ((ret = avio_read(pb, st->codec->extradata+16, 9)) < 0) goto fail; while (!avio_feof(pb)) { if (acTL_found && ctx->num_play != 1) { int64_t size = avio_size(pb); int64_t offset = avio_tell(pb); if (size < 0) { ret = size; goto fail; } else if (offset < 0) { ret = offset; goto fail; } else if ((ret = ffio_ensure_seekback(pb, size - offset)) < 0) { av_log(s, AV_LOG_WARNING, "Could not ensure seekback, will not loop\n"); ctx->num_play = 1; } } if ((ctx->num_play == 1 || !acTL_found) && ((ret = ffio_ensure_seekback(pb, 4 /* len */ + 4 /* tag */)) < 0)) goto fail; len = avio_rb32(pb); if (len > 0x7fffffff) { ret = AVERROR_INVALIDDATA; goto fail; } tag = avio_rl32(pb); switch (tag) { case MKTAG('a', 'c', 'T', 'L'): if ((ret = avio_seek(pb, -8, SEEK_CUR)) < 0 || (ret = append_extradata(st->codec, pb, len + 12)) < 0) goto fail; acTL_found = 1; ctx->num_frames = AV_RB32(st->codec->extradata + ret + 8); ctx->num_play = AV_RB32(st->codec->extradata + ret + 12); av_log(s, AV_LOG_DEBUG, "num_frames: %"PRIu32", num_play: %"PRIu32"\n", ctx->num_frames, ctx->num_play); break; case MKTAG('f', 'c', 'T', 'L'): if (!acTL_found) { ret = AVERROR_INVALIDDATA; goto fail; } if ((ret = avio_seek(pb, -8, SEEK_CUR)) < 0) goto fail; return 0; default: if ((ret = avio_seek(pb, -8, SEEK_CUR)) < 0 || (ret = append_extradata(st->codec, pb, len + 12)) < 0) goto fail; } } fail: if (st->codec->extradata_size) { av_freep(&st->codec->extradata); st->codec->extradata_size = 0; } return ret; }
static int ffm2_read_header(AVFormatContext *s) { FFMContext *ffm = s->priv_data; AVStream *st; AVIOContext *pb = s->pb; AVCodecContext *codec; ffm->packet_size = avio_rb32(pb); if (ffm->packet_size != FFM_PACKET_SIZE) goto fail; ffm->write_index = avio_rb64(pb); /* get also filesize */ if (pb->seekable) { ffm->file_size = avio_size(pb); if (ffm->write_index && 0) adjust_write_index(s); } else { ffm->file_size = (UINT64_C(1) << 63) - 1; } while(!url_feof(pb)) { unsigned id = avio_rb32(pb); unsigned size = avio_rb32(pb); int64_t next = avio_tell(pb) + size; char rc_eq_buf[128]; if(!id) break; switch(id) { case MKBETAG('M', 'A', 'I', 'N'): avio_rb32(pb); /* nb_streams */ avio_rb32(pb); /* total bitrate */ break; case MKBETAG('C', 'O', 'M', 'M'): st = avformat_new_stream(s, NULL); if (!st) goto fail; avpriv_set_pts_info(st, 64, 1, 1000000); codec = st->codec; /* generic info */ codec->codec_id = avio_rb32(pb); codec->codec_type = avio_r8(pb); codec->bit_rate = avio_rb32(pb); codec->flags = avio_rb32(pb); codec->flags2 = avio_rb32(pb); codec->debug = avio_rb32(pb); if (codec->flags & CODEC_FLAG_GLOBAL_HEADER) { if (ff_get_extradata(codec, pb, avio_rb32(pb)) < 0) return AVERROR(ENOMEM); } avio_seek(pb, next, SEEK_SET); id = avio_rb32(pb); size = avio_rb32(pb); next = avio_tell(pb) + size; switch(id) { case MKBETAG('S', 'T', 'V', 'I'): codec->time_base.num = avio_rb32(pb); codec->time_base.den = avio_rb32(pb); codec->width = avio_rb16(pb); codec->height = avio_rb16(pb); codec->gop_size = avio_rb16(pb); codec->pix_fmt = avio_rb32(pb); codec->qmin = avio_r8(pb); codec->qmax = avio_r8(pb); codec->max_qdiff = avio_r8(pb); codec->qcompress = avio_rb16(pb) / 10000.0; codec->qblur = avio_rb16(pb) / 10000.0; codec->bit_rate_tolerance = avio_rb32(pb); avio_get_str(pb, INT_MAX, rc_eq_buf, sizeof(rc_eq_buf)); codec->rc_eq = av_strdup(rc_eq_buf); codec->rc_max_rate = avio_rb32(pb); codec->rc_min_rate = avio_rb32(pb); codec->rc_buffer_size = avio_rb32(pb); codec->i_quant_factor = av_int2double(avio_rb64(pb)); codec->b_quant_factor = av_int2double(avio_rb64(pb)); codec->i_quant_offset = av_int2double(avio_rb64(pb)); codec->b_quant_offset = av_int2double(avio_rb64(pb)); codec->dct_algo = avio_rb32(pb); codec->strict_std_compliance = avio_rb32(pb); codec->max_b_frames = avio_rb32(pb); codec->mpeg_quant = avio_rb32(pb); codec->intra_dc_precision = avio_rb32(pb); codec->me_method = avio_rb32(pb); codec->mb_decision = avio_rb32(pb); codec->nsse_weight = avio_rb32(pb); codec->frame_skip_cmp = avio_rb32(pb); codec->rc_buffer_aggressivity = av_int2double(avio_rb64(pb)); codec->codec_tag = avio_rb32(pb); codec->thread_count = avio_r8(pb); codec->coder_type = avio_rb32(pb); codec->me_cmp = avio_rb32(pb); codec->me_subpel_quality = avio_rb32(pb); codec->me_range = avio_rb32(pb); codec->keyint_min = avio_rb32(pb); codec->scenechange_threshold = avio_rb32(pb); codec->b_frame_strategy = avio_rb32(pb); codec->qcompress = av_int2double(avio_rb64(pb)); codec->qblur = av_int2double(avio_rb64(pb)); codec->max_qdiff = avio_rb32(pb); codec->refs = avio_rb32(pb); break; case MKBETAG('S', 'T', 'A', 'U'): codec->sample_rate = avio_rb32(pb); codec->channels = avio_rl16(pb); codec->frame_size = avio_rl16(pb); break; } break; } avio_seek(pb, next, SEEK_SET); } /* get until end of block reached */ while ((avio_tell(pb) % ffm->packet_size) != 0) avio_r8(pb); /* init packet demux */ ffm->packet_ptr = ffm->packet; ffm->packet_end = ffm->packet; ffm->frame_offset = 0; ffm->dts = 0; ffm->read_state = READ_HEADER; ffm->first_packet = 1; return 0; fail: ffm_close(s); return -1; }
/* first is true if we read the frame header */ static int ffm_read_data(AVFormatContext *s, uint8_t *buf, int size, int header) { FFMContext *ffm = s->priv_data; AVIOContext *pb = s->pb; int len, fill_size, size1, frame_offset, id; size1 = size; while (size > 0) { redo: len = ffm->packet_end - ffm->packet_ptr; if (len < 0) return -1; if (len > size) len = size; if (len == 0) { if (avio_tell(pb) == ffm->file_size) avio_seek(pb, ffm->packet_size, SEEK_SET); retry_read: if (pb->buffer_size != ffm->packet_size) { int64_t tell = avio_tell(pb); ffio_set_buf_size(pb, ffm->packet_size); avio_seek(pb, tell, SEEK_SET); } id = avio_rb16(pb); /* PACKET_ID */ if (id != PACKET_ID) if (ffm_resync(s, id) < 0) return -1; fill_size = avio_rb16(pb); ffm->dts = avio_rb64(pb); frame_offset = avio_rb16(pb); avio_read(pb, ffm->packet, ffm->packet_size - FFM_HEADER_SIZE); ffm->packet_end = ffm->packet + (ffm->packet_size - FFM_HEADER_SIZE - fill_size); if (ffm->packet_end < ffm->packet || frame_offset < 0) return -1; /* if first packet or resynchronization packet, we must handle it specifically */ if (ffm->first_packet || (frame_offset & 0x8000)) { if (!frame_offset) { /* This packet has no frame headers in it */ if (avio_tell(pb) >= ffm->packet_size * 3LL) { avio_seek(pb, -ffm->packet_size * 2LL, SEEK_CUR); goto retry_read; } /* This is bad, we cannot find a valid frame header */ return 0; } ffm->first_packet = 0; if ((frame_offset & 0x7fff) < FFM_HEADER_SIZE) return -1; ffm->packet_ptr = ffm->packet + (frame_offset & 0x7fff) - FFM_HEADER_SIZE; if (!header) break; } else { ffm->packet_ptr = ffm->packet; } goto redo; } memcpy(buf, ffm->packet_ptr, len); buf += len; ffm->packet_ptr += len; size -= len; header = 0; } return size1 - size; }
static int wav_parse_bext_tag(AVFormatContext *s, int64_t size) { char temp[131], *coding_history; int ret, x; uint64_t time_reference; int64_t umid_parts[8], umid_mask = 0; if ((ret = wav_parse_bext_string(s, "description", 256)) < 0 || (ret = wav_parse_bext_string(s, "originator", 32)) < 0 || (ret = wav_parse_bext_string(s, "originator_reference", 32)) < 0 || (ret = wav_parse_bext_string(s, "origination_date", 10)) < 0 || (ret = wav_parse_bext_string(s, "origination_time", 8)) < 0) return ret; time_reference = avio_rl64(s->pb); snprintf(temp, sizeof(temp), "%"PRIu64, time_reference); if ((ret = av_dict_set(&s->metadata, "time_reference", temp, 0)) < 0) return ret; /* check if version is >= 1, in which case an UMID may be present */ if (avio_rl16(s->pb) >= 1) { for (x = 0; x < 8; x++) umid_mask |= umid_parts[x] = avio_rb64(s->pb); if (umid_mask) { /* the string formatting below is per SMPTE 330M-2004 Annex C */ if (umid_parts[4] == 0 && umid_parts[5] == 0 && umid_parts[6] == 0 && umid_parts[7] == 0) { /* basic UMID */ snprintf(temp, sizeof(temp), "0x%016"PRIX64"%016"PRIX64"%016"PRIX64"%016"PRIX64, umid_parts[0], umid_parts[1], umid_parts[2], umid_parts[3]); } else { /* extended UMID */ snprintf(temp, sizeof(temp), "0x%016"PRIX64"%016"PRIX64"%016"PRIX64"%016"PRIX64 "0x%016"PRIX64"%016"PRIX64"%016"PRIX64"%016"PRIX64, umid_parts[0], umid_parts[1], umid_parts[2], umid_parts[3], umid_parts[4], umid_parts[5], umid_parts[6], umid_parts[7]); } if ((ret = av_dict_set(&s->metadata, "umid", temp, 0)) < 0) return ret; } avio_skip(s->pb, 190); } else avio_skip(s->pb, 254); if (size > 602) { /* CodingHistory present */ size -= 602; if (!(coding_history = av_malloc(size+1))) return AVERROR(ENOMEM); if ((ret = avio_read(s->pb, coding_history, size)) < 0) return ret; coding_history[size] = 0; if ((ret = av_dict_set(&s->metadata, "coding_history", coding_history, AV_METADATA_DONT_STRDUP_VAL)) < 0) return ret; } return 0; }
static int parse_dsd_prop(AVFormatContext *s, AVStream *st, uint64_t eof) { AVIOContext *pb = s->pb; char abss[24]; int hour, min, sec, i, ret, config; int dsd_layout[6]; ID3v2ExtraMeta *id3v2_extra_meta; while (avio_tell(pb) + 12 <= eof) { uint32_t tag = avio_rl32(pb); uint64_t size = avio_rb64(pb); uint64_t orig_pos = avio_tell(pb); switch(tag) { case MKTAG('A','B','S','S'): if (size < 8) return AVERROR_INVALIDDATA; hour = avio_rb16(pb); min = avio_r8(pb); sec = avio_r8(pb); snprintf(abss, sizeof(abss), "%02dh:%02dm:%02ds:%d", hour, min, sec, avio_rb32(pb)); av_dict_set(&st->metadata, "absolute_start_time", abss, 0); break; case MKTAG('C','H','N','L'): if (size < 2) return AVERROR_INVALIDDATA; st->codec->channels = avio_rb16(pb); if (size < 2 + st->codec->channels * 4) return AVERROR_INVALIDDATA; st->codec->channel_layout = 0; if (st->codec->channels > FF_ARRAY_ELEMS(dsd_layout)) { avpriv_request_sample(s, "channel layout"); break; } for (i = 0; i < st->codec->channels; i++) dsd_layout[i] = avio_rl32(pb); for (i = 0; i < FF_ARRAY_ELEMS(dsd_channel_layout); i++) { const DSDLayoutDesc * d = &dsd_channel_layout[i]; if (av_get_channel_layout_nb_channels(d->layout) == st->codec->channels && !memcmp(d->dsd_layout, dsd_layout, st->codec->channels * sizeof(uint32_t))) { st->codec->channel_layout = d->layout; break; } } break; case MKTAG('C','M','P','R'): if (size < 4) return AVERROR_INVALIDDATA; tag = avio_rl32(pb); st->codec->codec_id = ff_codec_get_id(dsd_codec_tags, tag); if (!st->codec->codec_id) { av_log(s, AV_LOG_ERROR, "'%c%c%c%c' compression is not supported\n", tag&0xFF, (tag>>8)&0xFF, (tag>>16)&0xFF, (tag>>24)&0xFF); return AVERROR_PATCHWELCOME; } break; case MKTAG('F','S',' ',' '): if (size < 4) return AVERROR_INVALIDDATA; st->codec->sample_rate = avio_rb32(pb) / 8; break; case MKTAG('I','D','3',' '): id3v2_extra_meta = NULL; ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta, size); if (id3v2_extra_meta) { if ((ret = ff_id3v2_parse_apic(s, &id3v2_extra_meta)) < 0) { ff_id3v2_free_extra_meta(&id3v2_extra_meta); return ret; } ff_id3v2_free_extra_meta(&id3v2_extra_meta); } if (size < avio_tell(pb) - orig_pos) { av_log(s, AV_LOG_ERROR, "id3 exceeds chunk size\n"); return AVERROR_INVALIDDATA; } break; case MKTAG('L','S','C','O'): if (size < 2) return AVERROR_INVALIDDATA; config = avio_rb16(pb); if (config != 0xFFFF) { if (config < FF_ARRAY_ELEMS(dsd_loudspeaker_config)) st->codec->channel_layout = dsd_loudspeaker_config[config]; if (!st->codec->channel_layout) avpriv_request_sample(s, "loudspeaker configuration %d", config); } break; } avio_skip(pb, size - (avio_tell(pb) - orig_pos) + (size & 1)); }
static int amf_parse_object(AVFormatContext *s, AVStream *astream, AVStream *vstream, const char *key, int64_t max_pos, int depth) { AVCodecContext *acodec, *vcodec; AVIOContext *ioc; AMFDataType amf_type; char str_val[256]; double num_val; num_val = 0; ioc = s->pb; amf_type = avio_r8(ioc); switch(amf_type) { case AMF_DATA_TYPE_NUMBER: num_val = av_int2double(avio_rb64(ioc)); break; case AMF_DATA_TYPE_BOOL: num_val = avio_r8(ioc); break; case AMF_DATA_TYPE_STRING: if(amf_get_string(ioc, str_val, sizeof(str_val)) < 0) return -1; break; case AMF_DATA_TYPE_OBJECT: if ((vstream || astream) && ioc->seekable && key && !strcmp(KEYFRAMES_TAG, key) && depth == 1) if (parse_keyframes_index(s, ioc, vstream ? vstream : astream, max_pos) < 0) av_log(s, AV_LOG_ERROR, "Keyframe index parsing failed\n"); while (avio_tell(ioc) < max_pos - 2 && amf_get_string(ioc, str_val, sizeof(str_val)) > 0) { if (amf_parse_object(s, astream, vstream, str_val, max_pos, depth + 1) < 0) return -1; //if we couldn't skip, bomb out. } if(avio_r8(ioc) != AMF_END_OF_OBJECT) return -1; break; case AMF_DATA_TYPE_NULL: case AMF_DATA_TYPE_UNDEFINED: case AMF_DATA_TYPE_UNSUPPORTED: break; //these take up no additional space case AMF_DATA_TYPE_MIXEDARRAY: avio_skip(ioc, 4); //skip 32-bit max array index while(avio_tell(ioc) < max_pos - 2 && amf_get_string(ioc, str_val, sizeof(str_val)) > 0) { //this is the only case in which we would want a nested parse to not skip over the object if(amf_parse_object(s, astream, vstream, str_val, max_pos, depth + 1) < 0) return -1; } if(avio_r8(ioc) != AMF_END_OF_OBJECT) return -1; break; case AMF_DATA_TYPE_ARRAY: { unsigned int arraylen, i; arraylen = avio_rb32(ioc); for(i = 0; i < arraylen && avio_tell(ioc) < max_pos - 1; i++) { if(amf_parse_object(s, NULL, NULL, NULL, max_pos, depth + 1) < 0) return -1; //if we couldn't skip, bomb out. } } break; case AMF_DATA_TYPE_DATE: avio_skip(ioc, 8 + 2); //timestamp (double) and UTC offset (int16) break; default: //unsupported type, we couldn't skip return -1; } if(depth == 1 && key) { //only look for metadata values when we are not nested and key != NULL acodec = astream ? astream->codec : NULL; vcodec = vstream ? vstream->codec : NULL; if (amf_type == AMF_DATA_TYPE_NUMBER) { if (!strcmp(key, "duration")) s->duration = num_val * AV_TIME_BASE; else if (!strcmp(key, "videodatarate") && vcodec && 0 <= (int)(num_val * 1024.0)) vcodec->bit_rate = num_val * 1024.0; else if (!strcmp(key, "audiodatarate") && acodec && 0 <= (int)(num_val * 1024.0)) acodec->bit_rate = num_val * 1024.0; else if (!strcmp(key, "datastream")) { AVStream *st = create_stream(s, 2, AVMEDIA_TYPE_DATA); if (!st) return AVERROR(ENOMEM); st->codec->codec_id = CODEC_ID_TEXT; } } if (amf_type == AMF_DATA_TYPE_OBJECT && s->nb_streams == 1 && ((!acodec && !strcmp(key, "audiocodecid")) || (!vcodec && !strcmp(key, "videocodecid")))) s->ctx_flags &= ~AVFMTCTX_NOHEADER; //If there is either audio/video missing, codecid will be an empty object if (!strcmp(key, "duration") || !strcmp(key, "filesize") || !strcmp(key, "width") || !strcmp(key, "height") || !strcmp(key, "videodatarate") || !strcmp(key, "framerate") || !strcmp(key, "videocodecid") || !strcmp(key, "audiodatarate") || !strcmp(key, "audiosamplerate") || !strcmp(key, "audiosamplesize") || !strcmp(key, "stereo") || !strcmp(key, "audiocodecid")) return 0; if(amf_type == AMF_DATA_TYPE_BOOL) { av_strlcpy(str_val, num_val > 0 ? "true" : "false", sizeof(str_val)); av_dict_set(&s->metadata, key, str_val, 0); } else if(amf_type == AMF_DATA_TYPE_NUMBER) { snprintf(str_val, sizeof(str_val), "%.f", num_val); av_dict_set(&s->metadata, key, str_val, 0); } else if (amf_type == AMF_DATA_TYPE_STRING) av_dict_set(&s->metadata, key, str_val, 0); } return 0; }
static int parse_keyframes_index(AVFormatContext *s, AVIOContext *ioc, AVStream *vstream, int64_t max_pos) { FLVContext *flv = s->priv_data; unsigned int timeslen = 0, fileposlen = 0, i; char str_val[256]; int64_t *times = NULL; int64_t *filepositions = NULL; int ret = AVERROR(ENOSYS); int64_t initial_pos = avio_tell(ioc); if(vstream->nb_index_entries>0) { av_log(s, AV_LOG_WARNING, "Skiping duplicate index\n"); return 0; } if (s->flags & AVFMT_FLAG_IGNIDX) return 0; while (avio_tell(ioc) < max_pos - 2 && amf_get_string(ioc, str_val, sizeof(str_val)) > 0) { int64_t** current_array; unsigned int arraylen; // Expect array object in context if (avio_r8(ioc) != AMF_DATA_TYPE_ARRAY) break; arraylen = avio_rb32(ioc); if(arraylen>>28) break; if (!strcmp(KEYFRAMES_TIMESTAMP_TAG , str_val) && !times) { current_array= × timeslen= arraylen; } else if (!strcmp(KEYFRAMES_BYTEOFFSET_TAG, str_val) && !filepositions) { current_array= &filepositions; fileposlen= arraylen; } else // unexpected metatag inside keyframes, will not use such metadata for indexing break; if (!(*current_array = av_mallocz(sizeof(**current_array) * arraylen))) { ret = AVERROR(ENOMEM); goto finish; } for (i = 0; i < arraylen && avio_tell(ioc) < max_pos - 1; i++) { if (avio_r8(ioc) != AMF_DATA_TYPE_NUMBER) goto invalid; current_array[0][i] = av_int2double(avio_rb64(ioc)); } if (times && filepositions) { // All done, exiting at a position allowing amf_parse_object // to finish parsing the object ret = 0; break; } } if (timeslen == fileposlen && fileposlen>1 && max_pos <= filepositions[0]) { for (i = 0; i < fileposlen; i++) { av_add_index_entry(vstream, filepositions[i], times[i]*1000, 0, 0, AVINDEX_KEYFRAME); if (i < 2) { flv->validate_index[i].pos = filepositions[i]; flv->validate_index[i].dts = times[i] * 1000; flv->validate_count = i + 1; } } } else { invalid: av_log(s, AV_LOG_WARNING, "Invalid keyframes object, skipping.\n"); } finish: av_freep(×); av_freep(&filepositions); avio_seek(ioc, initial_pos, SEEK_SET); return ret; }
static int ffm2_read_header(AVFormatContext *s) { FFMContext *ffm = s->priv_data; AVStream *st; AVIOContext *pb = s->pb; AVCodecContext *codec; int ret; int f_main = 0, f_cprv = -1, f_stvi = -1, f_stau = -1; AVCodec *enc; char *buffer; ffm->packet_size = avio_rb32(pb); if (ffm->packet_size != FFM_PACKET_SIZE) { av_log(s, AV_LOG_ERROR, "Invalid packet size %d, expected size was %d\n", ffm->packet_size, FFM_PACKET_SIZE); ret = AVERROR_INVALIDDATA; goto fail; } ffm->write_index = avio_rb64(pb); /* get also filesize */ if (pb->seekable) { ffm->file_size = avio_size(pb); if (ffm->write_index && 0) adjust_write_index(s); } else { ffm->file_size = (UINT64_C(1) << 63) - 1; } while(!avio_feof(pb)) { unsigned id = avio_rb32(pb); unsigned size = avio_rb32(pb); int64_t next = avio_tell(pb) + size; char rc_eq_buf[128]; if(!id) break; switch(id) { case MKBETAG('M', 'A', 'I', 'N'): if (f_main++) { ret = AVERROR(EINVAL); goto fail; } avio_rb32(pb); /* nb_streams */ avio_rb32(pb); /* total bitrate */ break; case MKBETAG('C', 'O', 'M', 'M'): f_cprv = f_stvi = f_stau = 0; st = avformat_new_stream(s, NULL); if (!st) { ret = AVERROR(ENOMEM); goto fail; } avpriv_set_pts_info(st, 64, 1, 1000000); codec = st->codec; /* generic info */ codec->codec_id = avio_rb32(pb); codec->codec_type = avio_r8(pb); codec->bit_rate = avio_rb32(pb); codec->flags = avio_rb32(pb); codec->flags2 = avio_rb32(pb); codec->debug = avio_rb32(pb); if (codec->flags & CODEC_FLAG_GLOBAL_HEADER) { if (ff_get_extradata(codec, pb, avio_rb32(pb)) < 0) return AVERROR(ENOMEM); } break; case MKBETAG('S', 'T', 'V', 'I'): if (f_stvi++) { ret = AVERROR(EINVAL); goto fail; } codec->time_base.num = avio_rb32(pb); codec->time_base.den = avio_rb32(pb); if (codec->time_base.num <= 0 || codec->time_base.den <= 0) { av_log(s, AV_LOG_ERROR, "Invalid time base %d/%d\n", codec->time_base.num, codec->time_base.den); ret = AVERROR_INVALIDDATA; goto fail; } codec->width = avio_rb16(pb); codec->height = avio_rb16(pb); codec->gop_size = avio_rb16(pb); codec->pix_fmt = avio_rb32(pb); codec->qmin = avio_r8(pb); codec->qmax = avio_r8(pb); codec->max_qdiff = avio_r8(pb); codec->qcompress = avio_rb16(pb) / 10000.0; codec->qblur = avio_rb16(pb) / 10000.0; codec->bit_rate_tolerance = avio_rb32(pb); avio_get_str(pb, INT_MAX, rc_eq_buf, sizeof(rc_eq_buf)); codec->rc_eq = av_strdup(rc_eq_buf); codec->rc_max_rate = avio_rb32(pb); codec->rc_min_rate = avio_rb32(pb); codec->rc_buffer_size = avio_rb32(pb); codec->i_quant_factor = av_int2double(avio_rb64(pb)); codec->b_quant_factor = av_int2double(avio_rb64(pb)); codec->i_quant_offset = av_int2double(avio_rb64(pb)); codec->b_quant_offset = av_int2double(avio_rb64(pb)); codec->dct_algo = avio_rb32(pb); codec->strict_std_compliance = avio_rb32(pb); codec->max_b_frames = avio_rb32(pb); codec->mpeg_quant = avio_rb32(pb); codec->intra_dc_precision = avio_rb32(pb); codec->me_method = avio_rb32(pb); codec->mb_decision = avio_rb32(pb); codec->nsse_weight = avio_rb32(pb); codec->frame_skip_cmp = avio_rb32(pb); codec->rc_buffer_aggressivity = av_int2double(avio_rb64(pb)); codec->codec_tag = avio_rb32(pb); codec->thread_count = avio_r8(pb); codec->coder_type = avio_rb32(pb); codec->me_cmp = avio_rb32(pb); codec->me_subpel_quality = avio_rb32(pb); codec->me_range = avio_rb32(pb); codec->keyint_min = avio_rb32(pb); codec->scenechange_threshold = avio_rb32(pb); codec->b_frame_strategy = avio_rb32(pb); codec->qcompress = av_int2double(avio_rb64(pb)); codec->qblur = av_int2double(avio_rb64(pb)); codec->max_qdiff = avio_rb32(pb); codec->refs = avio_rb32(pb); break; case MKBETAG('S', 'T', 'A', 'U'): if (f_stau++) { ret = AVERROR(EINVAL); goto fail; } codec->sample_rate = avio_rb32(pb); codec->channels = avio_rl16(pb); codec->frame_size = avio_rl16(pb); break; case MKBETAG('C', 'P', 'R', 'V'): if (f_cprv++) { ret = AVERROR(EINVAL); goto fail; } enc = avcodec_find_encoder(codec->codec_id); if (enc && enc->priv_data_size && enc->priv_class) { buffer = av_malloc(size + 1); if (!buffer) { ret = AVERROR(ENOMEM); goto fail; } avio_get_str(pb, size, buffer, size + 1); if ((ret = ffm_append_recommended_configuration(st, &buffer)) < 0) goto fail; } break; case MKBETAG('S', '2', 'V', 'I'): if (f_stvi++) { ret = AVERROR(EINVAL); goto fail; } buffer = av_malloc(size); if (!buffer) { ret = AVERROR(ENOMEM); goto fail; } avio_get_str(pb, INT_MAX, buffer, size); av_set_options_string(codec, buffer, "=", ","); if ((ret = ffm_append_recommended_configuration(st, &buffer)) < 0) goto fail; break; case MKBETAG('S', '2', 'A', 'U'): if (f_stau++) { ret = AVERROR(EINVAL); goto fail; } buffer = av_malloc(size); if (!buffer) { ret = AVERROR(ENOMEM); goto fail; } avio_get_str(pb, INT_MAX, buffer, size); av_set_options_string(codec, buffer, "=", ","); ffm_append_recommended_configuration(st, &buffer); break; } avio_seek(pb, next, SEEK_SET); } /* get until end of block reached */ while ((avio_tell(pb) % ffm->packet_size) != 0 && !pb->eof_reached) avio_r8(pb); /* init packet demux */ ffm->packet_ptr = ffm->packet; ffm->packet_end = ffm->packet; ffm->frame_offset = 0; ffm->dts = 0; ffm->read_state = READ_HEADER; ffm->first_packet = 1; return 0; fail: ffm_close(s); return ret; }
/* Returns the number of sound data frames or negative on error */ static int get_aiff_header(AVFormatContext *s, int size, unsigned version) { AVIOContext *pb = s->pb; AVCodecContext *codec = s->streams[0]->codec; AIFFInputContext *aiff = s->priv_data; int exp; uint64_t val; int sample_rate; unsigned int num_frames; if (size & 1) size++; codec->codec_type = AVMEDIA_TYPE_AUDIO; codec->channels = avio_rb16(pb); num_frames = avio_rb32(pb); codec->bits_per_coded_sample = avio_rb16(pb); exp = avio_rb16(pb) - 16383 - 63; val = avio_rb64(pb); if (exp <-63 || exp >63) { av_log(s, AV_LOG_ERROR, "exp %d is out of range\n", exp); return AVERROR_INVALIDDATA; } if (exp >= 0) sample_rate = val << exp; else sample_rate = (val + (1ULL<<(-exp-1))) >> -exp; codec->sample_rate = sample_rate; size -= 18; /* get codec id for AIFF-C */ if (size < 4) { version = AIFF; } else if (version == AIFF_C_VERSION1) { codec->codec_tag = avio_rl32(pb); codec->codec_id = ff_codec_get_id(ff_codec_aiff_tags, codec->codec_tag); if (codec->codec_id == AV_CODEC_ID_NONE) { char tag[32]; av_get_codec_tag_string(tag, sizeof(tag), codec->codec_tag); avpriv_request_sample(s, "unknown or unsupported codec tag: %s", tag); } size -= 4; } if (version != AIFF_C_VERSION1 || codec->codec_id == AV_CODEC_ID_PCM_S16BE) { codec->codec_id = aiff_codec_get_id(codec->bits_per_coded_sample); codec->bits_per_coded_sample = av_get_bits_per_sample(codec->codec_id); aiff->block_duration = 1; } else { switch (codec->codec_id) { case AV_CODEC_ID_PCM_F32BE: case AV_CODEC_ID_PCM_F64BE: case AV_CODEC_ID_PCM_S16LE: case AV_CODEC_ID_PCM_ALAW: case AV_CODEC_ID_PCM_MULAW: aiff->block_duration = 1; break; case AV_CODEC_ID_ADPCM_IMA_QT: codec->block_align = 34*codec->channels; break; case AV_CODEC_ID_MACE3: codec->block_align = 2*codec->channels; break; case AV_CODEC_ID_ADPCM_G726LE: codec->bits_per_coded_sample = 5; case AV_CODEC_ID_ADPCM_IMA_WS: case AV_CODEC_ID_ADPCM_G722: case AV_CODEC_ID_MACE6: case AV_CODEC_ID_SDX2_DPCM: codec->block_align = 1*codec->channels; break; case AV_CODEC_ID_GSM: codec->block_align = 33; break; default: aiff->block_duration = 1; break; } if (codec->block_align > 0) aiff->block_duration = av_get_audio_frame_duration(codec, codec->block_align); } /* Block align needs to be computed in all cases, as the definition * is specific to applications -> here we use the WAVE format definition */ if (!codec->block_align) codec->block_align = (av_get_bits_per_sample(codec->codec_id) * codec->channels) >> 3; if (aiff->block_duration) { codec->bit_rate = codec->sample_rate * (codec->block_align << 3) / aiff->block_duration; } /* Chunk is over */ if (size) avio_skip(pb, size); return num_frames; }
static int iff_read_header(AVFormatContext *s) { IffDemuxContext *iff = s->priv_data; AVIOContext *pb = s->pb; AVStream *st; uint8_t *buf; uint32_t chunk_id; uint64_t data_size; uint32_t screenmode = 0, num, den; unsigned transparency = 0; unsigned masking = 0; // no mask uint8_t fmt[16]; int fmt_size; st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); st->codec->channels = 1; st->codec->channel_layout = AV_CH_LAYOUT_MONO; iff->is_64bit = avio_rl32(pb) == ID_FRM8; avio_skip(pb, iff->is_64bit ? 8 : 4); // codec_tag used by ByteRun1 decoder to distinguish progressive (PBM) and interlaced (ILBM) content st->codec->codec_tag = avio_rl32(pb); if (st->codec->codec_tag == ID_ANIM) { avio_skip(pb, 8); st->codec->codec_tag = avio_rl32(pb); } iff->bitmap_compression = -1; iff->svx8_compression = -1; iff->maud_bits = -1; iff->maud_compression = -1; while(!avio_feof(pb)) { uint64_t orig_pos; int res; const char *metadata_tag = NULL; int version, nb_comments, i; chunk_id = avio_rl32(pb); data_size = iff->is_64bit ? avio_rb64(pb) : avio_rb32(pb); orig_pos = avio_tell(pb); switch(chunk_id) { case ID_VHDR: st->codec->codec_type = AVMEDIA_TYPE_AUDIO; if (data_size < 14) return AVERROR_INVALIDDATA; avio_skip(pb, 12); st->codec->sample_rate = avio_rb16(pb); if (data_size >= 16) { avio_skip(pb, 1); iff->svx8_compression = avio_r8(pb); } break; case ID_MHDR: st->codec->codec_type = AVMEDIA_TYPE_AUDIO; if (data_size < 32) return AVERROR_INVALIDDATA; avio_skip(pb, 4); iff->maud_bits = avio_rb16(pb); avio_skip(pb, 2); num = avio_rb32(pb); den = avio_rb16(pb); if (!den) return AVERROR_INVALIDDATA; avio_skip(pb, 2); st->codec->sample_rate = num / den; st->codec->channels = avio_rb16(pb); iff->maud_compression = avio_rb16(pb); if (st->codec->channels == 1) st->codec->channel_layout = AV_CH_LAYOUT_MONO; else if (st->codec->channels == 2) st->codec->channel_layout = AV_CH_LAYOUT_STEREO; break; case ID_ABIT: case ID_BODY: case ID_DBOD: case ID_DSD: case ID_MDAT: iff->body_pos = avio_tell(pb); iff->body_end = iff->body_pos + data_size; iff->body_size = data_size; break; case ID_CHAN: if (data_size < 4) return AVERROR_INVALIDDATA; if (avio_rb32(pb) < 6) { st->codec->channels = 1; st->codec->channel_layout = AV_CH_LAYOUT_MONO; } else { st->codec->channels = 2; st->codec->channel_layout = AV_CH_LAYOUT_STEREO; } break; case ID_CAMG: if (data_size < 4) return AVERROR_INVALIDDATA; screenmode = avio_rb32(pb); break; case ID_CMAP: if (data_size < 3 || data_size > 768 || data_size % 3) { av_log(s, AV_LOG_ERROR, "Invalid CMAP chunk size %"PRIu64"\n", data_size); return AVERROR_INVALIDDATA; } st->codec->extradata_size = data_size + IFF_EXTRA_VIDEO_SIZE; st->codec->extradata = av_malloc(data_size + IFF_EXTRA_VIDEO_SIZE + FF_INPUT_BUFFER_PADDING_SIZE); if (!st->codec->extradata) return AVERROR(ENOMEM); if (avio_read(pb, st->codec->extradata + IFF_EXTRA_VIDEO_SIZE, data_size) < 0) return AVERROR(EIO); break; case ID_BMHD: st->codec->codec_type = AVMEDIA_TYPE_VIDEO; if (data_size <= 8) return AVERROR_INVALIDDATA; st->codec->width = avio_rb16(pb); st->codec->height = avio_rb16(pb); avio_skip(pb, 4); // x, y offset st->codec->bits_per_coded_sample = avio_r8(pb); if (data_size >= 10) masking = avio_r8(pb); if (data_size >= 11) iff->bitmap_compression = avio_r8(pb); if (data_size >= 14) { avio_skip(pb, 1); // padding transparency = avio_rb16(pb); } if (data_size >= 16) { st->sample_aspect_ratio.num = avio_r8(pb); st->sample_aspect_ratio.den = avio_r8(pb); } break; case ID_DPEL: if (data_size < 4 || (data_size & 3)) return AVERROR_INVALIDDATA; if ((fmt_size = avio_read(pb, fmt, sizeof(fmt))) < 0) return fmt_size; if (fmt_size == sizeof(deep_rgb24) && !memcmp(fmt, deep_rgb24, sizeof(deep_rgb24))) st->codec->pix_fmt = AV_PIX_FMT_RGB24; else if (fmt_size == sizeof(deep_rgba) && !memcmp(fmt, deep_rgba, sizeof(deep_rgba))) st->codec->pix_fmt = AV_PIX_FMT_RGBA; else if (fmt_size == sizeof(deep_bgra) && !memcmp(fmt, deep_bgra, sizeof(deep_bgra))) st->codec->pix_fmt = AV_PIX_FMT_BGRA; else if (fmt_size == sizeof(deep_argb) && !memcmp(fmt, deep_argb, sizeof(deep_argb))) st->codec->pix_fmt = AV_PIX_FMT_ARGB; else if (fmt_size == sizeof(deep_abgr) && !memcmp(fmt, deep_abgr, sizeof(deep_abgr))) st->codec->pix_fmt = AV_PIX_FMT_ABGR; else { avpriv_request_sample(s, "color format %.16s", fmt); return AVERROR_PATCHWELCOME; } break; case ID_DGBL: 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); iff->bitmap_compression = avio_rb16(pb); st->sample_aspect_ratio.num = avio_r8(pb); st->sample_aspect_ratio.den = avio_r8(pb); st->codec->bits_per_coded_sample = 24; break; case ID_DLOC: if (data_size < 4) return AVERROR_INVALIDDATA; st->codec->width = avio_rb16(pb); st->codec->height = avio_rb16(pb); break; case ID_TVDC: if (data_size < sizeof(iff->tvdc)) return AVERROR_INVALIDDATA; res = avio_read(pb, iff->tvdc, sizeof(iff->tvdc)); if (res < 0) return res; 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; /* DSD tags */ case MKTAG('F','V','E','R'): if (data_size < 4) return AVERROR_INVALIDDATA; version = avio_rb32(pb); av_log(s, AV_LOG_DEBUG, "DSIFF v%d.%d.%d.%d\n",version >> 24, (version >> 16) & 0xFF, (version >> 8) & 0xFF, version & 0xFF); st->codec->codec_type = AVMEDIA_TYPE_AUDIO; break; case MKTAG('D','I','I','N'): res = parse_dsd_diin(s, st, orig_pos + data_size); if (res < 0) return res; break; case MKTAG('P','R','O','P'): if (data_size < 4) return AVERROR_INVALIDDATA; if (avio_rl32(pb) != MKTAG('S','N','D',' ')) { avpriv_request_sample(s, "unknown property type"); break; } res = parse_dsd_prop(s, st, orig_pos + data_size); if (res < 0) return res; break; case MKTAG('C','O','M','T'): if (data_size < 2) return AVERROR_INVALIDDATA; nb_comments = avio_rb16(pb); for (i = 0; i < nb_comments; i++) { int year, mon, day, hour, min, type, ref; char tmp[24]; const char *tag; int metadata_size; year = avio_rb16(pb); mon = avio_r8(pb); day = avio_r8(pb); hour = avio_r8(pb); min = avio_r8(pb); snprintf(tmp, sizeof(tmp), "%04d-%02d-%02d %02d:%02d", year, mon, day, hour, min); av_dict_set(&st->metadata, "comment_time", tmp, 0); type = avio_rb16(pb); ref = avio_rb16(pb); switch (type) { case 1: if (!i) tag = "channel_comment"; else { snprintf(tmp, sizeof(tmp), "channel%d_comment", ref); tag = tmp; } break; case 2: tag = ref < FF_ARRAY_ELEMS(dsd_source_comment) ? dsd_source_comment[ref] : "source_comment"; break; case 3: tag = ref < FF_ARRAY_ELEMS(dsd_history_comment) ? dsd_history_comment[ref] : "file_history"; break; default: tag = "comment"; } metadata_size = avio_rb32(pb); if ((res = get_metadata(s, tag, metadata_size)) < 0) { av_log(s, AV_LOG_ERROR, "cannot allocate metadata tag %s!\n", tag); return res; } if (metadata_size & 1) avio_skip(pb, 1); } 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!\n", metadata_tag); return res; } } avio_skip(pb, data_size - (avio_tell(pb) - orig_pos) + (data_size & 1)); } avio_seek(pb, iff->body_pos, SEEK_SET); switch(st->codec->codec_type) { case AVMEDIA_TYPE_AUDIO: avpriv_set_pts_info(st, 32, 1, st->codec->sample_rate); if (st->codec->codec_tag == ID_16SV) st->codec->codec_id = AV_CODEC_ID_PCM_S16BE_PLANAR; else if (st->codec->codec_tag == ID_MAUD) { if (iff->maud_bits == 8 && !iff->maud_compression) { st->codec->codec_id = AV_CODEC_ID_PCM_U8; } else if (iff->maud_bits == 16 && !iff->maud_compression) { st->codec->codec_id = AV_CODEC_ID_PCM_S16BE; } else if (iff->maud_bits == 8 && iff->maud_compression == 2) { st->codec->codec_id = AV_CODEC_ID_PCM_ALAW; } else if (iff->maud_bits == 8 && iff->maud_compression == 3) { st->codec->codec_id = AV_CODEC_ID_PCM_MULAW; } else { avpriv_request_sample(s, "compression %d and bit depth %d", iff->maud_compression, iff->maud_bits); return AVERROR_PATCHWELCOME; } } else if (st->codec->codec_tag != ID_DSD) { switch (iff->svx8_compression) { case COMP_NONE: st->codec->codec_id = AV_CODEC_ID_PCM_S8_PLANAR; break; case COMP_FIB: st->codec->codec_id = AV_CODEC_ID_8SVX_FIB; break; case COMP_EXP: st->codec->codec_id = AV_CODEC_ID_8SVX_EXP; break; default: av_log(s, AV_LOG_ERROR, "Unknown SVX8 compression method '%d'\n", iff->svx8_compression); return -1; } } st->codec->bits_per_coded_sample = av_get_bits_per_sample(st->codec->codec_id); 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: iff->bpp = st->codec->bits_per_coded_sample; if ((screenmode & 0x800 /* Hold And Modify */) && iff->bpp <= 8) { iff->ham = iff->bpp > 6 ? 6 : 4; st->codec->bits_per_coded_sample = 24; } iff->flags = (screenmode & 0x80 /* Extra HalfBrite */) && iff->bpp <= 8; iff->masking = masking; iff->transparency = transparency; if (!st->codec->extradata) { st->codec->extradata_size = IFF_EXTRA_VIDEO_SIZE; st->codec->extradata = av_malloc(IFF_EXTRA_VIDEO_SIZE + FF_INPUT_BUFFER_PADDING_SIZE); if (!st->codec->extradata) return AVERROR(ENOMEM); } av_assert0(st->codec->extradata_size >= IFF_EXTRA_VIDEO_SIZE); buf = st->codec->extradata; bytestream_put_be16(&buf, IFF_EXTRA_VIDEO_SIZE); bytestream_put_byte(&buf, iff->bitmap_compression); bytestream_put_byte(&buf, iff->bpp); bytestream_put_byte(&buf, iff->ham); bytestream_put_byte(&buf, iff->flags); bytestream_put_be16(&buf, iff->transparency); bytestream_put_byte(&buf, iff->masking); bytestream_put_buffer(&buf, iff->tvdc, sizeof(iff->tvdc)); st->codec->codec_id = AV_CODEC_ID_IFF_ILBM; break; default: return -1; } return 0; }