static int flac_read_header(AVFormatContext *s, AVFormatParameters *ap) { uint8_t buf[ID3v2_HEADER_SIZE]; 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 */ /* skip ID3v2 header if found */ ret = get_buffer(s->pb, buf, ID3v2_HEADER_SIZE); if (ret == ID3v2_HEADER_SIZE && ff_id3v2_match(buf, ID3v2_DEFAULT_MAGIC)) { int len = ff_id3v2_tag_len(buf); url_fseek(s->pb, len - ID3v2_HEADER_SIZE, SEEK_CUR); } else { url_fseek(s->pb, 0, SEEK_SET); } /* if fLaC marker is not found, assume there is no header */ if (get_le32(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) { get_buffer(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 (get_buffer(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 VP8StatusCode ParseOptionalChunks(const uint8_t** const data, size_t* const data_size, size_t const riff_size, const uint8_t** const alpha_data, size_t* const alpha_size) { const uint8_t* buf; size_t buf_size; uint32_t total_size = TAG_SIZE + CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE; assert(data != NULL); assert(data_size != NULL); buf = *data; buf_size = *data_size; assert(alpha_data != NULL); assert(alpha_size != NULL); *alpha_data = NULL; *alpha_size = 0; while (1) { uint32_t chunk_size; uint32_t disk_chunk_size; *data = buf; *data_size = buf_size; if (buf_size < CHUNK_HEADER_SIZE) { return VP8_STATUS_NOT_ENOUGH_DATA; } chunk_size = get_le32(buf + TAG_SIZE); if (chunk_size > MAX_CHUNK_PAYLOAD) { return VP8_STATUS_BITSTREAM_ERROR; } disk_chunk_size = (CHUNK_HEADER_SIZE + chunk_size + 1) & ~1; total_size += disk_chunk_size; if (riff_size > 0 && (total_size > riff_size)) { return VP8_STATUS_BITSTREAM_ERROR; } if (!memcmp(buf, "VP8 ", TAG_SIZE) || !memcmp(buf, "VP8L", TAG_SIZE)) { return VP8_STATUS_OK; } if (buf_size < disk_chunk_size) { return VP8_STATUS_NOT_ENOUGH_DATA; } if (!memcmp(buf, "ALPH", TAG_SIZE)) { *alpha_data = buf + CHUNK_HEADER_SIZE; *alpha_size = chunk_size; } buf += disk_chunk_size; buf_size -= disk_chunk_size; } }
static int smacker_read_packet(AVFormatContext *s, AVPacket *pkt) { SmackerContext *smk = s->priv_data; int flags; int ret; int i; int frame_size = 0; int palchange = 0; int pos; if (url_feof(s->pb) || smk->cur_frame >= smk->frames) return AVERROR_EOF; /* if we demuxed all streams, pass another frame */ if(smk->curstream < 0) { url_fseek(s->pb, smk->nextpos, 0); frame_size = smk->frm_size[smk->cur_frame] & (~3); flags = smk->frm_flags[smk->cur_frame]; /* handle palette change event */ pos = url_ftell(s->pb); if(flags & SMACKER_PAL){ int size, sz, t, off, j, pos; uint8_t *pal = smk->pal; uint8_t oldpal[768]; memcpy(oldpal, pal, 768); size = get_byte(s->pb); size = size * 4 - 1; frame_size -= size; frame_size--; sz = 0; pos = url_ftell(s->pb) + size; while(sz < 256){ t = get_byte(s->pb); if(t & 0x80){ /* skip palette entries */ sz += (t & 0x7F) + 1; pal += ((t & 0x7F) + 1) * 3; } else if(t & 0x40){ /* copy with offset */ off = get_byte(s->pb) * 3; j = (t & 0x3F) + 1; while(j-- && sz < 256) { *pal++ = oldpal[off + 0]; *pal++ = oldpal[off + 1]; *pal++ = oldpal[off + 2]; sz++; off += 3; } } else { /* new entries */ *pal++ = smk_pal[t]; *pal++ = smk_pal[get_byte(s->pb) & 0x3F]; *pal++ = smk_pal[get_byte(s->pb) & 0x3F]; sz++; } } url_fseek(s->pb, pos, 0); palchange |= 1; } flags >>= 1; smk->curstream = -1; /* if audio chunks are present, put them to stack and retrieve later */ for(i = 0; i < 7; i++) { if(flags & 1) { int size; size = get_le32(s->pb) - 4; frame_size -= size; frame_size -= 4; smk->curstream++; smk->bufs[smk->curstream] = av_realloc(smk->bufs[smk->curstream], size); smk->buf_sizes[smk->curstream] = size; ret = get_buffer(s->pb, smk->bufs[smk->curstream], size); if(ret != size) return AVERROR(EIO); smk->stream_id[smk->curstream] = smk->indexes[i]; } flags >>= 1; } if (av_new_packet(pkt, frame_size + 768)) return AVERROR(ENOMEM); if(smk->frm_size[smk->cur_frame] & 1) palchange |= 2; pkt->data[0] = palchange; memcpy(pkt->data + 1, smk->pal, 768); ret = get_buffer(s->pb, pkt->data + 769, frame_size); if(ret != frame_size) return AVERROR(EIO); pkt->stream_index = smk->videoindex; pkt->size = ret + 769; smk->cur_frame++; smk->nextpos = url_ftell(s->pb); } else {
/** * \brief read until we found all data needed for decoding * \param vst video stream of which to change parameters * \param ast video stream of which to change parameters * \param myth set if this is a MythTVVideo format file * \return 1 if all required codec data was found */ static int get_codec_data(ByteIOContext *pb, AVStream *vst, AVStream *ast, int myth) { frametype_t frametype; if (!vst && !myth) return 1; // no codec data needed while (!url_feof(pb)) { int size, subtype; frametype = get_byte(pb); switch (frametype) { case NUV_EXTRADATA: subtype = get_byte(pb); url_fskip(pb, 6); size = PKTSIZE(get_le32(pb)); if (vst && subtype == 'R') { vst->codec->extradata_size = size; vst->codec->extradata = av_malloc(size); get_buffer(pb, vst->codec->extradata, size); size = 0; if (!myth) return 1; } break; case NUV_MYTHEXT: url_fskip(pb, 7); size = PKTSIZE(get_le32(pb)); if (size != 128 * 4) break; get_le32(pb); // version if (vst) { vst->codec->codec_tag = get_le32(pb); vst->codec->codec_id = codec_get_id(codec_bmp_tags, vst->codec->codec_tag); if (vst->codec->codec_tag == MKTAG('R', 'J', 'P', 'G')) vst->codec->codec_id = CODEC_ID_NUV; } else url_fskip(pb, 4); if (ast) { ast->codec->codec_tag = get_le32(pb); ast->codec->sample_rate = get_le32(pb); ast->codec->bits_per_sample = get_le32(pb); ast->codec->channels = get_le32(pb); ast->codec->codec_id = wav_codec_get_id(ast->codec->codec_tag, ast->codec->bits_per_sample); ast->need_parsing = AVSTREAM_PARSE_FULL; } else url_fskip(pb, 4 * 4); size -= 6 * 4; url_fskip(pb, size); return 1; case NUV_SEEKP: size = 11; break; default: url_fskip(pb, 7); size = PKTSIZE(get_le32(pb)); break; } url_fskip(pb, size); } return 0; }
static int ape_read_header(AVFormatContext * s, AVFormatParameters * ap) { ByteIOContext *pb = s->pb; APEContext *ape = s->priv_data; AVStream *st; uint32_t tag; int i; int total_blocks; int64_t pts; /* TODO: Skip any leading junk such as id3v2 tags */ ape->junklength = 0; tag = get_le32(pb); if (tag != MKTAG('M', 'A', 'C', ' ')) return -1; ape->fileversion = get_le16(pb); if (ape->fileversion < APE_MIN_VERSION || ape->fileversion > APE_MAX_VERSION) { av_log(s, AV_LOG_ERROR, "Unsupported file version - %d.%02d\n", ape->fileversion / 1000, (ape->fileversion % 1000) / 10); return -1; } if (ape->fileversion >= 3980) { ape->padding1 = get_le16(pb); ape->descriptorlength = get_le32(pb); ape->headerlength = get_le32(pb); ape->seektablelength = get_le32(pb); ape->wavheaderlength = get_le32(pb); ape->audiodatalength = get_le32(pb); ape->audiodatalength_high = get_le32(pb); ape->wavtaillength = get_le32(pb); get_buffer(pb, ape->md5, 16); /* Skip any unknown bytes at the end of the descriptor. This is for future compatibility */ if (ape->descriptorlength > 52) url_fseek(pb, ape->descriptorlength - 52, SEEK_CUR); /* Read header data */ ape->compressiontype = get_le16(pb); ape->formatflags = get_le16(pb); ape->blocksperframe = get_le32(pb); ape->finalframeblocks = get_le32(pb); ape->totalframes = get_le32(pb); ape->bps = get_le16(pb); ape->channels = get_le16(pb); ape->samplerate = get_le32(pb); } else { ape->descriptorlength = 0; ape->headerlength = 32; ape->compressiontype = get_le16(pb); ape->formatflags = get_le16(pb); ape->channels = get_le16(pb); ape->samplerate = get_le32(pb); ape->wavheaderlength = get_le32(pb); ape->wavtaillength = get_le32(pb); ape->totalframes = get_le32(pb); ape->finalframeblocks = get_le32(pb); if (ape->formatflags & MAC_FORMAT_FLAG_HAS_PEAK_LEVEL) { url_fseek(pb, 4, SEEK_CUR); /* Skip the peak level */ ape->headerlength += 4; } if (ape->formatflags & MAC_FORMAT_FLAG_HAS_SEEK_ELEMENTS) { ape->seektablelength = get_le32(pb); ape->headerlength += 4; ape->seektablelength *= sizeof(int32_t); } else ape->seektablelength = ape->totalframes * sizeof(int32_t); if (ape->formatflags & MAC_FORMAT_FLAG_8_BIT) ape->bps = 8; else if (ape->formatflags & MAC_FORMAT_FLAG_24_BIT) ape->bps = 24; else ape->bps = 16; if (ape->fileversion >= 3950) ape->blocksperframe = 73728 * 4; else if (ape->fileversion >= 3900 || (ape->fileversion >= 3800 && ape->compressiontype >= 4000)) ape->blocksperframe = 73728; else ape->blocksperframe = 9216; /* Skip any stored wav header */ if (!(ape->formatflags & MAC_FORMAT_FLAG_CREATE_WAV_HEADER)) url_fskip(pb, ape->wavheaderlength); } if(!ape->totalframes){ av_log(s, AV_LOG_ERROR, "No frames in the file!\n"); return AVERROR(EINVAL); } if(ape->totalframes > UINT_MAX / sizeof(APEFrame)){ av_log(s, AV_LOG_ERROR, "Too many frames: %d\n", ape->totalframes); return -1; } ape->frames = av_malloc(ape->totalframes * sizeof(APEFrame)); if(!ape->frames) return AVERROR_NOMEM; ape->firstframe = ape->junklength + ape->descriptorlength + ape->headerlength + ape->seektablelength + ape->wavheaderlength; ape->currentframe = 0; ape->totalsamples = ape->finalframeblocks; if (ape->totalframes > 1) ape->totalsamples += ape->blocksperframe * (ape->totalframes - 1); if (ape->seektablelength > 0) { ape->seektable = av_malloc(ape->seektablelength); if (!ape->seektable) return AVERROR(ENOMEM); for (i = 0; i < ape->seektablelength / sizeof(uint32_t); i++) ape->seektable[i] = get_le32(pb); } ape->frames[0].pos = ape->firstframe; ape->frames[0].nblocks = ape->blocksperframe; ape->frames[0].skip = 0; for (i = 1; i < ape->totalframes; i++) { ape->frames[i].pos = ape->seektable[i]; //ape->frames[i-1].pos + ape->blocksperframe; ape->frames[i].nblocks = ape->blocksperframe; ape->frames[i - 1].size = ape->frames[i].pos - ape->frames[i - 1].pos; ape->frames[i].skip = (ape->frames[i].pos - ape->frames[0].pos) & 3; } ape->frames[ape->totalframes - 1].size = ape->finalframeblocks * 4; ape->frames[ape->totalframes - 1].nblocks = ape->finalframeblocks; for (i = 0; i < ape->totalframes; i++) { if(ape->frames[i].skip){ ape->frames[i].pos -= ape->frames[i].skip; ape->frames[i].size += ape->frames[i].skip; } ape->frames[i].size = (ape->frames[i].size + 3) & ~3; } ape_dumpinfo(s, ape); /* try to read APE tags */ if (!url_is_streamed(pb)) { ape_parse_tag(s); url_fseek(pb, 0, SEEK_SET); } av_log(s, AV_LOG_DEBUG, "Decoding file - v%d.%02d, compression level %d\n", ape->fileversion / 1000, (ape->fileversion % 1000) / 10, ape->compressiontype); /* now we are ready: build format streams */ st = av_new_stream(s, 0); if (!st) return -1; total_blocks = (ape->totalframes == 0) ? 0 : ((ape->totalframes - 1) * ape->blocksperframe) + ape->finalframeblocks; st->codec->codec_type = CODEC_TYPE_AUDIO; st->codec->codec_id = CODEC_ID_APE; st->codec->codec_tag = MKTAG('A', 'P', 'E', ' '); st->codec->channels = ape->channels; st->codec->sample_rate = ape->samplerate; st->codec->bits_per_coded_sample = ape->bps; st->codec->frame_size = MAC_SUBFRAME_SIZE; st->nb_frames = ape->totalframes; s->start_time = 0; s->duration = (int64_t) total_blocks * AV_TIME_BASE / ape->samplerate; av_set_pts_info(st, 64, MAC_SUBFRAME_SIZE, ape->samplerate); st->codec->extradata = av_malloc(APE_EXTRADATA_SIZE); st->codec->extradata_size = APE_EXTRADATA_SIZE; AV_WL16(st->codec->extradata + 0, ape->fileversion); AV_WL16(st->codec->extradata + 2, ape->compressiontype); AV_WL16(st->codec->extradata + 4, ape->formatflags); pts = 0; for (i = 0; i < ape->totalframes; i++) { ape->frames[i].pts = pts; av_add_index_entry(st, ape->frames[i].pos, ape->frames[i].pts, 0, 0, AVINDEX_KEYFRAME); pts += ape->blocksperframe / MAC_SUBFRAME_SIZE; } return 0; }
// Skips to the next VP8/VP8L chunk header in the data given the size of the // RIFF chunk 'riff_size'. // Returns VP8_STATUS_BITSTREAM_ERROR if any invalid chunk size is encountered, // VP8_STATUS_NOT_ENOUGH_DATA in case of insufficient data, and // VP8_STATUS_OK otherwise. // If an alpha chunk is found, *alpha_data and *alpha_size are set // appropriately. static VP8StatusCode ParseOptionalChunks(const uint8_t** const data, size_t* const data_size, size_t const riff_size, const uint8_t** const alpha_data, size_t* const alpha_size) { const uint8_t* buf; size_t buf_size; uint32_t total_size = TAG_SIZE + // "WEBP". CHUNK_HEADER_SIZE + // "VP8Xnnnn". VP8X_CHUNK_SIZE; // data. assert(data != NULL); assert(data_size != NULL); buf = *data; buf_size = *data_size; assert(alpha_data != NULL); assert(alpha_size != NULL); *alpha_data = NULL; *alpha_size = 0; while (1) { uint32_t chunk_size; uint32_t disk_chunk_size; // chunk_size with padding *data = buf; *data_size = buf_size; if (buf_size < CHUNK_HEADER_SIZE) { // Insufficient data. return VP8_STATUS_NOT_ENOUGH_DATA; } chunk_size = get_le32(buf + TAG_SIZE); if (chunk_size > MAX_CHUNK_PAYLOAD) { return VP8_STATUS_BITSTREAM_ERROR; // Not a valid chunk size. } // For odd-sized chunk-payload, there's one byte padding at the end. disk_chunk_size = (CHUNK_HEADER_SIZE + chunk_size + 1) & ~1; total_size += disk_chunk_size; // Check that total bytes skipped so far does not exceed riff_size. if (riff_size > 0 && (total_size > riff_size)) { return VP8_STATUS_BITSTREAM_ERROR; // Not a valid chunk size. } // Start of a (possibly incomplete) VP8/VP8L chunk implies that we have // parsed all the optional chunks. // Note: This check must occur before the check 'buf_size < disk_chunk_size' // below to allow incomplete VP8/VP8L chunks. if (!memcmp(buf, "VP8 ", TAG_SIZE) || !memcmp(buf, "VP8L", TAG_SIZE)) { return VP8_STATUS_OK; } if (buf_size < disk_chunk_size) { // Insufficient data. return VP8_STATUS_NOT_ENOUGH_DATA; } if (!memcmp(buf, "ALPH", TAG_SIZE)) { // A valid ALPH header. *alpha_data = buf + CHUNK_HEADER_SIZE; *alpha_size = chunk_size; } // We have a full and valid chunk; skip it. buf += disk_chunk_size; buf_size -= disk_chunk_size; } }
int __acc_cdecl_qsort le32_compare(const void *e1, const void *e2) { const unsigned d1 = get_le32(e1); const unsigned d2 = get_le32(e2); return (d1 < d2) ? -1 : ((d1 > d2) ? 1 : 0); }
static int idcin_read_header(AVFormatContext *s, AVFormatParameters *ap) { ByteIOContext *pb = &s->pb; IdcinDemuxContext *idcin = (IdcinDemuxContext *)s->priv_data; AVStream *st; unsigned int width, height; unsigned int sample_rate, bytes_per_sample, channels; /* get the 5 header parameters */ width = get_le32(pb); height = get_le32(pb); sample_rate = get_le32(pb); bytes_per_sample = get_le32(pb); channels = get_le32(pb); st = av_new_stream(s, 0); if (!st) return AVERROR_NOMEM; av_set_pts_info(st, 33, 1, 90000); idcin->video_stream_index = st->index; st->codec->codec_type = CODEC_TYPE_VIDEO; st->codec->codec_id = CODEC_ID_IDCIN; st->codec->codec_tag = 0; /* no fourcc */ st->codec->width = width; st->codec->height = height; /* load up the Huffman tables into extradata */ st->codec->extradata_size = HUFFMAN_TABLE_SIZE; st->codec->extradata = av_malloc(HUFFMAN_TABLE_SIZE); if (get_buffer(pb, st->codec->extradata, HUFFMAN_TABLE_SIZE) != HUFFMAN_TABLE_SIZE) return AVERROR_IO; /* save a reference in order to transport the palette */ st->codec->palctrl = &idcin->palctrl; /* if sample rate is 0, assume no audio */ if (sample_rate) { idcin->audio_present = 1; st = av_new_stream(s, 0); if (!st) return AVERROR_NOMEM; av_set_pts_info(st, 33, 1, 90000); idcin->audio_stream_index = st->index; st->codec->codec_type = CODEC_TYPE_AUDIO; st->codec->codec_tag = 1; st->codec->channels = channels; st->codec->sample_rate = sample_rate; st->codec->bits_per_sample = bytes_per_sample * 8; st->codec->bit_rate = sample_rate * bytes_per_sample * 8 * channels; st->codec->block_align = bytes_per_sample * channels; if (bytes_per_sample == 1) st->codec->codec_id = CODEC_ID_PCM_U8; else st->codec->codec_id = CODEC_ID_PCM_S16LE; if (sample_rate % 14 != 0) { idcin->audio_chunk_size1 = (sample_rate / 14) * bytes_per_sample * channels; idcin->audio_chunk_size2 = (sample_rate / 14 + 1) * bytes_per_sample * channels; } else { idcin->audio_chunk_size1 = idcin->audio_chunk_size2 = (sample_rate / 14) * bytes_per_sample * channels; } idcin->current_audio_chunk = 0; } else idcin->audio_present = 1; idcin->next_chunk_is_video = 1; idcin->pts = 0; return 0; }
static int idcin_read_packet(AVFormatContext *s, AVPacket *pkt) { int ret; unsigned int command; unsigned int chunk_size; IdcinDemuxContext *idcin = (IdcinDemuxContext *)s->priv_data; ByteIOContext *pb = &s->pb; int i; int palette_scale; unsigned char r, g, b; unsigned char palette_buffer[768]; if (url_feof(&s->pb)) return AVERROR_IO; if (idcin->next_chunk_is_video) { command = get_le32(pb); if (command == 2) { return AVERROR_IO; } else if (command == 1) { /* trigger a palette change */ idcin->palctrl.palette_changed = 1; if (get_buffer(pb, palette_buffer, 768) != 768) return AVERROR_IO; /* scale the palette as necessary */ palette_scale = 2; for (i = 0; i < 768; i++) if (palette_buffer[i] > 63) { palette_scale = 0; break; } for (i = 0; i < 256; i++) { r = palette_buffer[i * 3 ] << palette_scale; g = palette_buffer[i * 3 + 1] << palette_scale; b = palette_buffer[i * 3 + 2] << palette_scale; idcin->palctrl.palette[i] = (r << 16) | (g << 8) | (b); } } chunk_size = get_le32(pb); /* skip the number of decoded bytes (always equal to width * height) */ url_fseek(pb, 4, SEEK_CUR); chunk_size -= 4; ret= av_get_packet(pb, pkt, chunk_size); if (ret != chunk_size) return AVERROR_IO; pkt->stream_index = idcin->video_stream_index; pkt->pts = idcin->pts; } else { /* send out the audio chunk */ if (idcin->current_audio_chunk) chunk_size = idcin->audio_chunk_size2; else chunk_size = idcin->audio_chunk_size1; ret= av_get_packet(pb, pkt, chunk_size); if (ret != chunk_size) return AVERROR_IO; pkt->stream_index = idcin->audio_stream_index; pkt->pts = idcin->pts; idcin->current_audio_chunk ^= 1; idcin->pts += FRAME_PTS_INC; } if (idcin->audio_present) idcin->next_chunk_is_video ^= 1; return ret; }
static void get_spc_xid6( byte const begin [], int size, track_info_t* out ) { // header byte const* end = begin + size; if ( size < 8 || memcmp( begin, "xid6", 4 ) ) { check( false ); return; } int info_size = get_le32( begin + 4 ); byte const* in = begin + 8; if ( end - in > info_size ) { dprintf( "SPC: Extra data after xid6\n" ); end = in + info_size; } int year = 0; char copyright [256 + 5]; int copyright_len = 0; int const year_len = 5; int disc = 0, track = 0; while ( end - in >= 4 ) { // header int id = in [0]; int data = in [3] * 0x100 + in [2]; int type = in [1]; int len = type ? data : 0; in += 4; if ( len > end - in ) { dprintf( "SPC: xid6 goes past end" ); break; // block goes past end of data } // handle specific block types char* field = NULL; switch ( id ) { case 0x01: field = out->song; break; case 0x02: field = out->game; break; case 0x03: field = out->author; break; case 0x04: field = out->dumper; break; case 0x07: field = out->comment; break; case 0x10: field = out->ost; break; case 0x11: disc = data; break; case 0x12: track = data; break; case 0x14: year = data; break; //case 0x30: // intro length // Many SPCs have intro length set wrong for looped tracks, making it useless /* case 0x30: check( len == 4 ); if ( len >= 4 ) { out->intro_length = get_le32( in ) / 64; if ( out->length > 0 ) { int loop = out->length - out->intro_length; if ( loop >= 2000 ) out->loop_length = loop; } } break; */ case 0x33: check( len == 4 ); if ( len >= 4 ) { out->fade_length = get_le32( in ) / 64; } break; case 0x13: copyright_len = min( len, (int) sizeof copyright - year_len ); memcpy( ©right [year_len], in, copyright_len ); break; default: if ( id < 0x01 || (id > 0x07 && id < 0x10) || (id > 0x14 && id < 0x30) || id > 0x36 ) dprintf( "SPC: Unknown xid6 block: %X\n", (int) id ); break; } if ( field ) { check( type == 1 ); Gme_File::copy_field_( field, (char const*) in, len ); } // skip to next block in += len; // blocks are supposed to be 4-byte aligned with zero-padding... byte const* unaligned = in; while ( (in - begin) & 3 && in < end ) { if ( *in++ != 0 ) { // ...but some files have no padding in = unaligned; //dprintf( "SPC: xid6 info tag wasn't properly padded to align\n" ); break; } } } char* p = ©right [year_len]; if ( year ) { *--p = ' '; // avoid using bloated printf for ( int n = 4; n--; ) { *--p = char (year % 10 + '0'); year /= 10; } copyright_len += year_len; } if ( copyright_len ) Gme_File::copy_field_( out->copyright, p, copyright_len ); if ( disc > 0 && disc <= 9 ) { out->disc [0] = disc + '0'; out->disc [1] = 0; } if ( track > 255 && track < ( ( 100 << 8 ) - 1 ) ) { char* p = ©right [3]; *p = 0; if ( track & 255 ) *--p = char (track & 255); track >>= 8; for ( int n = 2; n-- && track; ) { *--p = char (track % 10 + '0'); track /= 10; } memcpy( out->track, p, ©right [4] - p ); }
static int wv_read_block_header(AVFormatContext *ctx, ByteIOContext *pb) { WVContext *wc = ctx->priv_data; uint32_t tag, ver; int size; int rate, bpp, chan; wc->pos = url_ftell(pb); tag = get_le32(pb); if (tag != MKTAG('w', 'v', 'p', 'k')) return -1; size = get_le32(pb); if(size < 24 || size > WV_BLOCK_LIMIT){ av_log(ctx, AV_LOG_ERROR, "Incorrect block size %i\n", size); return -1; } wc->blksize = size; ver = get_le16(pb); if(ver < 0x402 || ver > 0x410){ av_log(ctx, AV_LOG_ERROR, "Unsupported version %03X\n", ver); return -1; } get_byte(pb); // track no get_byte(pb); // track sub index wc->samples = get_le32(pb); // total samples in file wc->soff = get_le32(pb); // offset in samples of current block get_buffer(pb, wc->extra, WV_EXTRA_SIZE); wc->flags = AV_RL32(wc->extra + 4); //parse flags if(wc->flags & WV_FLOAT){ av_log(ctx, AV_LOG_ERROR, "Floating point data is not supported\n"); return -1; } if(wc->flags & WV_HYBRID){ av_log(ctx, AV_LOG_ERROR, "Hybrid coding mode is not supported\n"); return -1; } bpp = ((wc->flags & 3) + 1) << 3; chan = 1 + !(wc->flags & WV_MONO); rate = wv_rates[(wc->flags >> 23) & 0xF]; if(rate == -1){ av_log(ctx, AV_LOG_ERROR, "Unknown sampling rate\n"); return -1; } if(!wc->bpp) wc->bpp = bpp; if(!wc->chan) wc->chan = chan; if(!wc->rate) wc->rate = rate; if(wc->flags && bpp != wc->bpp){ av_log(ctx, AV_LOG_ERROR, "Bits per sample differ, this block: %i, header block: %i\n", bpp, wc->bpp); return -1; } if(wc->flags && chan != wc->chan){ av_log(ctx, AV_LOG_ERROR, "Channels differ, this block: %i, header block: %i\n", chan, wc->chan); return -1; } if(wc->flags && rate != wc->rate){ av_log(ctx, AV_LOG_ERROR, "Sampling rate differ, this block: %i, header block: %i\n", rate, wc->rate); return -1; } wc->blksize = size - 24; return 0; }
static int mtv_read_header(AVFormatContext *s, AVFormatParameters *ap) { MTVDemuxContext *mtv = s->priv_data; ByteIOContext *pb = s->pb; AVStream *st; url_fskip(pb, 3); mtv->file_size = get_le32(pb); mtv->segments = get_le32(pb); url_fskip(pb, 32); mtv->audio_identifier = get_le24(pb); mtv->audio_br = get_le16(pb); mtv->img_colorfmt = get_le24(pb); mtv->img_bpp = get_byte(pb); mtv->img_width = get_le16(pb); mtv->img_height = get_le16(pb); mtv->img_segment_size = get_le16(pb); url_fskip(pb, 4); mtv->audio_subsegments = get_le16(pb); mtv->video_fps = (mtv->audio_br / 4) / mtv->audio_subsegments; /* FIXME Add sanity check here */ /* first packet is always audio*/ mtv->audio_packet_count = 1; /* all systems go! init decoders */ /* video - raw rgb565 */ st = av_new_stream(s, VIDEO_SID); if(!st) return AVERROR(ENOMEM); av_set_pts_info(st, 64, 1, mtv->video_fps); st->codec->codec_type = CODEC_TYPE_VIDEO; st->codec->codec_id = CODEC_ID_RAWVIDEO; st->codec->codec_tag = MKTAG('R', 'G', 'B', mtv->img_bpp); st->codec->width = mtv->img_width; st->codec->height = mtv->img_height; st->codec->bits_per_sample = mtv->img_bpp; st->codec->sample_rate = mtv->video_fps; /* audio - mp3 */ st = av_new_stream(s, AUDIO_SID); if(!st) return AVERROR(ENOMEM); av_set_pts_info(st, 64, 1, AUDIO_SAMPLING_RATE); st->codec->codec_type = CODEC_TYPE_AUDIO; st->codec->codec_id = CODEC_ID_MP3; st->codec->bit_rate = mtv->audio_br; st->need_parsing = AVSTREAM_PARSE_FULL; /* Jump over header */ if(url_fseek(pb, MTV_HEADER_SIZE, SEEK_SET) != MTV_HEADER_SIZE) return AVERROR(EIO); return 0; }
static int nuv_header(AVFormatContext *s, AVFormatParameters *ap) { NUVContext *ctx = s->priv_data; ByteIOContext *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; get_buffer(pb, id_string, 12); is_mythtv = !memcmp(id_string, "MythTVVideo", 12); url_fskip(pb, 5); // version string url_fskip(pb, 3); // padding width = get_le32(pb); height = get_le32(pb); get_le32(pb); // unused, "desiredwidth" get_le32(pb); // unused, "desiredheight" get_byte(pb); // 'P' == progressive, 'I' == interlaced url_fskip(pb, 3); // padding aspect = av_int2dbl(get_le64(pb)); if (aspect > 0.9999 && aspect < 1.0001) aspect = 4.0 / 3.0; fps = av_int2dbl(get_le64(pb)); // number of packets per stream type, -1 means unknown, e.g. streaming v_packs = get_le32(pb); a_packs = get_le32(pb); get_le32(pb); // text get_le32(pb); // keyframe distance (?) if (v_packs) { ctx->v_id = stream_nr++; vst = av_new_stream(s, ctx->v_id); 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 = av_new_stream(s, ctx->a_id); 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; }
static int wv_read_block_header(AVFormatContext *ctx, ByteIOContext *pb) { WVContext *wc = ctx->priv_data; uint32_t tag, ver; int size; int rate, bpp, chan; wc->pos = url_ftell(pb); tag = get_le32(pb); if (tag != MKTAG('w', 'v', 'p', 'k')) return -1; size = get_le32(pb); if(size < 24 || size > WV_BLOCK_LIMIT){ av_log(ctx, AV_LOG_ERROR, "Incorrect block size %i\n", size); return -1; } wc->blksize = size; ver = get_le16(pb); if(ver < 0x402 || ver > 0x410){ av_log(ctx, AV_LOG_ERROR, "Unsupported version %03X\n", ver); return -1; } get_byte(pb); // track no get_byte(pb); // track sub index wc->samples = get_le32(pb); // total samples in file wc->soff = get_le32(pb); // offset in samples of current block get_buffer(pb, wc->extra, WV_EXTRA_SIZE); wc->flags = AV_RL32(wc->extra + 4); //parse flags bpp = ((wc->flags & 3) + 1) << 3; chan = 1 + !(wc->flags & WV_MONO); rate = wv_rates[(wc->flags >> 23) & 0xF]; if(rate == -1 && !wc->block_parsed){ int64_t block_end = url_ftell(pb) + wc->blksize - 24; if(url_is_streamed(pb)){ av_log(ctx, AV_LOG_ERROR, "Cannot determine custom sampling rate\n"); return -1; } while(url_ftell(pb) < block_end){ int id, size; id = get_byte(pb); size = (id & 0x80) ? get_le24(pb) : get_byte(pb); size <<= 1; if(id&0x40) size--; if((id&0x3F) == 0x27){ rate = get_le24(pb); break; }else{ url_fskip(pb, size); } } if(rate == -1){ av_log(ctx, AV_LOG_ERROR, "Cannot determine custom sampling rate\n"); return -1; } url_fseek(pb, block_end - wc->blksize + 24, SEEK_SET); } if(!wc->bpp) wc->bpp = bpp; if(!wc->chan) wc->chan = chan; if(!wc->rate) wc->rate = rate; if(wc->flags && bpp != wc->bpp){ av_log(ctx, AV_LOG_ERROR, "Bits per sample differ, this block: %i, header block: %i\n", bpp, wc->bpp); return -1; } if(wc->flags && chan != wc->chan){ av_log(ctx, AV_LOG_ERROR, "Channels differ, this block: %i, header block: %i\n", chan, wc->chan); return -1; } if(wc->flags && rate != -1 && rate != wc->rate){ av_log(ctx, AV_LOG_ERROR, "Sampling rate differ, this block: %i, header block: %i\n", rate, wc->rate); return -1; } wc->blksize = size - 24; return 0; }
static int ea_read_packet(AVFormatContext *s, AVPacket *pkt) { EaDemuxContext *ea = s->priv_data; ByteIOContext *pb = s->pb; int ret = 0; int packet_read = 0; unsigned int chunk_type, chunk_size; int key = 0; while (!packet_read) { chunk_type = get_le32(pb); chunk_size = (ea->big_endian ? get_be32(pb) : get_le32(pb)) - 8; switch (chunk_type) { /* audio data */ case ISNh_TAG: /* header chunk also contains data; skip over the header portion*/ url_fskip(pb, 32); chunk_size -= 32; case ISNd_TAG: case SCDl_TAG: case SNDC_TAG: if (!ea->audio_codec) { url_fskip(pb, chunk_size); break; } else if (ea->audio_codec == CODEC_ID_PCM_S16LE_PLANAR) { url_fskip(pb, 12); /* planar header */ chunk_size -= 12; } ret = av_get_packet(pb, pkt, chunk_size); if (ret != chunk_size) ret = AVERROR(EIO); else { pkt->stream_index = ea->audio_stream_index; pkt->pts = 90000; pkt->pts *= ea->audio_frame_counter; pkt->pts /= ea->sample_rate; switch (ea->audio_codec) { case CODEC_ID_ADPCM_EA: /* 2 samples/byte, 1 or 2 samples per frame depending * on stereo; chunk also has 12-byte header */ ea->audio_frame_counter += ((chunk_size - 12) * 2) / ea->num_channels; break; default: ea->audio_frame_counter += chunk_size / (ea->bytes * ea->num_channels); } } packet_read = 1; break; /* ending tag */ case 0: case ISNe_TAG: case SCEl_TAG: case SEND_TAG: ret = AVERROR(EIO); packet_read = 1; break; case MV0K_TAG: key = PKT_FLAG_KEY; case MV0F_TAG: ret = av_get_packet(pb, pkt, chunk_size); if (ret != chunk_size) ret = AVERROR_IO; else { pkt->stream_index = ea->video_stream_index; pkt->flags |= key; } packet_read = 1; break; default: url_fseek(pb, chunk_size, SEEK_CUR); break; } } return ret; }
int main(int argc, char *argv[]) { int i, devfd, c, readlen, writelen; int req_blocks, part1_offset; int ubl_size = 0, uboot_size; struct rbl_header *rblp; unsigned int uboot_load_address = 0, uboot_entry_point = 0; unsigned int uboot_sign_start = 0, uboot_start_block = 0; while ((c = getopt(argc, argv, "?hvd:u:b:l:e:p:")) >= 0) { switch (c) { case 'd': dev_name = optarg; break; case 'u': ubl_name = optarg; break; case 'l': uboot_load_address = strtoul(optarg, NULL, 16); break; case 'e': uboot_entry_point = strtoul(optarg, NULL, 16); break; case 'v': verbose++; break; case 'b': uboot_name = optarg; break; case 'p': platform = optarg; for (i = 0; i < strlen(platform) - 1; i++) platform[i] = toupper(platform[i]); printf("%s\n", platform); break; case 'h': case '?': usage(); return 0; } } if (!ubl_name) uboot_start_block = UBL_START_BLOCK; if (!strcmp(platform, "DM3XX")) { if (!uboot_load_address) uboot_load_address = DM3XX_UBOOT_LOAD_ADDRESS; if (!uboot_entry_point) uboot_entry_point = DM3XX_UBOOT_LOAD_ADDRESS; } if (!strcmp(platform, "OMAPL138")) { if (!uboot_load_address) uboot_load_address = DA850_UBOOT_LOAD_ADDRESS; if (!uboot_entry_point) uboot_entry_point = DA850_UBOOT_LOAD_ADDRESS; } /* Open the SD/MMC Device in Read-Write Mode */ devfd = open(dev_name, O_RDWR); if (devfd <= 0) { fprintf(stderr, "Device open Error : %s\n", strerror(errno)); exit(-1); } /* Read Master Boot Record - MBR */ readlen = read(devfd, readbuf, BLOCK_SIZE); if (readlen < 0) fprintf(stderr, "Device Read Error : %s\n", strerror(errno)); if (verbose > 2) { printf("====================Master Boot Record============\n"); print_hex(readbuf, BLOCK_SIZE); printf("==================================================\n"); } /* Get UBL file size and round it to upper 512 byte boundary */ // if (!strcmp(platform, "DM3XX")) { if (ubl_name) { ubl_size = get_file_size(ubl_name); if (ubl_size < 0) { close(devfd); return -1; } ubl_size = (ubl_size + BLOCK_SIZE - 1) & ~BLOCK_SIZE; verbose_printf("UBL Size %d\n", ubl_size); } if (uboot_name) { uboot_size = get_file_size(uboot_name); uboot_size = (uboot_size + BLOCK_SIZE - 1) & ~BLOCK_SIZE; verbose_printf("U-Boot Size %d\n", uboot_size); if (uboot_size <= 0) { fprintf(stderr, "Invalid U-Boot Size %d\n", uboot_size); close(devfd); return -1; } } /* Get U-boot file size and round it to upper 512 byte boundary */ // uboot_size = get_file_size(uboot_name); // if (uboot_size <= 0) { // fprintf(stderr, "Invalid U-Boot Size %d\n", uboot_size); // close(devfd); // return -1; // } /* Get first partition start address offset from Master Boot Record */ part1_offset = get_le32 (&readbuf[PART1_LBA_OFFSET]); verbose_printf("First partition starts at %d(%ld)\n", part1_offset, (part1_offset * BLOCK_SIZE)); /* Add MBR + UBL Size + Uboot Size */ // if (!(strcmp(platform, "DM3XX"))) { if (ubl_name) { req_blocks = UBL_START_BLOCK + (ubl_size / BLOCK_SIZE) + UBL_BLOCK_OFFSET + (uboot_size / BLOCK_SIZE) + 1; printf("Required Blocks %d, Available Blocks %d\n", req_blocks, part1_offset - 1); /* * Return if the card does not have enough * space for writing UBL/Uboot */ if (req_blocks > part1_offset) { fprintf(stderr, "Not enough space left for " "flashing UBL and U-boot\n"); fprintf(stderr, "Make sure that the First Partition " " Starts after %d sectors\n", req_blocks); close(devfd); return -1; } /* Generate UBL Signature */ rblp = (struct rbl_header *)ubl_signature; memset(rblp, 0, sizeof(struct rbl_header)); rblp->magic_num = UBL_MAGIC_NUM; rblp->entry_point = UBL_ENTRY_POINT; rblp->num_blocks = ubl_size / BLOCK_SIZE; rblp->start_block = UBL_START_BLOCK; if (verbose > 1) { printf("UBL Magic Number : %08x\n", rblp->magic_num); printf("UBL Entry Point : %08x\n", rblp->entry_point); printf("UBL Number of Blocks : %08x\n", rblp->num_blocks); printf("UBL Starting Block : %08x\n", rblp->start_block); printf("UBL Load Address : %08x\n", rblp->load_address); } /* Write UBL Signature verbose_printf("Writing UBL Signature\n"); lseek(devfd, (BLOCK_SIZE * UBL_SIGN_START), SEEK_SET); for (i = UBL_SIGN_START; i < (UBL_SIGN_COUNT + UBL_SIGN_START); i++) { writelen = write(devfd, rblp, BLOCK_SIZE); if (writelen < BLOCK_SIZE) { close(devfd); return -1; } } */ /* Write UBL Binary */ verbose_printf("Writing UBL\n"); // lseek(devfd, (BLOCK_SIZE * rblp->start_block), SEEK_SET); write_file(devfd, ubl_name); } if (!uboot_name) { close(devfd); return 0; } /* Generate U-boot signature */ rblp = (struct rbl_header *)uboot_signature; memset(rblp, 0, sizeof(struct rbl_header)); rblp->magic_num = UBOOT_MAGIC_NUM; rblp->entry_point = uboot_entry_point; rblp->num_blocks = (uboot_size / BLOCK_SIZE) + 1; if (!strcmp(platform, "DM3XX")) { rblp->start_block = UBL_START_BLOCK + (ubl_size / BLOCK_SIZE) + UBL_BLOCK_OFFSET; } else if (!strcmp(platform, "OMAPL138")) { rblp->start_block = uboot_start_block; uboot_sign_start = 1; } else { printf("error\n"); return -1; } rblp->load_address = uboot_load_address; if (verbose > 1) { printf("U-Boot Magic Number : %08x\n", rblp->magic_num); printf("U-Boot Entry Point : %08x\n", rblp->entry_point); printf("U-Boot Number of Blocks : %08x\n", rblp->num_blocks); printf("U-Boot Starting Block : %08x\n", rblp->start_block); printf("Load U-Boot Address : %08x\n", rblp->load_address); } /* Write U-Boot Signature */ verbose_printf("Writing U-Boot Signature\n"); if (!strcmp(platform, "DM3XX")) lseek(devfd, (BLOCK_SIZE * UBOOT_SIGN_START), SEEK_SET); else lseek(devfd, (BLOCK_SIZE * uboot_sign_start), SEEK_SET); for (i = UBOOT_SIGN_START; i < (UBOOT_SIGN_COUNT + UBOOT_SIGN_START); i++) { writelen = write(devfd, rblp, BLOCK_SIZE); if (writelen < BLOCK_SIZE) { close(devfd); return -1; } } /* Write U-Boot File */ lseek(devfd, (BLOCK_SIZE * rblp->start_block), SEEK_SET); verbose_printf("Writing U-Boot\n"); write_file(devfd, uboot_name); printf("Done...\n"); close(devfd); return 0; }
static int rpl_read_packet(AVFormatContext *s, AVPacket *pkt) { RPLContext *rpl = s->priv_data; ByteIOContext *pb = s->pb; AVStream* stream; AVIndexEntry* index_entry; uint32_t ret; if (rpl->chunk_part == s->nb_streams) { rpl->chunk_number++; rpl->chunk_part = 0; } stream = s->streams[rpl->chunk_part]; if (rpl->chunk_number >= stream->nb_index_entries) return -1; index_entry = &stream->index_entries[rpl->chunk_number]; if (rpl->frame_in_part == 0) if (url_fseek(pb, index_entry->pos, SEEK_SET) < 0) return AVERROR(EIO); if (stream->codec->codec_type == AVMEDIA_TYPE_VIDEO && stream->codec->codec_tag == 124) { // We have to split Escape 124 frames because there are // multiple frames per chunk in Escape 124 samples. uint32_t frame_size, frame_flags; frame_flags = get_le32(pb); frame_size = get_le32(pb); if (url_fseek(pb, -8, SEEK_CUR) < 0) return AVERROR(EIO); ret = av_get_packet(pb, pkt, frame_size); if (ret != frame_size) { av_free_packet(pkt); return AVERROR(EIO); } pkt->duration = 1; pkt->pts = index_entry->timestamp + rpl->frame_in_part; pkt->stream_index = rpl->chunk_part; rpl->frame_in_part++; if (rpl->frame_in_part == rpl->frames_per_chunk) { rpl->frame_in_part = 0; rpl->chunk_part++; } } else { ret = av_get_packet(pb, pkt, index_entry->size); if (ret != index_entry->size) { av_free_packet(pkt); return AVERROR(EIO); } if (stream->codec->codec_type == AVMEDIA_TYPE_VIDEO) { // frames_per_chunk should always be one here; the header // parsing will warn if it isn't. pkt->duration = rpl->frames_per_chunk; } else { // All the audio codecs supported in this container // (at least so far) are constant-bitrate. pkt->duration = ret * 8; } pkt->pts = index_entry->timestamp; pkt->stream_index = rpl->chunk_part; rpl->chunk_part++; } // None of the Escape formats have keyframes, and the ADPCM // format used doesn't have keyframes. if (rpl->chunk_number == 0 && rpl->frame_in_part == 0) pkt->flags |= AV_PKT_FLAG_KEY; return ret; }
blargg_err_t Zip_Extractor::update_info( bool advance_first ) { while ( 1 ) { entry_t& e = (entry_t&) catalog [catalog_pos]; if ( memcmp( e.type, "\0K\1\2P", 5 ) && memcmp( e.type, "PK\1\2", 4 ) ) { check( !memcmp( e.type, "\0K\5\6P", 5 ) ); break; } unsigned len = get_le16( e.filename_len ); int next_offset = catalog_pos + entry_size + len + get_le16( e.extra_len ) + get_le16( e.comment_len ); if ( (unsigned) next_offset > catalog.size() - end_entry_size ) return blargg_err_file_corrupt; if ( catalog [next_offset] == 'P' ) reorder_entry_header( next_offset ); if ( !advance_first ) { char unterminate = e.filename[len]; e.filename [len] = 0; // terminate name std::string fname = e.filename; if ( is_normal_file( e, len ) ) { e.filename[len] = unterminate; name.resize(fname.size()+1); if(len != 0) { memcpy(name.begin(),fname.c_str(),len); name[name.size()-1] = 0; } set_name( name.begin() ); set_info( get_le32( e.size ), get_le32( e.date ), get_le32( e.crc ) ); unsigned extra_len = get_le32(e.extra_len); //walk over extra fields unsigned i = len; while(i < extra_len + len) { unsigned id = get_le16(e.filename + i); i += 2; unsigned exlen = get_le16(e.filename + i); i += 2; int exfield = i; i += exlen; if(id == 0x7075) //INFO-ZIP unicode path extra field (contains version, checksum, and utf-8 filename) { unsigned version = (unsigned char)*(e.filename + exfield); if(version == 1) { exfield += 1; //skip version exfield += 4; //skip crc //the remainder is a utf-8 filename int fnamelen = exlen-5; char* tempbuf = (char*)malloc(fnamelen + 1); memcpy(tempbuf,e.filename + exfield, fnamelen); tempbuf[fnamelen] = 0; wchar_t* wfname_buf = blargg_to_wide(tempbuf); std::wstring wfname = wfname_buf; free(tempbuf); free(wfname_buf); size_t wfname_len = wfname.size(); this->wname.resize(wfname_len+1); if(wfname_len != 0) { memcpy(this->wname.begin(),wfname.c_str(),wfname_len*sizeof(wchar_t)); wname[wname.size()-1] = 0; } set_name( name.begin(), wname.begin() ); } } } break; } } catalog_pos = next_offset; advance_first = false; } return blargg_ok; }
static int read_header(AVFormatContext *s, AVFormatParameters *ap) { AnmDemuxContext *anm = s->priv_data; ByteIOContext *pb = s->pb; AVStream *st; int i, ret; url_fskip(pb, 4); /* magic number */ if (get_le16(pb) != MAX_PAGES) { av_log_ask_for_sample(s, "max_pages != " AV_STRINGIFY(MAX_PAGES) "\n"); return AVERROR_INVALIDDATA; } anm->nb_pages = get_le16(pb); anm->nb_records = get_le32(pb); url_fskip(pb, 2); /* max records per page */ anm->page_table_offset = get_le16(pb); if (get_le32(pb) != ANIM_TAG) return AVERROR_INVALIDDATA; /* video stream */ st = av_new_stream(s, 0); if (!st) return AVERROR(ENOMEM); st->codec->codec_type = AVMEDIA_TYPE_VIDEO; st->codec->codec_id = CODEC_ID_ANM; st->codec->codec_tag = 0; /* no fourcc */ st->codec->width = get_le16(pb); st->codec->height = get_le16(pb); if (get_byte(pb) != 0) goto invalid; url_fskip(pb, 1); /* frame rate multiplier info */ /* ignore last delta record (used for looping) */ if (get_byte(pb)) /* has_last_delta */ anm->nb_records = FFMAX(anm->nb_records - 1, 0); url_fskip(pb, 1); /* last_delta_valid */ if (get_byte(pb) != 0) goto invalid; if (get_byte(pb) != 1) goto invalid; url_fskip(pb, 1); /* other recs per frame */ if (get_byte(pb) != 1) goto invalid; url_fskip(pb, 32); /* record_types */ st->nb_frames = get_le32(pb); av_set_pts_info(st, 64, 1, get_le16(pb)); url_fskip(pb, 58); /* color cycling and palette data */ st->codec->extradata_size = 16*8 + 4*256; st->codec->extradata = av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); if (!st->codec->extradata) { ret = AVERROR(ENOMEM); goto close_and_return; } ret = get_buffer(pb, st->codec->extradata, st->codec->extradata_size); if (ret < 0) goto close_and_return; /* read page table */ ret = url_fseek(pb, anm->page_table_offset, SEEK_SET); if (ret < 0) goto close_and_return; for (i = 0; i < MAX_PAGES; i++) { Page *p = &anm->pt[i]; p->base_record = get_le16(pb); p->nb_records = get_le16(pb); p->size = get_le16(pb); } /* find page of first frame */ anm->page = find_record(anm, 0); if (anm->page < 0) { ret = anm->page; goto close_and_return; } anm->record = -1; return 0; invalid: av_log_ask_for_sample(s, NULL); ret = AVERROR_INVALIDDATA; close_and_return: av_close_input_stream(s); return ret; }
/* aiff input */ static int aiff_read_header(AVFormatContext *s, AVFormatParameters *ap) { int size, filesize, offset; uint32_t tag; unsigned version = AIFF_C_VERSION1; ByteIOContext *pb = &s->pb; AVStream * st = s->streams[0]; /* check FORM header */ filesize = get_tag(pb, &tag); if (filesize < 0 || tag != MKTAG('F', 'O', 'R', 'M')) return AVERROR_INVALIDDATA; /* AIFF data type */ tag = get_le32(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_NOMEM; 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; break; case MKTAG('F', 'V', 'E', 'R'): /* Version chunk */ version = get_be32(pb); break; case MKTAG('N', 'A', 'M', 'E'): /* Sample name chunk */ get_meta (pb, s->title, sizeof(s->title), size); break; case MKTAG('A', 'U', 'T', 'H'): /* Author chunk */ get_meta (pb, s->author, sizeof(s->author), size); break; case MKTAG('(', 'c', ')', ' '): /* Copyright chunk */ get_meta (pb, s->copyright, sizeof(s->copyright), size); break; case MKTAG('A', 'N', 'N', 'O'): /* Annotation chunk */ get_meta (pb, s->comment, sizeof(s->comment), size); break; case MKTAG('S', 'S', 'N', 'D'): /* Sampled sound chunk */ get_be32(pb); /* Block align... don't care */ offset = get_be32(pb); /* Offset of sound data */ goto got_sound; default: /* Jump */ if (size & 1) /* Always even aligned */ size++; url_fskip (pb, size); } } /* End of loop and didn't get sound */ return AVERROR_INVALIDDATA; 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->nb_frames; /* Position the stream at the first block */ url_fskip(pb, offset); return 0; }
static int fourxm_read_packet(AVFormatContext *s, AVPacket *pkt) { FourxmDemuxContext *fourxm = s->priv_data; ByteIOContext *pb = &s->pb; unsigned int fourcc_tag; unsigned int size, out_size; int ret = 0; int track_number; int packet_read = 0; unsigned char header[8]; int audio_frame_count; while (!packet_read) { if ((ret = get_buffer(&s->pb, header, 8)) < 0) return ret; fourcc_tag = AV_RL32(&header[0]); size = AV_RL32(&header[4]); if (url_feof(pb)) return AVERROR(EIO); switch (fourcc_tag) { case LIST_TAG: /* this is a good time to bump the video pts */ fourxm->video_pts ++; /* skip the LIST-* tag and move on to the next fourcc */ get_le32(pb); break; case ifrm_TAG: case pfrm_TAG: case cfrm_TAG: case ifr2_TAG: case pfr2_TAG: case cfr2_TAG: { /* allocate 8 more bytes than 'size' to account for fourcc * and size */ if (size + 8 < size || av_new_packet(pkt, size + 8)) return AVERROR(EIO); pkt->stream_index = fourxm->video_stream_index; pkt->pts = fourxm->video_pts; pkt->pos = url_ftell(&s->pb); memcpy(pkt->data, header, 8); ret = get_buffer(&s->pb, &pkt->data[8], size); if (ret < 0) av_free_packet(pkt); else packet_read = 1; break; } case snd__TAG: track_number = get_le32(pb); out_size= get_le32(pb); size-=8; if (track_number == fourxm->selected_track) { ret= av_get_packet(&s->pb, pkt, size); if(ret<0) return AVERROR(EIO); pkt->stream_index = fourxm->tracks[fourxm->selected_track].stream_index; pkt->pts = fourxm->audio_pts; packet_read = 1; /* pts accounting */ audio_frame_count = size; if (fourxm->tracks[fourxm->selected_track].adpcm) audio_frame_count -= 2 * (fourxm->tracks[fourxm->selected_track].channels); audio_frame_count /= fourxm->tracks[fourxm->selected_track].channels; if (fourxm->tracks[fourxm->selected_track].adpcm) audio_frame_count *= 2; else audio_frame_count /= (fourxm->tracks[fourxm->selected_track].bits / 8); fourxm->audio_pts += audio_frame_count; } else { url_fseek(pb, size, SEEK_CUR); } break; default: url_fseek(pb, size, SEEK_CUR); break; } } return ret; }
/* mmf input */ static int mmf_read_header(AVFormatContext *s, AVFormatParameters *ap) { MMFContext *mmf = s->priv_data; unsigned int tag; ByteIOContext *pb = &s->pb; AVStream *st; offset_t file_size, size; int rate, params; tag = get_le32(pb); if (tag != MKTAG('M', 'M', 'M', 'D')) return -1; file_size = get_be32(pb); /* Skip some unused chunks that may or may not be present */ for(;; url_fseek(pb, size, SEEK_CUR)) { tag = get_le32(pb); size = get_be32(pb); if(tag == MKTAG('C','N','T','I')) continue; if(tag == MKTAG('O','P','D','A')) continue; break; } /* Tag = "ATRx", where "x" = track number */ if ((tag & 0xffffff) == MKTAG('M', 'T', 'R', 0)) { av_log(s, AV_LOG_ERROR, "MIDI like format found, unsupported\n"); return -1; } if ((tag & 0xffffff) != MKTAG('A', 'T', 'R', 0)) { av_log(s, AV_LOG_ERROR, "Unsupported SMAF chunk %08x\n", tag); return -1; } get_byte(pb); /* format type */ get_byte(pb); /* sequence type */ params = get_byte(pb); /* (channel << 7) | (format << 4) | rate */ rate = mmf_rate(params & 0x0f); if(rate < 0) { av_log(s, AV_LOG_ERROR, "Invalid sample rate\n"); return -1; } get_byte(pb); /* wave base bit */ get_byte(pb); /* time base d */ get_byte(pb); /* time base g */ /* Skip some unused chunks that may or may not be present */ for(;; url_fseek(pb, size, SEEK_CUR)) { tag = get_le32(pb); size = get_be32(pb); if(tag == MKTAG('A','t','s','q')) continue; if(tag == MKTAG('A','s','p','I')) continue; break; } /* Make sure it's followed by an Awa chunk, aka wave data */ if ((tag & 0xffffff) != MKTAG('A', 'w', 'a', 0)) { av_log(s, AV_LOG_ERROR, "Unexpected SMAF chunk %08x\n", tag); return -1; } mmf->data_size = size; st = av_new_stream(s, 0); if (!st) return AVERROR_NOMEM; st->codec->codec_type = CODEC_TYPE_AUDIO; st->codec->codec_id = CODEC_ID_ADPCM_YAMAHA; st->codec->sample_rate = rate; st->codec->channels = 1; st->codec->bits_per_sample = 4; st->codec->bit_rate = st->codec->sample_rate * st->codec->bits_per_sample; av_set_pts_info(st, 64, 1, st->codec->sample_rate); return 0; }
static void ape_parse_tag(AVFormatContext *s) { ByteIOContext *pb = s->pb; int file_size = url_fsize(pb); uint32_t val, fields, tag_bytes; uint8_t buf[8]; int i; if (file_size < APE_TAG_FOOTER_BYTES) return; url_fseek(pb, file_size - APE_TAG_FOOTER_BYTES, SEEK_SET); get_buffer(pb, buf, 8); /* APETAGEX */ if (strncmp(buf, "APETAGEX", 8)) { return; } val = get_le32(pb); /* APE tag version */ if (val > APE_TAG_VERSION) { av_log(s, AV_LOG_ERROR, "Unsupported tag version. (>=%d)\n", APE_TAG_VERSION); return; } tag_bytes = get_le32(pb); /* tag size */ if (tag_bytes - APE_TAG_FOOTER_BYTES > (1024 * 1024 * 16)) { av_log(s, AV_LOG_ERROR, "Tag size is way too big\n"); return; } fields = get_le32(pb); /* number of fields */ if (fields > 65536) { av_log(s, AV_LOG_ERROR, "Too many tag fields (%d)\n", fields); return; } val = get_le32(pb); /* flags */ if (val & APE_TAG_FLAG_IS_HEADER) { av_log(s, AV_LOG_ERROR, "APE Tag is a header\n"); return; } if (val & APE_TAG_FLAG_CONTAINS_HEADER) tag_bytes += 2*APE_TAG_FOOTER_BYTES; url_fseek(pb, file_size - tag_bytes, SEEK_SET); for (i=0; i<fields; i++) ape_tag_read_field(s); #if ENABLE_DEBUG av_log(s, AV_LOG_DEBUG, "\nAPE Tags:\n\n"); av_log(s, AV_LOG_DEBUG, "title = %s\n", s->title); av_log(s, AV_LOG_DEBUG, "author = %s\n", s->author); av_log(s, AV_LOG_DEBUG, "copyright = %s\n", s->copyright); av_log(s, AV_LOG_DEBUG, "comment = %s\n", s->comment); av_log(s, AV_LOG_DEBUG, "album = %s\n", s->album); av_log(s, AV_LOG_DEBUG, "year = %d\n", s->year); av_log(s, AV_LOG_DEBUG, "track = %d\n", s->track); av_log(s, AV_LOG_DEBUG, "genre = %s\n", s->genre); #endif }
/* * Process EA file header * Returns 1 if the EA file is valid and successfully opened, 0 otherwise */ int CEASpliterFilter::process_header() { uint32_t blockid, size = 0; int i; EaDemuxContext *ea = (EaDemuxContext *)m_pea; for (i=0; i<5 && (!ea->audio_codec || !ea->video_codec); i++) { unsigned int startpos = m_pFile->GetPos(); int err = 0; blockid = get_le32(pb); av_log(s, AV_LOG_ERROR, " %x\n", blockid); size = get_le32(pb); if (i == 0) ea->big_endian = size > 0x000FFFFF; if (ea->big_endian) size = bswap_32(size); switch (blockid) { case ISNh_TAG: if (m_pFile->BitRead(32) != EACS_TAG) { av_log (s, AV_LOG_ERROR, "unknown 1SNh headerid\n"); return 0; } err = process_audio_header_eacs(); break; case SCHl_TAG : case SHEN_TAG : blockid = get_le32(pb); if (blockid == GSTR_TAG) { url_fskip(pb, 4); } else if ((blockid & 0xFFFF)!=PT00_TAG) { av_log (s, AV_LOG_ERROR, "unknown SCHl headerid %x\n", blockid); return 0; } err = process_audio_header_elements(); break; case SEAD_TAG: err = process_audio_header_sead(); break; case MVIh_TAG : ea->video_codec = CODEC_ID_CMV; ea->time_base.num = 0; ea->time_base.den = 0; break; case kVGT_TAG: ea->video_codec = CODEC_ID_TGV; ea->time_base.num = 0; ea->time_base.den = 0; break; case mTCD_TAG : err = process_video_header_mdec(); break; case MPCh_TAG: ea->video_codec = CODEC_ID_MPEG2VIDEO; break; case pQGT_TAG: case TGQs_TAG: ea->video_codec = CODEC_ID_TGQ; break; case pIQT_TAG: ea->video_codec = CODEC_ID_TQI; break; case MADk_TAG : ea->video_codec = CODEC_ID_MAD; break; case MVhd_TAG : err = process_video_header_vp6(); break; default: av_log(s, AV_LOG_ERROR, "error parsing header: %x\n", blockid); break; } if (err < 0) { av_log(s, AV_LOG_ERROR, "error parsing header: %i\n", err); return err; } //url_fseek(pb, startpos + size, SEEK_SET); m_pFile->Seek( startpos + size); } //url_fseek(pb, 0, SEEK_SET); m_pFile->Seek(0); return 1; }
static void get_spc_xid6( byte const* begin, long size, track_info_t* out ) { // header byte const* end = begin + size; if ( size < 8 || memcmp( begin, "xid6", 4 ) ) { check( false ); return; } long info_size = get_le32( begin + 4 ); byte const* in = begin + 8; if ( end - in > info_size ) { ddprintf( "Extra data after SPC xid6 info\n" ); end = in + info_size; } int year = 0; char copyright [256 + 5]; int copyright_len = 0; int const year_len = 5; while ( end - in >= 4 ) { // header int id = in [0]; int data = in [3] * 0x100 + in [2]; int type = in [1]; int len = type ? data : 0; in += 4; if ( len > end - in ) { check( false ); break; // block goes past end of data } // handle specific block types char* field = 0; switch ( id ) { case 0x01: field = out->song; break; case 0x02: field = out->game; break; case 0x03: field = out->author; break; case 0x04: field = out->dumper; break; case 0x07: field = out->comment; break; case 0x14: year = data; break; //case 0x30: // intro length // Many SPCs have intro length set wrong for looped tracks, making it useless /* case 0x30: check( len == 4 ); if ( len >= 4 ) { out->intro_length = get_le32( in ) / 64; if ( out->length > 0 ) { long loop = out->length - out->intro_length; if ( loop >= 2000 ) out->loop_length = loop; } } break; */ case 0x13: copyright_len = min( len, (int) sizeof copyright - year_len ); memcpy( ©right [year_len], in, copyright_len ); break; default: if ( id < 0x01 || (id > 0x07 && id < 0x10) || (id > 0x14 && id < 0x30) || id > 0x36 ) ddprintf( "Unknown SPC xid6 block: %X\n", (int) id ); break; } if ( field ) { check( type == 1 ); Gme_File::copy_field_( field, (char const*) in, len ); } // skip to next block in += len; // blocks are supposed to be 4-byte aligned with zero-padding... byte const* unaligned = in; while ( (in - begin) & 3 && in < end ) { if ( *in++ != 0 ) { // ...but some files have no padding in = unaligned; ddprintf( "SPC info tag wasn't properly padded to align\n" ); break; } } } char* p = ©right [year_len]; if ( year ) { *--p = ' '; for ( int n = 4; n--; ) { *--p = char (year % 10 + '0'); year /= 10; } copyright_len += year_len; } if ( copyright_len ) Gme_File::copy_field_( out->copyright, p, copyright_len ); check( in == end ); }
int CEASpliterFilter::ea_read_packet() { EaDemuxContext *ea = (EaDemuxContext *)m_pea; AVPacket *pkt = (AVPacket *)m_pkt; //ByteIOContext *pb = s->pb; int ret = 0; int packet_read = 0; unsigned int chunk_type, chunk_size; int key = 0; int av_uninit(num_samples); while (!packet_read) { chunk_type = get_le32(pb); chunk_size = (ea->big_endian ? get_be32(pb) : get_le32(pb)) - 8; switch (chunk_type) { /* audio data */ case ISNh_TAG: /* header chunk also contains data; skip over the header portion*/ url_fskip(pb, 32); chunk_size -= 32; case ISNd_TAG: case SCDl_TAG: case SNDC_TAG: case SDEN_TAG: if (!ea->audio_codec) { url_fskip(pb, chunk_size); break; } else if (ea->audio_codec == CODEC_ID_PCM_S16LE_PLANAR || ea->audio_codec == CODEC_ID_MP3) { num_samples = get_le32(pb); url_fskip(pb, 8); chunk_size -= 12; } ret = eav_get_packet( chunk_size); if (ret < 0) return ret; pkt->stream_index = ea->audio_stream_index; pkt->pts = 90000; pkt->pts *= ea->audio_frame_counter; pkt->pts /= ea->sample_rate; switch (ea->audio_codec) { case CODEC_ID_ADPCM_EA: /* 2 samples/byte, 1 or 2 samples per frame depending * on stereo; chunk also has 12-byte header */ ea->audio_frame_counter += ((chunk_size - 12) * 2) / ea->num_channels; break; case CODEC_ID_PCM_S16LE_PLANAR: case CODEC_ID_MP3: ea->audio_frame_counter += num_samples; break; default: ea->audio_frame_counter += chunk_size / (ea->bytes * ea->num_channels); } packet_read = 1; break; /* ending tag */ case 0: case ISNe_TAG: case SCEl_TAG: case SEND_TAG: case SEEN_TAG: ret = AVERROR(EIO); packet_read = 1; break; case MVIh_TAG: case kVGT_TAG: case pQGT_TAG: case TGQs_TAG: case MADk_TAG: key = PKT_FLAG_KEY; case MVIf_TAG: case fVGT_TAG: case MADm_TAG: case MADe_TAG: url_fseek(pb, -8, SEEK_CUR); // include chunk preamble chunk_size += 8; goto get_video_packet; case mTCD_TAG: url_fseek(pb, 8, SEEK_CUR); // skip ea dct header chunk_size -= 8; goto get_video_packet; case MV0K_TAG: case MPCh_TAG: case pIQT_TAG: key = PKT_FLAG_KEY; case MV0F_TAG: get_video_packet: ret = eav_get_packet( chunk_size); if (ret < 0) return ret; pkt->stream_index = ea->video_stream_index; pkt->flags |= key; packet_read = 1; break; default: url_fseek(pb, chunk_size, SEEK_CUR); break; } } return ret; }
static int read_packet(AVFormatContext *s, AVPacket *pkt) { ByteIOContext *pb = s->pb; C93DemuxContext *c93 = s->priv_data; C93BlockRecord *br = &c93->block_records[c93->current_block]; int datasize; int ret, i; if (c93->next_pkt_is_audio) { c93->current_frame++; c93->next_pkt_is_audio = 0; datasize = get_le16(pb); if (datasize > 42) { if (!c93->audio) { c93->audio = av_new_stream(s, 1); if (!c93->audio) return AVERROR(ENOMEM); c93->audio->codec->codec_type = AVMEDIA_TYPE_AUDIO; } url_fskip(pb, 26); /* VOC header */ ret = voc_get_packet(s, pkt, c93->audio, datasize - 26); if (ret > 0) { pkt->stream_index = 1; pkt->flags |= AV_PKT_FLAG_KEY; return ret; } } } if (c93->current_frame >= br->frames) { if (c93->current_block >= 511 || !br[1].length) return AVERROR(EIO); br++; c93->current_block++; c93->current_frame = 0; } if (c93->current_frame == 0) { url_fseek(pb, br->index * 2048, SEEK_SET); for (i = 0; i < 32; i++) { c93->frame_offsets[i] = get_le32(pb); } } url_fseek(pb,br->index * 2048 + c93->frame_offsets[c93->current_frame], SEEK_SET); datasize = get_le16(pb); /* video frame size */ ret = av_new_packet(pkt, datasize + 768 + 1); if (ret < 0) return ret; pkt->data[0] = 0; pkt->size = datasize + 1; ret = get_buffer(pb, pkt->data + 1, datasize); if (ret < datasize) { ret = AVERROR(EIO); goto fail; } datasize = get_le16(pb); /* palette size */ if (datasize) { if (datasize != 768) { av_log(s, AV_LOG_ERROR, "invalid palette size %u\n", datasize); ret = AVERROR_INVALIDDATA; goto fail; } pkt->data[0] |= C93_HAS_PALETTE; ret = get_buffer(pb, pkt->data + pkt->size, datasize); if (ret < datasize) { ret = AVERROR(EIO); goto fail; } pkt->size += 768; } pkt->stream_index = 0; c93->next_pkt_is_audio = 1; /* only the first frame is guaranteed to not reference previous frames */ if (c93->current_block == 0 && c93->current_frame == 0) { pkt->flags |= AV_PKT_FLAG_KEY; pkt->data[0] |= C93_FIRST_FRAME; } return 0; fail: av_free_packet(pkt); return ret; }
void PackUnix::unpack(OutputFile *fo) { unsigned szb_info = sizeof(b_info); { Elf32_Ehdr ehdr; fi->seek(0, SEEK_SET); fi->readx(&ehdr, sizeof(ehdr)); unsigned const e_entry = get_te32(&ehdr.e_entry); if (e_entry < 0x401180) { /* old style, 8-byte b_info */ szb_info = 2*sizeof(unsigned); } else { Elf32_Phdr phdr; fi->seek(get_te32(&ehdr.e_phoff), SEEK_SET); fi->readx(&phdr, sizeof(phdr)); unsigned const p_vaddr = get_te32(&phdr.p_vaddr); if (0x80==(e_entry - p_vaddr)) { /* 1.22 old style */ szb_info = 2*sizeof(unsigned); } } } unsigned c_adler = upx_adler32(NULL, 0); unsigned u_adler = upx_adler32(NULL, 0); // defaults for ph.version == 8 unsigned orig_file_size = 0; blocksize = 512 * 1024; fi->seek(overlay_offset, SEEK_SET); if (ph.version > 8) { p_info hbuf; fi->readx(&hbuf, sizeof(hbuf)); orig_file_size = get_te32(&hbuf.p_filesize); blocksize = get_te32(&hbuf.p_blocksize); if (file_size > (off_t)orig_file_size || blocksize > orig_file_size) throwCantUnpack("file header corrupted"); } else { // skip 4 bytes (program id) fi->seek(4, SEEK_CUR); } ibuf.alloc(blocksize + OVERHEAD); // decompress blocks unsigned total_in = 0; unsigned total_out = 0; b_info bhdr; memset(&bhdr, 0, sizeof(bhdr)); for (;;) { #define buf ibuf int i; unsigned sz_unc, sz_cpr; fi->readx(&bhdr, szb_info); ph.u_len = sz_unc = get_te32(&bhdr.sz_unc); ph.c_len = sz_cpr = get_te32(&bhdr.sz_cpr); if (sz_unc == 0) // uncompressed size 0 -> EOF { // note: must reload sz_cpr as magic is always stored le32 sz_cpr = get_le32(&bhdr.sz_cpr); if (sz_cpr != UPX_MAGIC_LE32) // sz_cpr must be h->magic throwCompressedDataViolation(); break; } if (sz_unc <= 0 || sz_cpr <= 0) throwCompressedDataViolation(); if (sz_cpr > sz_unc || sz_unc > blocksize) throwCompressedDataViolation(); i = blocksize + OVERHEAD - sz_cpr; fi->readx(buf+i, sz_cpr); // update checksum of compressed data c_adler = upx_adler32(buf + i, sz_cpr, c_adler); // decompress if (sz_cpr < sz_unc) { decompress(buf+i, buf, false); if (0!=bhdr.b_ftid) { Filter ft(ph.level); ft.init(bhdr.b_ftid); ft.cto = bhdr.b_cto8; ft.unfilter(buf, sz_unc); } i = 0; } // update checksum of uncompressed data u_adler = upx_adler32(buf + i, sz_unc, u_adler); total_in += sz_cpr; total_out += sz_unc; // write block if (fo) fo->write(buf + i, sz_unc); #undef buf } // update header with totals ph.c_len = total_in; ph.u_len = total_out; // all bytes must be written if (ph.version > 8 && total_out != orig_file_size) throwEOFException(); // finally test the checksums // if (ph.c_adler != c_adler || ph.u_adler != u_adler) // throwChecksumError(); }
static int smacker_read_header(AVFormatContext *s, AVFormatParameters *ap) { ByteIOContext *pb = s->pb; SmackerContext *smk = 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); if(smk->flags & SMACKER_FLAG_RING_FRAME) smk->frames++; 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 = AVMEDIA_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); st->duration = smk->frames; /* handle possible audio streams */ for(i = 0; i < 7; i++) { smk->indexes[i] = -1; if(smk->rates[i] & 0xFFFFFF){ ast[i] = av_new_stream(s, 0); smk->indexes[i] = ast[i]->index; ast[i]->codec->codec_type = AVMEDIA_TYPE_AUDIO; if (smk->rates[i] & SMK_AUD_BINKAUD) { ast[i]->codec->codec_id = CODEC_ID_BINKAUDIO_RDFT; } else if (smk->rates[i] & SMK_AUD_USEDCT) { ast[i]->codec->codec_id = CODEC_ID_BINKAUDIO_DCT; } else if (smk->rates[i] & SMK_AUD_PACKED){ ast[i]->codec->codec_id = CODEC_ID_SMACKAUDIO; ast[i]->codec->codec_tag = MKTAG('S', 'M', 'K', 'A'); } else { ast[i]->codec->codec_id = CODEC_ID_PCM_U8; } 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_coded_sample = (smk->rates[i] & SMK_AUD_16BITS) ? 16 : 8; if(ast[i]->codec->bits_per_coded_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_coded_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(EIO); } ((int32_t*)st->codec->extradata)[0] = av_le2ne32(smk->mmap_size); ((int32_t*)st->codec->extradata)[1] = av_le2ne32(smk->mclr_size); ((int32_t*)st->codec->extradata)[2] = av_le2ne32(smk->full_size); ((int32_t*)st->codec->extradata)[3] = av_le2ne32(smk->type_size); smk->curstream = -1; smk->nextpos = url_ftell(pb); return 0; }
static int tta_read_header(AVFormatContext *s, AVFormatParameters *ap) { TTAContext *c = s->priv_data; AVStream *st; int i, channels, bps, samplerate, datalen, framelen; uint64_t framepos, start_offset; ff_id3v2_read(s); if (!av_metadata_get(s->metadata, "", NULL, AV_METADATA_IGNORE_SUFFIX)) ff_id3v1_read(s); start_offset = url_ftell(s->pb); if (get_le32(s->pb) != AV_RL32("TTA1")) return -1; // not tta file url_fskip(s->pb, 2); // FIXME: flags channels = get_le16(s->pb); bps = get_le16(s->pb); samplerate = get_le32(s->pb); if(samplerate <= 0 || samplerate > 1000000){ av_log(s, AV_LOG_ERROR, "nonsense samplerate\n"); return -1; } datalen = get_le32(s->pb); if(datalen < 0){ av_log(s, AV_LOG_ERROR, "nonsense datalen\n"); return -1; } url_fskip(s->pb, 4); // header crc framelen = samplerate*256/245; c->totalframes = datalen / framelen + ((datalen % framelen) ? 1 : 0); c->currentframe = 0; if(c->totalframes >= UINT_MAX/sizeof(uint32_t)){ av_log(s, AV_LOG_ERROR, "totalframes too large\n"); return -1; } st = av_new_stream(s, 0); if (!st) return AVERROR(ENOMEM); av_set_pts_info(st, 64, 1, samplerate); st->start_time = 0; st->duration = datalen; framepos = url_ftell(s->pb) + 4*c->totalframes + 4; for (i = 0; i < c->totalframes; i++) { uint32_t size = get_le32(s->pb); av_add_index_entry(st, framepos, i*framelen, size, 0, AVINDEX_KEYFRAME); framepos += size; } url_fskip(s->pb, 4); // seektable crc st->codec->codec_type = AVMEDIA_TYPE_AUDIO; st->codec->codec_id = CODEC_ID_TTA; st->codec->channels = channels; st->codec->sample_rate = samplerate; st->codec->bits_per_coded_sample = bps; st->codec->extradata_size = url_ftell(s->pb) - start_offset; if(st->codec->extradata_size+FF_INPUT_BUFFER_PADDING_SIZE <= (unsigned)st->codec->extradata_size){ //this check is redundant as get_buffer should fail av_log(s, AV_LOG_ERROR, "extradata_size too large\n"); return -1; } st->codec->extradata = av_mallocz(st->codec->extradata_size+FF_INPUT_BUFFER_PADDING_SIZE); url_fseek(s->pb, start_offset, SEEK_SET); get_buffer(s->pb, st->codec->extradata, st->codec->extradata_size); return 0; }