static int read_header(AVFormatContext *s) { BRSTMDemuxContext *b = s->priv_data; int bom, major, minor, codec, chunk; int64_t pos, h1offset, toffset; uint32_t size, start, asize; AVStream *st; int ret = AVERROR_EOF; st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); st->codec->codec_type = AVMEDIA_TYPE_AUDIO; avio_skip(s->pb, 4); bom = avio_rb16(s->pb); if (bom != 0xFEFF && bom != 0xFFFE) { av_log(s, AV_LOG_ERROR, "invalid byte order: %X\n", bom); return AVERROR_INVALIDDATA; } if (bom == 0xFFFE) { avpriv_request_sample(s, "little endian byte order"); return AVERROR_PATCHWELCOME; } major = avio_r8(s->pb); minor = avio_r8(s->pb); avio_skip(s->pb, 4); // size of file size = avio_rb16(s->pb); if (size < 14) return AVERROR_INVALIDDATA; avio_skip(s->pb, size - 14); pos = avio_tell(s->pb); if (avio_rl32(s->pb) != MKTAG('H','E','A','D')) return AVERROR_INVALIDDATA; size = avio_rb32(s->pb); if (size < 256) return AVERROR_INVALIDDATA; avio_skip(s->pb, 4); // unknown h1offset = avio_rb32(s->pb); if (h1offset > size) return AVERROR_INVALIDDATA; avio_skip(s->pb, 12); toffset = avio_rb32(s->pb) + 16LL; if (toffset > size) return AVERROR_INVALIDDATA; avio_skip(s->pb, pos + h1offset + 8 - avio_tell(s->pb)); codec = avio_r8(s->pb); switch (codec) { case 0: codec = AV_CODEC_ID_PCM_S8_PLANAR; break; case 1: codec = AV_CODEC_ID_PCM_S16BE_PLANAR; break; case 2: codec = AV_CODEC_ID_ADPCM_THP; break; default: avpriv_request_sample(s, "codec %d", codec); return AVERROR_PATCHWELCOME; } avio_skip(s->pb, 1); // loop flag st->codec->codec_id = codec; st->codec->channels = avio_r8(s->pb); if (!st->codec->channels) return AVERROR_INVALIDDATA; avio_skip(s->pb, 1); // padding st->codec->sample_rate = avio_rb16(s->pb); if (!st->codec->sample_rate) return AVERROR_INVALIDDATA; avio_skip(s->pb, 2); // padding avio_skip(s->pb, 4); // loop start sample st->start_time = 0; st->duration = avio_rb32(s->pb); avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); start = avio_rb32(s->pb); b->current_block = 0; b->block_count = avio_rb32(s->pb); if (b->block_count > UINT16_MAX) { av_log(s, AV_LOG_WARNING, "too many blocks: %u\n", b->block_count); return AVERROR_INVALIDDATA; } b->block_size = avio_rb32(s->pb); if (b->block_size > UINT16_MAX / st->codec->channels) return AVERROR_INVALIDDATA; b->block_size *= st->codec->channels; b->samples_per_block = avio_rb32(s->pb); b->last_block_used_bytes = avio_rb32(s->pb); if (b->last_block_used_bytes > UINT16_MAX / st->codec->channels) return AVERROR_INVALIDDATA; b->last_block_used_bytes *= st->codec->channels; avio_skip(s->pb, 4); // last block samples avio_skip(s->pb, 4); // last block size if (codec == AV_CODEC_ID_ADPCM_THP) { int ch; avio_skip(s->pb, pos + toffset - avio_tell(s->pb)); toffset = avio_rb32(s->pb) + 16LL; if (toffset > size) return AVERROR_INVALIDDATA; avio_skip(s->pb, pos + toffset - avio_tell(s->pb)); b->table = av_mallocz(32 * st->codec->channels); if (!b->table) return AVERROR(ENOMEM); for (ch = 0; ch < st->codec->channels; ch++) { if (avio_read(s->pb, b->table + ch * 32, 32) != 32) { ret = AVERROR_INVALIDDATA; goto fail; } avio_skip(s->pb, 24); } } if (size < (avio_tell(s->pb) - pos)) { ret = AVERROR_INVALIDDATA; goto fail; } avio_skip(s->pb, size - (avio_tell(s->pb) - pos)); while (!avio_feof(s->pb)) { chunk = avio_rl32(s->pb); size = avio_rb32(s->pb); if (size < 8) { ret = AVERROR_INVALIDDATA; goto fail; } size -= 8; switch (chunk) { case MKTAG('A','D','P','C'): if (codec != AV_CODEC_ID_ADPCM_THP) goto skip; asize = b->block_count * st->codec->channels * 4; if (size < asize) { ret = AVERROR_INVALIDDATA; goto fail; } if (b->adpc) { av_log(s, AV_LOG_WARNING, "skipping additional ADPC chunk\n"); goto skip; } else { b->adpc = av_mallocz(asize); if (!b->adpc) { ret = AVERROR(ENOMEM); goto fail; } avio_read(s->pb, b->adpc, asize); avio_skip(s->pb, size - asize); } break; case MKTAG('D','A','T','A'): if ((start < avio_tell(s->pb)) || (!b->adpc && codec == AV_CODEC_ID_ADPCM_THP)) { ret = AVERROR_INVALIDDATA; goto fail; } avio_skip(s->pb, start - avio_tell(s->pb)); if (major != 1 || minor) avpriv_request_sample(s, "Version %d.%d", major, minor); return 0; default: av_log(s, AV_LOG_WARNING, "skipping unknown chunk: %X\n", chunk); skip: avio_skip(s->pb, size); } } fail: read_close(s); return ret; }
bool AVIDecoder::AVIVideoTrack::isTruemotion1() const { return _bmInfo.compression == MKTAG('D', 'U', 'C', 'K') || _bmInfo.compression == MKTAG('d', 'u', 'c', 'k'); }
static int img_write_packet(AVFormatContext *s, AVPacket *pkt) { VideoData *img = s->priv_data; ByteIOContext *pb[3]; char filename[1024]; AVCodecContext *codec= s->streams[ pkt->stream_index ]->codec; int i; if (!img->is_pipe) { if (av_get_frame_filename(filename, sizeof(filename), img->path, img->img_number) < 0 && img->img_number>1) { av_log(s, AV_LOG_ERROR, "Could not get frame filename from pattern\n"); return AVERROR(EIO); } for(i=0; i<3; i++){ if (url_fopen(&pb[i], filename, URL_WRONLY) < 0) { av_log(s, AV_LOG_ERROR, "Could not open file : %s\n",filename); return AVERROR(EIO); } if(codec->codec_id != CODEC_ID_RAWVIDEO) break; filename[ strlen(filename) - 1 ]= 'U' + i; } } else { pb[0] = s->pb; } if(codec->codec_id == CODEC_ID_RAWVIDEO){ int ysize = codec->width * codec->height; put_buffer(pb[0], pkt->data , ysize); put_buffer(pb[1], pkt->data + ysize, (pkt->size - ysize)/2); put_buffer(pb[2], pkt->data + ysize +(pkt->size - ysize)/2, (pkt->size - ysize)/2); put_flush_packet(pb[1]); put_flush_packet(pb[2]); url_fclose(pb[1]); url_fclose(pb[2]); }else{ if(av_str2id(img_tags, s->filename) == CODEC_ID_JPEG2000){ AVStream *st = s->streams[0]; if(st->codec->extradata_size > 8 && AV_RL32(st->codec->extradata+4) == MKTAG('j','p','2','h')){ if(pkt->size < 8 || AV_RL32(pkt->data+4) != MKTAG('j','p','2','c')) goto error; put_be32(pb[0], 12); put_tag (pb[0], "jP "); put_be32(pb[0], 0x0D0A870A); // signature put_be32(pb[0], 20); put_tag (pb[0], "ftyp"); put_tag (pb[0], "jp2 "); put_be32(pb[0], 0); put_tag (pb[0], "jp2 "); put_buffer(pb[0], st->codec->extradata, st->codec->extradata_size); }else if(pkt->size < 8 || (!st->codec->extradata_size && AV_RL32(pkt->data+4) != MKTAG('j','P',' ',' '))){ // signature error: av_log(s, AV_LOG_ERROR, "malformated jpeg2000 codestream\n"); return -1; } } put_buffer(pb[0], pkt->data, pkt->size); } put_flush_packet(pb[0]); if (!img->is_pipe) { url_fclose(pb[0]); } img->img_number++; return 0; }
/* 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 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 ffm_write_header(AVFormatContext *s) { FFMContext *ffm = s->priv_data; AVDictionaryEntry *t; AVStream *st; AVIOContext *pb = s->pb; AVCodecContext *codec; int bit_rate, i, ret; if (t = av_dict_get(s->metadata, "creation_time", NULL, 0)) { ret = av_parse_time(&ffm->start_time, t->value, 0); if (ret < 0) return ret; } ffm->packet_size = FFM_PACKET_SIZE; /* header */ avio_wl32(pb, MKTAG('F', 'F', 'M', '2')); avio_wb32(pb, ffm->packet_size); avio_wb64(pb, 0); /* current write position */ if(avio_open_dyn_buf(&pb) < 0) return AVERROR(ENOMEM); avio_wb32(pb, s->nb_streams); bit_rate = 0; for(i=0;i<s->nb_streams;i++) { st = s->streams[i]; bit_rate += st->codec->bit_rate; } avio_wb32(pb, bit_rate); write_header_chunk(s->pb, pb, MKBETAG('M', 'A', 'I', 'N')); /* list of streams */ for(i=0;i<s->nb_streams;i++) { st = s->streams[i]; avpriv_set_pts_info(st, 64, 1, 1000000); if(avio_open_dyn_buf(&pb) < 0) return AVERROR(ENOMEM); codec = st->codec; /* generic info */ avio_wb32(pb, codec->codec_id); avio_w8(pb, codec->codec_type); avio_wb32(pb, codec->bit_rate); avio_wb32(pb, codec->flags); avio_wb32(pb, codec->flags2); avio_wb32(pb, codec->debug); if (codec->flags & CODEC_FLAG_GLOBAL_HEADER) { avio_wb32(pb, codec->extradata_size); avio_write(pb, codec->extradata, codec->extradata_size); } write_header_chunk(s->pb, pb, MKBETAG('C', 'O', 'M', 'M')); /* specific info */ switch(codec->codec_type) { case AVMEDIA_TYPE_VIDEO: if (st->recommended_encoder_configuration) { av_log(NULL, AV_LOG_DEBUG, "writing recommended configuration: %s\n", st->recommended_encoder_configuration); if ((ret = ffm_write_recommended_config(s->pb, codec, MKBETAG('S', '2', 'V', 'I'), st->recommended_encoder_configuration)) < 0) return ret; } else if ((ret = ffm_write_header_codec_ctx(s->pb, codec, MKBETAG('S', '2', 'V', 'I'), AV_OPT_FLAG_VIDEO_PARAM)) < 0 || (ret = ffm_write_header_codec_private_ctx(s, codec, AV_OPT_FLAG_VIDEO_PARAM)) < 0) return ret; break; case AVMEDIA_TYPE_AUDIO: if (st->recommended_encoder_configuration) { av_log(NULL, AV_LOG_DEBUG, "writing recommended configuration: %s\n", st->recommended_encoder_configuration); if ((ret = ffm_write_recommended_config(s->pb, codec, MKBETAG('S', '2', 'A', 'U'), st->recommended_encoder_configuration)) < 0) return ret; } else if ((ret = ffm_write_header_codec_ctx(s->pb, codec, MKBETAG('S', '2', 'A', 'U'), AV_OPT_FLAG_AUDIO_PARAM)) < 0 || (ret = ffm_write_header_codec_private_ctx(s, codec, AV_OPT_FLAG_AUDIO_PARAM)) < 0) return ret; break; default: return -1; } } pb = s->pb; avio_wb64(pb, 0); // end of header /* flush until end of block reached */ while ((avio_tell(pb) % ffm->packet_size) != 0) avio_w8(pb, 0); avio_flush(pb); /* init packet mux */ ffm->packet_ptr = ffm->packet; ffm->packet_end = ffm->packet + ffm->packet_size - FFM_HEADER_SIZE; av_assert0(ffm->packet_end >= ffm->packet); ffm->frame_offset = 0; ffm->dts = 0; ffm->first_packet = 1; return 0; }
static int read_header(AVFormatContext *s) { BRSTMDemuxContext *b = s->priv_data; int bom, major, minor, codec, chunk; int64_t h1offset, pos, toffset; uint32_t size, asize, start = 0; AVStream *st; int ret = AVERROR_EOF; int bfstm = !strcmp("bfstm", s->iformat->name); st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); st->codec->codec_type = AVMEDIA_TYPE_AUDIO; avio_skip(s->pb, 4); bom = avio_rb16(s->pb); if (bom != 0xFEFF && bom != 0xFFFE) { av_log(s, AV_LOG_ERROR, "invalid byte order: %X\n", bom); return AVERROR_INVALIDDATA; } if (bom == 0xFFFE) b->little_endian = 1; if (!bfstm) { major = avio_r8(s->pb); minor = avio_r8(s->pb); avio_skip(s->pb, 4); // size of file size = read16(s); if (size < 14) return AVERROR_INVALIDDATA; avio_skip(s->pb, size - 14); pos = avio_tell(s->pb); if (avio_rl32(s->pb) != MKTAG('H','E','A','D')) return AVERROR_INVALIDDATA; } else { uint32_t info_offset = 0, info_size; uint16_t section_count, header_size, i; header_size = read16(s); // 6 avio_skip(s->pb, 4); // Unknown constant 0x00030000 avio_skip(s->pb, 4); // size of file section_count = read16(s); avio_skip(s->pb, 2); // padding for (i = 0; avio_tell(s->pb) < header_size && !(start && info_offset) && i < section_count; i++) { uint16_t flag = read16(s); avio_skip(s->pb, 2); switch (flag) { case 0x4000: info_offset = read32(s); info_size = read32(s); break; case 0x4001: avio_skip(s->pb, 4); // seek offset avio_skip(s->pb, 4); // seek size break; case 0x4002: start = read32(s) + 8; avio_skip(s->pb, 4); //data_size = read32(s); break; case 0x4003: avio_skip(s->pb, 4); // REGN offset avio_skip(s->pb, 4); // REGN size break; } } if (!info_offset || !start) return AVERROR_INVALIDDATA; avio_skip(s->pb, info_offset - avio_tell(s->pb)); pos = avio_tell(s->pb); if (avio_rl32(s->pb) != MKTAG('I','N','F','O')) return AVERROR_INVALIDDATA; } size = read32(s); if (size < 192) return AVERROR_INVALIDDATA; avio_skip(s->pb, 4); // unknown h1offset = read32(s); if (h1offset > size) return AVERROR_INVALIDDATA; avio_skip(s->pb, 12); toffset = read32(s) + 16LL; if (toffset > size) return AVERROR_INVALIDDATA; avio_skip(s->pb, pos + h1offset + 8 - avio_tell(s->pb)); codec = avio_r8(s->pb); switch (codec) { case 0: codec = AV_CODEC_ID_PCM_S8_PLANAR; break; case 1: codec = b->little_endian ? AV_CODEC_ID_PCM_S16LE_PLANAR : AV_CODEC_ID_PCM_S16BE_PLANAR; break; case 2: codec = b->little_endian ? AV_CODEC_ID_ADPCM_THP_LE : AV_CODEC_ID_ADPCM_THP; break; default: avpriv_request_sample(s, "codec %d", codec); return AVERROR_PATCHWELCOME; } avio_skip(s->pb, 1); // loop flag st->codec->codec_id = codec; st->codec->channels = avio_r8(s->pb); if (!st->codec->channels) return AVERROR_INVALIDDATA; avio_skip(s->pb, 1); // padding st->codec->sample_rate = bfstm ? read32(s) : read16(s); if (!st->codec->sample_rate) return AVERROR_INVALIDDATA; if (!bfstm) avio_skip(s->pb, 2); // padding avio_skip(s->pb, 4); // loop start sample st->start_time = 0; st->duration = read32(s); avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); if (!bfstm) start = read32(s); b->current_block = 0; b->block_count = read32(s); if (b->block_count > UINT16_MAX) { av_log(s, AV_LOG_WARNING, "too many blocks: %u\n", b->block_count); return AVERROR_INVALIDDATA; } b->block_size = read32(s); if (b->block_size > UINT32_MAX / st->codec->channels) return AVERROR_INVALIDDATA; b->samples_per_block = read32(s); b->last_block_used_bytes = read32(s); b->last_block_samples = read32(s); b->last_block_size = read32(s); if (b->last_block_size > UINT32_MAX / st->codec->channels) return AVERROR_INVALIDDATA; if (b->last_block_used_bytes > b->last_block_size) return AVERROR_INVALIDDATA; if (codec == AV_CODEC_ID_ADPCM_THP || codec == AV_CODEC_ID_ADPCM_THP_LE) { int ch; avio_skip(s->pb, pos + toffset - avio_tell(s->pb)); if (!bfstm) toffset = read32(s) + 16LL; else toffset = toffset + read32(s) + st->codec->channels * 8 - 8; if (toffset > size) return AVERROR_INVALIDDATA; avio_skip(s->pb, pos + toffset - avio_tell(s->pb)); b->table = av_mallocz(32 * st->codec->channels); if (!b->table) return AVERROR(ENOMEM); for (ch = 0; ch < st->codec->channels; ch++) { if (avio_read(s->pb, b->table + ch * 32, 32) != 32) { ret = AVERROR_INVALIDDATA; goto fail; } avio_skip(s->pb, bfstm ? 14 : 24); } } if (size < (avio_tell(s->pb) - pos)) { ret = AVERROR_INVALIDDATA; goto fail; } avio_skip(s->pb, size - (avio_tell(s->pb) - pos)); while (!avio_feof(s->pb)) { chunk = avio_rl32(s->pb); size = read32(s); if (size < 8) { ret = AVERROR_INVALIDDATA; goto fail; } size -= 8; switch (chunk) { case MKTAG('S','E','E','K'): case MKTAG('A','D','P','C'): if (codec != AV_CODEC_ID_ADPCM_THP && codec != AV_CODEC_ID_ADPCM_THP_LE) goto skip; asize = b->block_count * st->codec->channels * 4; if (size < asize) { ret = AVERROR_INVALIDDATA; goto fail; } if (b->adpc) { av_log(s, AV_LOG_WARNING, "skipping additional ADPC chunk\n"); goto skip; } else { b->adpc = av_mallocz(asize); if (!b->adpc) { ret = AVERROR(ENOMEM); goto fail; } if (bfstm && codec != AV_CODEC_ID_ADPCM_THP_LE) { // Big-endian BFSTMs have little-endian SEEK tables // for some strange reason. int i; for (i = 0; i < asize; i += 2) { b->adpc[i+1] = avio_r8(s->pb); b->adpc[i] = avio_r8(s->pb); } } else { avio_read(s->pb, b->adpc, asize); } avio_skip(s->pb, size - asize); } break; case MKTAG('D','A','T','A'): if ((start < avio_tell(s->pb)) || (!b->adpc && (codec == AV_CODEC_ID_ADPCM_THP || codec == AV_CODEC_ID_ADPCM_THP_LE))) { ret = AVERROR_INVALIDDATA; goto fail; } avio_skip(s->pb, start - avio_tell(s->pb)); if (bfstm && (codec == AV_CODEC_ID_ADPCM_THP || codec == AV_CODEC_ID_ADPCM_THP_LE)) avio_skip(s->pb, 24); b->data_start = avio_tell(s->pb); if ((major != 1 || minor) && !bfstm) avpriv_request_sample(s, "Version %d.%d", major, minor); return 0; default: av_log(s, AV_LOG_WARNING, "skipping unknown chunk: %X\n", chunk); skip: avio_skip(s->pb, size); } } fail: read_close(s); return ret; }
static int caf_write_header(AVFormatContext *s) { AVIOContext *pb = s->pb; AVCodecContext *enc = s->streams[0]->codec; CAFContext *caf = s->priv_data; unsigned int codec_tag = ff_codec_get_tag(ff_codec_caf_tags, enc->codec_id); switch (enc->codec_id) { case CODEC_ID_AAC: case CODEC_ID_AC3: av_log(s, AV_LOG_ERROR, "muxing codec currently unsupported\n"); return AVERROR_PATCHWELCOME; } switch (enc->codec_id) { case CODEC_ID_PCM_S8: case CODEC_ID_PCM_S16LE: case CODEC_ID_PCM_S16BE: case CODEC_ID_PCM_S24LE: case CODEC_ID_PCM_S24BE: case CODEC_ID_PCM_S32LE: case CODEC_ID_PCM_S32BE: case CODEC_ID_PCM_F32LE: case CODEC_ID_PCM_F32BE: case CODEC_ID_PCM_F64LE: case CODEC_ID_PCM_F64BE: case CODEC_ID_PCM_ALAW: case CODEC_ID_PCM_MULAW: codec_tag = MKTAG('l','p','c','m'); } if (!codec_tag) { av_log(s, AV_LOG_ERROR, "unsupported codec\n"); return AVERROR_INVALIDDATA; } if (!enc->block_align && !pb->seekable) { av_log(s, AV_LOG_ERROR, "Muxing variable packet size not supported on non seekable output\n"); return AVERROR_INVALIDDATA; } ffio_wfourcc(pb, "caff"); //< mFileType avio_wb16(pb, 1); //< mFileVersion avio_wb16(pb, 0); //< mFileFlags ffio_wfourcc(pb, "desc"); //< Audio Description chunk avio_wb64(pb, 32); //< mChunkSize avio_wb64(pb, av_dbl2int(enc->sample_rate)); //< mSampleRate avio_wl32(pb, codec_tag); //< mFormatID avio_wb32(pb, codec_flags(enc->codec_id)); //< mFormatFlags avio_wb32(pb, enc->block_align); //< mBytesPerPacket avio_wb32(pb, samples_per_packet(enc->codec_id, enc->channels)); //< mFramesPerPacket avio_wb32(pb, enc->channels); //< mChannelsPerFrame avio_wb32(pb, av_get_bits_per_sample(enc->codec_id)); //< mBitsPerChannel if (enc->channel_layout) { ffio_wfourcc(pb, "chan"); avio_wb64(pb, 12); ff_mov_write_chan(pb, enc->channel_layout); } if (enc->codec_id == CODEC_ID_ALAC) { ffio_wfourcc(pb, "kuki"); avio_wb64(pb, 12 + enc->extradata_size); avio_write(pb, "\0\0\0\14frmaalac", 12); avio_write(pb, enc->extradata, enc->extradata_size); } else if (enc->codec_id == CODEC_ID_AMR_NB) { ffio_wfourcc(pb, "kuki"); avio_wb64(pb, 29); avio_write(pb, "\0\0\0\14frmasamr", 12); avio_wb32(pb, 0x11); /* size */ avio_write(pb, "samrFFMP", 8); avio_w8(pb, 0); /* decoder version */ avio_wb16(pb, 0x81FF); /* Mode set (all modes for AMR_NB) */ avio_w8(pb, 0x00); /* Mode change period (no restriction) */ avio_w8(pb, 0x01); /* Frames per sample */ } else if (enc->codec_id == CODEC_ID_QDM2) { ffio_wfourcc(pb, "kuki"); avio_wb64(pb, enc->extradata_size); avio_write(pb, enc->extradata, enc->extradata_size); } ffio_wfourcc(pb, "data"); //< Audio Data chunk caf->data = avio_tell(pb); avio_wb64(pb, -1); //< mChunkSize avio_wb32(pb, 0); //< mEditCount avio_flush(pb); return 0; }
/** * @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(AVIOContext *pb, AVStream *vst, AVStream *ast, int myth) { nuv_frametype frametype; if (!vst && !myth) return 1; // no codec data needed while (!url_feof(pb)) { int size, subtype; frametype = avio_r8(pb); switch (frametype) { case NUV_EXTRADATA: subtype = avio_r8(pb); avio_skip(pb, 6); size = PKTSIZE(avio_rl32(pb)); if (vst && subtype == 'R') { vst->codec->extradata_size = size; vst->codec->extradata = av_malloc(size); avio_read(pb, vst->codec->extradata, size); size = 0; if (!myth) return 1; } break; case NUV_MYTHEXT: avio_skip(pb, 7); size = PKTSIZE(avio_rl32(pb)); if (size != 128 * 4) break; avio_rl32(pb); // version if (vst) { vst->codec->codec_tag = avio_rl32(pb); vst->codec->codec_id = ff_codec_get_id(ff_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 avio_skip(pb, 4); if (ast) { ast->codec->codec_tag = avio_rl32(pb); ast->codec->sample_rate = avio_rl32(pb); ast->codec->bits_per_coded_sample = avio_rl32(pb); ast->codec->channels = avio_rl32(pb); ast->codec->codec_id = ff_wav_codec_get_id(ast->codec->codec_tag, ast->codec->bits_per_coded_sample); ast->need_parsing = AVSTREAM_PARSE_FULL; } else avio_skip(pb, 4 * 4); size -= 6 * 4; avio_skip(pb, size); return 1; case NUV_SEEKP: size = 11; break; default: avio_skip(pb, 7); size = PKTSIZE(avio_rl32(pb)); break; } avio_skip(pb, size); } return 0; }
static int xwma_read_header(AVFormatContext *s) { int64_t size; int ret; uint32_t dpds_table_size = 0; uint32_t *dpds_table = 0; unsigned int tag; AVIOContext *pb = s->pb; AVStream *st; XWMAContext *xwma = s->priv_data; int i; /* The following code is mostly copied from wav.c, with some * minor alterations. */ /* check RIFF header */ tag = avio_rl32(pb); if (tag != MKTAG('R', 'I', 'F', 'F')) return -1; avio_rl32(pb); /* file size */ tag = avio_rl32(pb); if (tag != MKTAG('X', 'W', 'M', 'A')) return -1; /* parse fmt header */ tag = avio_rl32(pb); if (tag != MKTAG('f', 'm', 't', ' ')) return -1; size = avio_rl32(pb); st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); ret = ff_get_wav_header(pb, st->codec, size); if (ret < 0) return ret; st->need_parsing = AVSTREAM_PARSE_NONE; /* All xWMA files I have seen contained WMAv2 data. If there are files * using WMA Pro or some other codec, then we need to figure out the right * extradata for that. Thus, ask the user for feedback, but try to go on * anyway. */ if (st->codec->codec_id != CODEC_ID_WMAV2) { av_log(s, AV_LOG_WARNING, "unexpected codec (tag 0x04%x; id %d)\n", st->codec->codec_tag, st->codec->codec_id); av_log_ask_for_sample(s, NULL); } else { /* In all xWMA files I have seen, there is no extradata. But the WMA * codecs require extradata, so we provide our own fake extradata. * * First, check that there really was no extradata in the header. If * there was, then try to use it, after asking the user to provide a * sample of this unusual file. */ if (st->codec->extradata_size != 0) { /* Surprise, surprise: We *did* get some extradata. No idea * if it will work, but just go on and try it, after asking * the user for a sample. */ av_log(s, AV_LOG_WARNING, "unexpected extradata (%d bytes)\n", st->codec->extradata_size); av_log_ask_for_sample(s, NULL); } else { st->codec->extradata_size = 6; st->codec->extradata = av_mallocz(6 + FF_INPUT_BUFFER_PADDING_SIZE); if (!st->codec->extradata) return AVERROR(ENOMEM); /* setup extradata with our experimentally obtained value */ st->codec->extradata[4] = 31; } } if (!st->codec->channels) { av_log(s, AV_LOG_WARNING, "Invalid channel count: %d\n", st->codec->channels); return AVERROR_INVALIDDATA; } if (!st->codec->bits_per_coded_sample) { av_log(s, AV_LOG_WARNING, "Invalid bits_per_coded_sample: %d\n", st->codec->bits_per_coded_sample); return AVERROR_INVALIDDATA; } /* set the sample rate */ avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); /* parse the remaining RIFF chunks */ for (;;) { if (pb->eof_reached) return -1; /* read next chunk tag */ tag = avio_rl32(pb); size = avio_rl32(pb); if (tag == MKTAG('d', 'a', 't', 'a')) { /* We assume that the data chunk comes last. */ break; } else if (tag == MKTAG('d','p','d','s')) { /* Quoting the MSDN xWMA docs on the dpds chunk: "Contains the * decoded packet cumulative data size array, each element is the * number of bytes accumulated after the corresponding xWMA packet * is decoded in order." * * Each packet has size equal to st->codec->block_align, which in * all cases I saw so far was always 2230. Thus, we can use the * dpds data to compute a seeking index. */ /* Error out if there is more than one dpds chunk. */ if (dpds_table) { av_log(s, AV_LOG_ERROR, "two dpds chunks present\n"); return -1; } /* Compute the number of entries in the dpds chunk. */ if (size & 3) { /* Size should be divisible by four */ av_log(s, AV_LOG_WARNING, "dpds chunk size %"PRId64" not divisible by 4\n", size); } dpds_table_size = size / 4; if (dpds_table_size == 0 || dpds_table_size >= INT_MAX / 4) { av_log(s, AV_LOG_ERROR, "dpds chunk size %"PRId64" invalid\n", size); return -1; } /* Allocate some temporary storage to keep the dpds data around. * for processing later on. */ dpds_table = av_malloc(dpds_table_size * sizeof(uint32_t)); if (!dpds_table) { return AVERROR(ENOMEM); } for (i = 0; i < dpds_table_size; ++i) { dpds_table[i] = avio_rl32(pb); size -= 4; } } avio_skip(pb, size); } /* Determine overall data length */ if (size < 0) return -1; if (!size) { xwma->data_end = INT64_MAX; } else xwma->data_end = avio_tell(pb) + size; if (dpds_table && dpds_table_size) { int64_t cur_pos; const uint32_t bytes_per_sample = (st->codec->channels * st->codec->bits_per_coded_sample) >> 3; /* Estimate the duration from the total number of output bytes. */ const uint64_t total_decoded_bytes = dpds_table[dpds_table_size - 1]; st->duration = total_decoded_bytes / bytes_per_sample; /* Use the dpds data to build a seek table. We can only do this after * we know the offset to the data chunk, as we need that to determine * the actual offset to each input block. * Note: If we allowed ourselves to assume that the data chunk always * follows immediately after the dpds block, we could of course guess * the data block's start offset already while reading the dpds chunk. * I decided against that, just in case other chunks ever are * discovered. */ cur_pos = avio_tell(pb); for (i = 0; i < dpds_table_size; ++i) { /* From the number of output bytes that would accumulate in the * output buffer after decoding the first (i+1) packets, we compute * an offset / timestamp pair. */ av_add_index_entry(st, cur_pos + (i+1) * st->codec->block_align, /* pos */ dpds_table[i] / bytes_per_sample, /* timestamp */ st->codec->block_align, /* size */ 0, /* duration */ AVINDEX_KEYFRAME); } } else if (st->codec->bit_rate) {
* along with xoreos-tools. If not, see <http://www.gnu.org/licenses/>. */ /** @file * Our very own intermediate texture format. * Currently used by NSBTX. */ #include "src/common/util.h" #include "src/common/strutil.h" #include "src/common/readstream.h" #include "src/common/error.h" #include "src/images/xoreositex.h" static const uint32 kXEOSID = MKTAG('X', 'E', 'O', 'S'); static const uint32 kITEXID = MKTAG('I', 'T', 'E', 'X'); namespace Images { XEOSITEX::XEOSITEX(Common::SeekableReadStream &xeositex) { load(xeositex); } XEOSITEX::~XEOSITEX() { } void XEOSITEX::load(Common::SeekableReadStream &xeositex) { try { readHeader(xeositex);
static int vfw_read_header(AVFormatContext *s, AVFormatParameters *ap) { struct vfw_ctx *ctx = s->priv_data; AVCodecContext *codec; AVStream *st; int devnum; int bisize; BITMAPINFO *bi; CAPTUREPARMS cparms; DWORD biCompression; WORD biBitCount; int ret; AVRational fps; if (!strcmp(s->filename, "list")) { for (devnum = 0; devnum <= 9; devnum++) { char driver_name[256]; char driver_ver[256]; ret = capGetDriverDescription(devnum, driver_name, sizeof(driver_name), driver_ver, sizeof(driver_ver)); if (ret) { av_log(s, AV_LOG_INFO, "Driver %d\n", devnum); av_log(s, AV_LOG_INFO, " %s\n", driver_name); av_log(s, AV_LOG_INFO, " %s\n", driver_ver); } } return AVERROR(EIO); } #if FF_API_FORMAT_PARAMETERS if (ap->time_base.num) fps = (AVRational){ap->time_base.den, ap->time_base.num}; #endif ctx->hwnd = capCreateCaptureWindow(NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, 0); if(!ctx->hwnd) { av_log(s, AV_LOG_ERROR, "Could not create capture window.\n"); return AVERROR(EIO); } /* If atoi fails, devnum==0 and the default device is used */ devnum = atoi(s->filename); ret = SendMessage(ctx->hwnd, WM_CAP_DRIVER_CONNECT, devnum, 0); if(!ret) { av_log(s, AV_LOG_ERROR, "Could not connect to device.\n"); DestroyWindow(ctx->hwnd); return AVERROR(ENODEV); } SendMessage(ctx->hwnd, WM_CAP_SET_OVERLAY, 0, 0); SendMessage(ctx->hwnd, WM_CAP_SET_PREVIEW, 0, 0); ret = SendMessage(ctx->hwnd, WM_CAP_SET_CALLBACK_VIDEOSTREAM, 0, (LPARAM) videostream_cb); if(!ret) { av_log(s, AV_LOG_ERROR, "Could not set video stream callback.\n"); goto fail_io; } SetWindowLongPtr(ctx->hwnd, GWLP_USERDATA, (LONG_PTR) s); st = av_new_stream(s, 0); if(!st) { vfw_read_close(s); return AVERROR(ENOMEM); } /* Set video format */ bisize = SendMessage(ctx->hwnd, WM_CAP_GET_VIDEOFORMAT, 0, 0); if(!bisize) goto fail_io; bi = av_malloc(bisize); if(!bi) { vfw_read_close(s); return AVERROR(ENOMEM); } ret = SendMessage(ctx->hwnd, WM_CAP_GET_VIDEOFORMAT, bisize, (LPARAM) bi); if(!ret) goto fail_bi; dump_bih(s, &bi->bmiHeader); if (ctx->video_size) { ret = av_parse_video_size(&bi->bmiHeader.biWidth, &bi->bmiHeader.biHeight, ctx->video_size); if (ret < 0) { av_log(s, AV_LOG_ERROR, "Couldn't parse video size.\n"); goto fail_bi; } } #if FF_API_FORMAT_PARAMETERS if (ap->width > 0) bi->bmiHeader.biWidth = ap->width; if (ap->height > 0) bi->bmiHeader.biHeight = ap->height; #endif if (0) { /* For testing yet unsupported compressions * Copy these values from user-supplied verbose information */ bi->bmiHeader.biWidth = 320; bi->bmiHeader.biHeight = 240; bi->bmiHeader.biPlanes = 1; bi->bmiHeader.biBitCount = 12; bi->bmiHeader.biCompression = MKTAG('I','4','2','0'); bi->bmiHeader.biSizeImage = 115200; dump_bih(s, &bi->bmiHeader); } ret = SendMessage(ctx->hwnd, WM_CAP_SET_VIDEOFORMAT, bisize, (LPARAM) bi); if(!ret) { av_log(s, AV_LOG_ERROR, "Could not set Video Format.\n"); goto fail_bi; } biCompression = bi->bmiHeader.biCompression; biBitCount = bi->bmiHeader.biBitCount; av_free(bi); /* Set sequence setup */ ret = SendMessage(ctx->hwnd, WM_CAP_GET_SEQUENCE_SETUP, sizeof(cparms), (LPARAM) &cparms); if(!ret) goto fail_io; dump_captureparms(s, &cparms); cparms.fYield = 1; // Spawn a background thread cparms.dwRequestMicroSecPerFrame = (fps.den*1000000) / fps.num; cparms.fAbortLeftMouse = 0; cparms.fAbortRightMouse = 0; cparms.fCaptureAudio = 0; cparms.vKeyAbort = 0; ret = SendMessage(ctx->hwnd, WM_CAP_SET_SEQUENCE_SETUP, sizeof(cparms), (LPARAM) &cparms); if(!ret) goto fail_io; codec = st->codec; codec->time_base = (AVRational){fps.den, fps.num}; codec->codec_type = AVMEDIA_TYPE_VIDEO; codec->width = bi->bmiHeader.biWidth; codec->height = bi->bmiHeader.biHeight; codec->pix_fmt = vfw_pixfmt(biCompression, biBitCount); if(codec->pix_fmt == PIX_FMT_NONE) { codec->codec_id = vfw_codecid(biCompression); if(codec->codec_id == CODEC_ID_NONE) { av_log(s, AV_LOG_ERROR, "Unknown compression type. " "Please report verbose (-v 9) debug information.\n"); vfw_read_close(s); return AVERROR_PATCHWELCOME; } codec->bits_per_coded_sample = biBitCount; } else { codec->codec_id = CODEC_ID_RAWVIDEO; if(biCompression == BI_RGB) { codec->bits_per_coded_sample = biBitCount; codec->extradata = av_malloc(9 + FF_INPUT_BUFFER_PADDING_SIZE); if (codec->extradata) { codec->extradata_size = 9; memcpy(codec->extradata, "BottomUp", 9); } } } av_set_pts_info(st, 32, 1, 1000); ctx->mutex = CreateMutex(NULL, 0, NULL); if(!ctx->mutex) { av_log(s, AV_LOG_ERROR, "Could not create Mutex.\n" ); goto fail_io; } ctx->event = CreateEvent(NULL, 1, 0, NULL); if(!ctx->event) { av_log(s, AV_LOG_ERROR, "Could not create Event.\n" ); goto fail_io; } ret = SendMessage(ctx->hwnd, WM_CAP_SEQUENCE_NOFILE, 0, 0); if(!ret) { av_log(s, AV_LOG_ERROR, "Could not start capture sequence.\n" ); goto fail_io; } return 0; fail_bi: av_free(bi); fail_io: vfw_read_close(s); return AVERROR(EIO); }
bool StuffItArchive::open(const Common::String &filename) { close(); _stream = SearchMan.createReadStreamForMember(filename); if (!_stream) return false; uint32 tag = _stream->readUint32BE(); // Check all the possible FourCC's bool found = false; for (int i = 0; i < ARRAYSIZE(s_magicNumbers); i++) { if (tag == s_magicNumbers[i]) { found = true; break; } } // Didn't find one, let's bail out if (!found) { close(); return false; } /* uint16 fileCount = */ _stream->readUint16BE(); /* uint32 archiveSize = */ _stream->readUint32BE(); // Some sort of second magic number if (_stream->readUint32BE() != MKTAG('r', 'L', 'a', 'u')) { close(); return false; } /* byte version = */ _stream->readByte(); // meaning not clear _stream->skip(7); // unknown while (_stream->pos() < _stream->size() && !_stream->eos()) { byte resForkCompression = _stream->readByte(); byte dataForkCompression = _stream->readByte(); byte fileNameLength = _stream->readByte(); Common::String name; for (byte i = 0; i < fileNameLength; i++) name += (char)_stream->readByte(); // Skip remaining bytes _stream->skip(63 - fileNameLength); /* uint32 fileType = */ _stream->readUint32BE(); /* uint32 fileCreator = */ _stream->readUint32BE(); /* uint16 finderFlags = */ _stream->readUint16BE(); /* uint32 creationDate = */ _stream->readUint32BE(); /* uint32 modificationDate = */ _stream->readUint32BE(); uint32 resForkUncompressedSize = _stream->readUint32BE(); uint32 dataForkUncompressedSize = _stream->readUint32BE(); uint32 resForkCompressedSize = _stream->readUint32BE(); uint32 dataForkCompressedSize = _stream->readUint32BE(); /* uint16 resForkCRC = */ _stream->readUint16BE(); /* uint16 dataForkCRC = */ _stream->readUint16BE(); _stream->skip(6); // unknown /* uint16 headerCRC = */ _stream->readUint16BE(); // Ignore directories for now if (dataForkCompression == 32 || dataForkCompression == 33) continue; if (dataForkUncompressedSize != 0) { // We have a data fork FileEntry entry; entry.compression = dataForkCompression; entry.uncompressedSize = dataForkUncompressedSize; entry.compressedSize = dataForkCompressedSize; entry.offset = _stream->pos() + resForkCompressedSize; _map[name] = entry; debug(0, "StuffIt file '%s', Compression = %d", name.c_str(), entry.compression); } if (resForkUncompressedSize != 0) { // We have a resource fork // Add a .rsrc extension so we know it's the resource fork name += ".rsrc"; FileEntry entry; entry.compression = resForkCompression; entry.uncompressedSize = resForkUncompressedSize; entry.compressedSize = resForkCompressedSize; entry.offset = _stream->pos(); _map[name] = entry; debug(0, "StuffIt file '%s', Compression = %d", name.c_str(), entry.compression); } // Go to the next entry _stream->skip(dataForkCompressedSize + resForkCompressedSize); } return true; }
#include "common/substream.h" namespace Grim { StuffItArchive::StuffItArchive() : Common::Archive() { _stream = 0; } StuffItArchive::~StuffItArchive() { close(); } // Some known values of StuffIt FourCC's // EMI Mac in particular uses ST65 static const uint32 s_magicNumbers[] = { MKTAG('S', 'I', 'T', '!'), MKTAG('S', 'T', '6', '5'), MKTAG('S', 'T', '5', '0'), MKTAG('S', 'T', '6', '0'), MKTAG('S', 'T', 'i', 'n'), MKTAG('S', 'T', 'i', '2'), MKTAG('S', 'T', 'i', '3'), MKTAG('S', 'T', 'i', '4'), MKTAG('S', 'T', '4', '6') }; bool StuffItArchive::open(const Common::String &filename) { close(); _stream = SearchMan.createReadStreamForMember(filename); if (!_stream) return false; uint32 tag = _stream->readUint32BE(); // Check all the possible FourCC's
STDMETHODIMP CDecAvcodec::InitDecoder(AVCodecID codec, const CMediaType *pmt) { DestroyDecoder(); DbgLog((LOG_TRACE, 10, L"Initializing ffmpeg for codec %S", avcodec_get_name(codec))); BITMAPINFOHEADER *pBMI = NULL; videoFormatTypeHandler((const BYTE *)pmt->Format(), pmt->FormatType(), &pBMI); m_pAVCodec = avcodec_find_decoder(codec); CheckPointer(m_pAVCodec, VFW_E_UNSUPPORTED_VIDEO); m_pAVCtx = avcodec_alloc_context3(m_pAVCodec); CheckPointer(m_pAVCtx, E_POINTER); if(codec == AV_CODEC_ID_MPEG1VIDEO || codec == AV_CODEC_ID_MPEG2VIDEO || pmt->subtype == FOURCCMap(MKTAG('H','2','6','4')) || pmt->subtype == FOURCCMap(MKTAG('h','2','6','4'))) { m_pParser = av_parser_init(codec); } DWORD dwDecFlags = m_pCallback->GetDecodeFlags(); LONG biRealWidth = pBMI->biWidth, biRealHeight = pBMI->biHeight; if (pmt->formattype == FORMAT_VideoInfo || pmt->formattype == FORMAT_MPEGVideo) { VIDEOINFOHEADER *vih = (VIDEOINFOHEADER *)pmt->Format(); if (vih->rcTarget.right != 0 && vih->rcTarget.bottom != 0) { biRealWidth = vih->rcTarget.right; biRealHeight = vih->rcTarget.bottom; } } else if (pmt->formattype == FORMAT_VideoInfo2 || pmt->formattype == FORMAT_MPEG2Video) { VIDEOINFOHEADER2 *vih2 = (VIDEOINFOHEADER2 *)pmt->Format(); if (vih2->rcTarget.right != 0 && vih2->rcTarget.bottom != 0) { biRealWidth = vih2->rcTarget.right; biRealHeight = vih2->rcTarget.bottom; } } m_pAVCtx->codec_id = codec; m_pAVCtx->codec_tag = pBMI->biCompression; m_pAVCtx->coded_width = pBMI->biWidth; m_pAVCtx->coded_height = abs(pBMI->biHeight); m_pAVCtx->bits_per_coded_sample = pBMI->biBitCount; m_pAVCtx->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK; m_pAVCtx->err_recognition = AV_EF_CAREFUL; m_pAVCtx->workaround_bugs = FF_BUG_AUTODETECT; m_pAVCtx->refcounted_frames = 1; if (codec == AV_CODEC_ID_H264) m_pAVCtx->flags2 |= CODEC_FLAG2_SHOW_ALL; // Setup threading int thread_type = getThreadFlags(codec); if (thread_type) { // Thread Count. 0 = auto detect int thread_count = m_pSettings->GetNumThreads(); if (thread_count == 0) { SYSTEM_INFO systemInfo; GetSystemInfo(&systemInfo); thread_count = systemInfo.dwNumberOfProcessors * 3 / 2; } m_pAVCtx->thread_count = max(1, min(thread_count, AVCODEC_MAX_THREADS)); m_pAVCtx->thread_type = thread_type; } else { m_pAVCtx->thread_count = 1; } if (dwDecFlags & LAV_VIDEO_DEC_FLAG_NO_MT) { m_pAVCtx->thread_count = 1; } m_pFrame = av_frame_alloc(); CheckPointer(m_pFrame, E_POINTER); m_h264RandomAccess.SetAVCNALSize(0); // Process Extradata BYTE *extra = NULL; size_t extralen = 0; getExtraData(*pmt, NULL, &extralen); BOOL bH264avc = FALSE; if (extralen > 0) { DbgLog((LOG_TRACE, 10, L"-> Processing extradata of %d bytes", extralen)); // Reconstruct AVC1 extradata format if (pmt->formattype == FORMAT_MPEG2Video && (m_pAVCtx->codec_tag == MAKEFOURCC('a','v','c','1') || m_pAVCtx->codec_tag == MAKEFOURCC('A','V','C','1') || m_pAVCtx->codec_tag == MAKEFOURCC('C','C','V','1'))) { MPEG2VIDEOINFO *mp2vi = (MPEG2VIDEOINFO *)pmt->Format(); extralen += 7; extra = (uint8_t *)av_mallocz(extralen + FF_INPUT_BUFFER_PADDING_SIZE); extra[0] = 1; extra[1] = (BYTE)mp2vi->dwProfile; extra[2] = 0; extra[3] = (BYTE)mp2vi->dwLevel; extra[4] = (BYTE)(mp2vi->dwFlags ? mp2vi->dwFlags : 2) - 1; // Actually copy the metadata into our new buffer size_t actual_len; getExtraData(*pmt, extra+6, &actual_len); // Count the number of SPS/PPS in them and set the length // We'll put them all into one block and add a second block with 0 elements afterwards // The parsing logic does not care what type they are, it just expects 2 blocks. BYTE *p = extra+6, *end = extra+6+actual_len; BOOL bSPS = FALSE, bPPS = FALSE; int count = 0; while (p+1 < end) { unsigned len = (((unsigned)p[0] << 8) | p[1]) + 2; if (p + len > end) { break; } if ((p[2] & 0x1F) == 7) bSPS = TRUE; if ((p[2] & 0x1F) == 8) bPPS = TRUE; count++; p += len; } extra[5] = count; extra[extralen-1] = 0; bH264avc = TRUE; m_h264RandomAccess.SetAVCNALSize(mp2vi->dwFlags); } else if (pmt->subtype == MEDIASUBTYPE_LAV_RAWVIDEO) { if (extralen < sizeof(m_pAVCtx->pix_fmt)) { DbgLog((LOG_TRACE, 10, L"-> LAV RAW Video extradata is missing..")); } else { extra = (uint8_t *)av_mallocz(extralen + FF_INPUT_BUFFER_PADDING_SIZE); getExtraData(*pmt, extra, NULL); m_pAVCtx->pix_fmt = *(AVPixelFormat *)extra; extralen -= sizeof(AVPixelFormat); memmove(extra, extra+sizeof(AVPixelFormat), extralen); } } else { // Just copy extradata for other formats extra = (uint8_t *)av_mallocz(extralen + FF_INPUT_BUFFER_PADDING_SIZE); getExtraData(*pmt, extra, NULL); } // Hack to discard invalid MP4 metadata with AnnexB style video if (codec == AV_CODEC_ID_H264 && !bH264avc && extra[0] == 1) { av_freep(&extra); extralen = 0; } m_pAVCtx->extradata = extra; m_pAVCtx->extradata_size = (int)extralen; } else { if (codec == AV_CODEC_ID_VP6 || codec == AV_CODEC_ID_VP6A || codec == AV_CODEC_ID_VP6F) { int cropH = pBMI->biWidth - biRealWidth; int cropV = pBMI->biHeight - biRealHeight; if (cropH >= 0 && cropH <= 0x0f && cropV >= 0 && cropV <= 0x0f) { m_pAVCtx->extradata = (uint8_t *)av_mallocz(1 + FF_INPUT_BUFFER_PADDING_SIZE); m_pAVCtx->extradata_size = 1; m_pAVCtx->extradata[0] = (cropH << 4) | cropV; } } } m_h264RandomAccess.flush(m_pAVCtx->thread_count); m_CurrentThread = 0; m_rtStartCache = AV_NOPTS_VALUE; LAVPinInfo lavPinInfo = {0}; BOOL bLAVInfoValid = SUCCEEDED(m_pCallback->GetLAVPinInfo(lavPinInfo)); m_bInputPadded = dwDecFlags & LAV_VIDEO_DEC_FLAG_LAVSPLITTER; // Setup codec-specific timing logic BOOL bVC1IsPTS = (codec == AV_CODEC_ID_VC1 && !(dwDecFlags & LAV_VIDEO_DEC_FLAG_VC1_DTS)); // Use ffmpegs logic to reorder timestamps // This is required for H264 content (except AVI), and generally all codecs that use frame threading // VC-1 is also a special case. Its required for splitters that deliver PTS timestamps (see bVC1IsPTS above) m_bFFReordering = ( codec == AV_CODEC_ID_H264 && !(dwDecFlags & LAV_VIDEO_DEC_FLAG_H264_AVI)) || codec == AV_CODEC_ID_VP8 || codec == AV_CODEC_ID_VP3 || codec == AV_CODEC_ID_THEORA || codec == AV_CODEC_ID_HUFFYUV || codec == AV_CODEC_ID_FFVHUFF || codec == AV_CODEC_ID_MPEG2VIDEO || codec == AV_CODEC_ID_MPEG1VIDEO || codec == AV_CODEC_ID_DIRAC || codec == AV_CODEC_ID_UTVIDEO || codec == AV_CODEC_ID_DNXHD || (codec == AV_CODEC_ID_MPEG4 && pmt->formattype == FORMAT_MPEG2Video) || bVC1IsPTS; // Stop time is unreliable, drop it and calculate it m_bCalculateStopTime = (codec == AV_CODEC_ID_H264 || codec == AV_CODEC_ID_DIRAC || (codec == AV_CODEC_ID_MPEG4 && pmt->formattype == FORMAT_MPEG2Video) || bVC1IsPTS); // Real Video content has some odd timestamps // LAV Splitter does them allright with RV30/RV40, everything else screws them up m_bRVDropBFrameTimings = (codec == AV_CODEC_ID_RV10 || codec == AV_CODEC_ID_RV20 || ((codec == AV_CODEC_ID_RV30 || codec == AV_CODEC_ID_RV40) && (!(dwDecFlags & LAV_VIDEO_DEC_FLAG_LAVSPLITTER) || (bLAVInfoValid && (lavPinInfo.flags & LAV_STREAM_FLAG_RV34_MKV))))); // Enable B-Frame delay handling m_bBFrameDelay = !m_bFFReordering && !m_bRVDropBFrameTimings; m_bWaitingForKeyFrame = TRUE; m_bResumeAtKeyFrame = codec == AV_CODEC_ID_MPEG2VIDEO || codec == AV_CODEC_ID_VC1 || codec == AV_CODEC_ID_RV30 || codec == AV_CODEC_ID_RV40 || codec == AV_CODEC_ID_VP3 || codec == AV_CODEC_ID_THEORA || codec == AV_CODEC_ID_MPEG4; m_bNoBufferConsumption = codec == AV_CODEC_ID_MJPEGB || codec == AV_CODEC_ID_LOCO; m_bHasPalette = m_pAVCtx->bits_per_coded_sample <= 8 && m_pAVCtx->extradata_size && !(dwDecFlags & LAV_VIDEO_DEC_FLAG_LAVSPLITTER) && (codec == AV_CODEC_ID_MSVIDEO1 || codec == AV_CODEC_ID_MSRLE || codec == AV_CODEC_ID_CINEPAK || codec == AV_CODEC_ID_8BPS || codec == AV_CODEC_ID_QPEG || codec == AV_CODEC_ID_QTRLE || codec == AV_CODEC_ID_TSCC); if (FAILED(AdditionaDecoderInit())) { return E_FAIL; } if (bLAVInfoValid) { // Setting has_b_frames to a proper value will ensure smoother decoding of H264 if (lavPinInfo.has_b_frames >= 0) { DbgLog((LOG_TRACE, 10, L"-> Setting has_b_frames to %d", lavPinInfo.has_b_frames)); m_pAVCtx->has_b_frames = lavPinInfo.has_b_frames; } } // Open the decoder int ret = avcodec_open2(m_pAVCtx, m_pAVCodec, NULL); if (ret >= 0) { DbgLog((LOG_TRACE, 10, L"-> ffmpeg codec opened successfully (ret: %d)", ret)); m_nCodecId = codec; } else { DbgLog((LOG_TRACE, 10, L"-> ffmpeg codec failed to open (ret: %d)", ret)); DestroyDecoder(); return VFW_E_UNSUPPORTED_VIDEO; } m_iInterlaced = 0; for (int i = 0; i < countof(ff_interlace_capable); i++) { if (codec == ff_interlace_capable[i]) { m_iInterlaced = -1; break; } } // Detect chroma and interlaced if (m_pAVCtx->extradata && m_pAVCtx->extradata_size) { if (codec == AV_CODEC_ID_MPEG2VIDEO) { CMPEG2HeaderParser mpeg2Parser(extra, extralen); if (mpeg2Parser.hdr.valid) { if (mpeg2Parser.hdr.chroma < 2) { m_pAVCtx->pix_fmt = PIX_FMT_YUV420P; } else if (mpeg2Parser.hdr.chroma == 2) { m_pAVCtx->pix_fmt = PIX_FMT_YUV422P; } m_iInterlaced = mpeg2Parser.hdr.interlaced; } } else if (codec == AV_CODEC_ID_H264) { CH264SequenceParser h264parser; if (bH264avc) h264parser.ParseNALs(extra+6, extralen-6, 2); else h264parser.ParseNALs(extra, extralen, 0); if (h264parser.sps.valid) m_iInterlaced = h264parser.sps.interlaced; } else if (codec == AV_CODEC_ID_VC1) { CVC1HeaderParser vc1parser(extra, extralen); if (vc1parser.hdr.valid) m_iInterlaced = (vc1parser.hdr.interlaced ? -1 : 0); } } if (codec == AV_CODEC_ID_DNXHD) m_pAVCtx->pix_fmt = PIX_FMT_YUV422P10; else if (codec == AV_CODEC_ID_FRAPS) m_pAVCtx->pix_fmt = PIX_FMT_BGR24; if (bLAVInfoValid && codec != AV_CODEC_ID_FRAPS && m_pAVCtx->pix_fmt != AV_PIX_FMT_DXVA2_VLD) m_pAVCtx->pix_fmt = lavPinInfo.pix_fmt; DbgLog((LOG_TRACE, 10, L"AVCodec init successfull. interlaced: %d", m_iInterlaced)); return S_OK; }
bool SmackerDecoder::loadStream(Common::SeekableReadStream *stream) { close(); _fileStream = stream; // Read in the Smacker header _header.signature = _fileStream->readUint32BE(); if (_header.signature != MKTAG('S', 'M', 'K', '2') && _header.signature != MKTAG('S', 'M', 'K', '4')) return false; uint32 width = _fileStream->readUint32LE(); uint32 height = _fileStream->readUint32LE(); uint32 frameCount = _fileStream->readUint32LE(); int32 frameDelay = _fileStream->readSint32LE(); // frame rate contains 2 digits after the comma, so 1497 is actually 14.97 fps Common::Rational frameRate; if (frameDelay > 0) frameRate = Common::Rational(1000, frameDelay); else if (frameDelay < 0) frameRate = Common::Rational(100000, -frameDelay); else frameRate = 1000; // Flags are determined by which bit is set, which can be one of the following: // 0 - set to 1 if file contains a ring frame. // 1 - set to 1 if file is Y-interlaced // 2 - set to 1 if file is Y-doubled // If bits 1 or 2 are set, the frame should be scaled to twice its height // before it is displayed. _header.flags = _fileStream->readUint32LE(); SmackerVideoTrack *videoTrack = createVideoTrack(width, height, frameCount, frameRate, _header.flags, _header.signature); addTrack(videoTrack); // TODO: should we do any extra processing for Smacker files with ring frames? // TODO: should we do any extra processing for Y-doubled videos? Are they the // same as Y-interlaced videos? uint32 i; for (i = 0; i < 7; ++i) _header.audioSize[i] = _fileStream->readUint32LE(); _header.treesSize = _fileStream->readUint32LE(); _header.mMapSize = _fileStream->readUint32LE(); _header.mClrSize = _fileStream->readUint32LE(); _header.fullSize = _fileStream->readUint32LE(); _header.typeSize = _fileStream->readUint32LE(); for (i = 0; i < 7; ++i) { // AudioRate - Frequency and format information for each sound track, up to 7 audio tracks. // The 32 constituent bits have the following meaning: // * bit 31 - indicates Huffman + DPCM compression // * bit 30 - indicates that audio data is present for this track // * bit 29 - 1 = 16-bit audio; 0 = 8-bit audio // * bit 28 - 1 = stereo audio; 0 = mono audio // * bit 27 - indicates Bink RDFT compression // * bit 26 - indicates Bink DCT compression // * bits 25-24 - unused // * bits 23-0 - audio sample rate uint32 audioInfo = _fileStream->readUint32LE(); _header.audioInfo[i].hasAudio = audioInfo & 0x40000000; _header.audioInfo[i].is16Bits = audioInfo & 0x20000000; _header.audioInfo[i].isStereo = audioInfo & 0x10000000; _header.audioInfo[i].sampleRate = audioInfo & 0xFFFFFF; if (audioInfo & 0x8000000) _header.audioInfo[i].compression = kCompressionRDFT; else if (audioInfo & 0x4000000) _header.audioInfo[i].compression = kCompressionDCT; else if (audioInfo & 0x80000000) _header.audioInfo[i].compression = kCompressionDPCM; else _header.audioInfo[i].compression = kCompressionNone; if (_header.audioInfo[i].hasAudio) { if (_header.audioInfo[i].compression == kCompressionRDFT || _header.audioInfo[i].compression == kCompressionDCT) warning("Unhandled Smacker v2 audio compression"); addTrack(new SmackerAudioTrack(_header.audioInfo[i], _soundType)); } } _header.dummy = _fileStream->readUint32LE(); _frameSizes = new uint32[frameCount]; for (i = 0; i < frameCount; ++i) _frameSizes[i] = _fileStream->readUint32LE(); _frameTypes = new byte[frameCount]; for (i = 0; i < frameCount; ++i) _frameTypes[i] = _fileStream->readByte(); byte *huffmanTrees = (byte *) malloc(_header.treesSize); _fileStream->read(huffmanTrees, _header.treesSize); Common::BitStream8LSB bs(new Common::MemoryReadStream(huffmanTrees, _header.treesSize, DisposeAfterUse::YES), true); videoTrack->readTrees(bs, _header.mMapSize, _header.mClrSize, _header.fullSize, _header.typeSize); _firstFrameStart = _fileStream->pos(); return true; }
* License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libavutil/error.h" #include "libavcodec/avcodec.h" #include "avformat.h" #include "riff.h" /* Note: When encoding, the first matching tag is used, so order is * important if multiple tags are possible for a given codec. * Note also that this list is used for more than just riff, other * files use it as well. */ const AVCodecTag ff_codec_bmp_tags[] = { { AV_CODEC_ID_H264, MKTAG('H', '2', '6', '4') }, { AV_CODEC_ID_H264, MKTAG('h', '2', '6', '4') }, { AV_CODEC_ID_H264, MKTAG('X', '2', '6', '4') }, { AV_CODEC_ID_H264, MKTAG('x', '2', '6', '4') }, { AV_CODEC_ID_H264, MKTAG('a', 'v', 'c', '1') }, { AV_CODEC_ID_H264, MKTAG('D', 'A', 'V', 'C') }, { AV_CODEC_ID_H264, MKTAG('S', 'M', 'V', '2') }, { AV_CODEC_ID_H264, MKTAG('V', 'S', 'S', 'H') }, { AV_CODEC_ID_H264, MKTAG('Q', '2', '6', '4') }, /* QNAP surveillance system */ { AV_CODEC_ID_H264, MKTAG('V', '2', '6', '4') }, /* CCTV recordings */ { AV_CODEC_ID_H264, MKTAG('G', 'A', 'V', 'C') }, /* GeoVision camera */ { AV_CODEC_ID_H264, MKTAG('U', 'M', 'S', 'V') }, { AV_CODEC_ID_H264, MKTAG('t', 's', 'h', 'd') }, { AV_CODEC_ID_H264, MKTAG('I', 'N', 'M', 'C') }, { AV_CODEC_ID_H263, MKTAG('H', '2', '6', '3') }, { AV_CODEC_ID_H263, MKTAG('X', '2', '6', '3') },
void SmackerDecoder::SmackerVideoTrack::decodeFrame(Common::BitStream &bs) { _MMapTree->reset(); _MClrTree->reset(); _FullTree->reset(); _TypeTree->reset(); // Height needs to be doubled if we have flags (Y-interlaced or Y-doubled) uint doubleY = _flags ? 2 : 1; uint bw = getWidth() / 4; uint bh = getHeight() / doubleY / 4; uint stride = getWidth(); uint block = 0, blocks = bw*bh; byte *out; uint type, run, j, mode; uint32 p1, p2, clr, map; byte hi, lo; uint i; while (block < blocks) { type = _TypeTree->getCode(bs); run = getBlockRun((type >> 2) & 0x3f); switch (type & 3) { case SMK_BLOCK_MONO: while (run-- && block < blocks) { clr = _MClrTree->getCode(bs); map = _MMapTree->getCode(bs); out = (byte *)_surface->getPixels() + (block / bw) * (stride * 4 * doubleY) + (block % bw) * 4; hi = clr >> 8; lo = clr & 0xff; for (i = 0; i < 4; i++) { for (j = 0; j < doubleY; j++) { out[0] = (map & 1) ? hi : lo; out[1] = (map & 2) ? hi : lo; out[2] = (map & 4) ? hi : lo; out[3] = (map & 8) ? hi : lo; out += stride; } map >>= 4; } ++block; } break; case SMK_BLOCK_FULL: // Smacker v2 has one mode, Smacker v4 has three if (_signature == MKTAG('S','M','K','2')) { mode = 0; } else { // 00 - mode 0 // 10 - mode 1 // 01 - mode 2 mode = 0; if (bs.getBit()) { mode = 1; } else if (bs.getBit()) { mode = 2; } } while (run-- && block < blocks) { out = (byte *)_surface->getPixels() + (block / bw) * (stride * 4 * doubleY) + (block % bw) * 4; switch (mode) { case 0: for (i = 0; i < 4; ++i) { p1 = _FullTree->getCode(bs); p2 = _FullTree->getCode(bs); for (j = 0; j < doubleY; ++j) { out[2] = p1 & 0xff; out[3] = p1 >> 8; out[0] = p2 & 0xff; out[1] = p2 >> 8; out += stride; } } break; case 1: p1 = _FullTree->getCode(bs); out[0] = out[1] = p1 & 0xFF; out[2] = out[3] = p1 >> 8; out += stride; out[0] = out[1] = p1 & 0xFF; out[2] = out[3] = p1 >> 8; out += stride; p2 = _FullTree->getCode(bs); out[0] = out[1] = p2 & 0xFF; out[2] = out[3] = p2 >> 8; out += stride; out[0] = out[1] = p2 & 0xFF; out[2] = out[3] = p2 >> 8; out += stride; break; case 2: for (i = 0; i < 2; i++) { // We first get p2 and then p1 // Check ffmpeg thread "[PATCH] Smacker video decoder bug fix" // http://article.gmane.org/gmane.comp.video.ffmpeg.devel/78768 p2 = _FullTree->getCode(bs); p1 = _FullTree->getCode(bs); for (j = 0; j < doubleY; ++j) { out[0] = p1 & 0xff; out[1] = p1 >> 8; out[2] = p2 & 0xff; out[3] = p2 >> 8; out += stride; } for (j = 0; j < doubleY; ++j) { out[0] = p1 & 0xff; out[1] = p1 >> 8; out[2] = p2 & 0xff; out[3] = p2 >> 8; out += stride; } } break; } ++block; } break; case SMK_BLOCK_SKIP: while (run-- && block < blocks) block++; break; case SMK_BLOCK_FILL: uint32 col; mode = type >> 8; while (run-- && block < blocks) { out = (byte *)_surface->getPixels() + (block / bw) * (stride * 4 * doubleY) + (block % bw) * 4; col = mode * 0x01010101; for (i = 0; i < 4 * doubleY; ++i) { out[0] = out[1] = out[2] = out[3] = col; out += stride; } ++block; } break; } } }
av_cold int ff_decklink_read_header(AVFormatContext *avctx) { struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data; struct decklink_ctx *ctx; AVStream *st; HRESULT result; char fname[1024]; char *tmp; int mode_num = 0; int ret; ctx = (struct decklink_ctx *) av_mallocz(sizeof(struct decklink_ctx)); if (!ctx) return AVERROR(ENOMEM); ctx->list_devices = cctx->list_devices; ctx->list_formats = cctx->list_formats; ctx->teletext_lines = cctx->teletext_lines; ctx->preroll = cctx->preroll; ctx->duplex_mode = cctx->duplex_mode; if (cctx->video_input > 0 && (unsigned int)cctx->video_input < FF_ARRAY_ELEMS(decklink_video_connection_map)) ctx->video_input = decklink_video_connection_map[cctx->video_input]; if (cctx->audio_input > 0 && (unsigned int)cctx->audio_input < FF_ARRAY_ELEMS(decklink_audio_connection_map)) ctx->audio_input = decklink_audio_connection_map[cctx->audio_input]; ctx->audio_pts_source = cctx->audio_pts_source; ctx->video_pts_source = cctx->video_pts_source; ctx->draw_bars = cctx->draw_bars; cctx->ctx = ctx; #if !CONFIG_LIBZVBI if (ctx->teletext_lines) { av_log(avctx, AV_LOG_ERROR, "Libzvbi support is needed for capturing teletext, please recompile FFmpeg.\n"); return AVERROR(ENOSYS); } #endif /* Check audio channel option for valid values: 2, 8 or 16 */ switch (cctx->audio_channels) { case 2: case 8: case 16: break; default: av_log(avctx, AV_LOG_ERROR, "Value of channels option must be one of 2, 8 or 16\n"); return AVERROR(EINVAL); } /* List available devices. */ if (ctx->list_devices) { ff_decklink_list_devices(avctx); return AVERROR_EXIT; } strcpy (fname, avctx->filename); tmp=strchr (fname, '@'); if (tmp != NULL) { mode_num = atoi (tmp+1); *tmp = 0; } ret = ff_decklink_init_device(avctx, fname); if (ret < 0) return ret; /* Get input device. */ if (ctx->dl->QueryInterface(IID_IDeckLinkInput, (void **) &ctx->dli) != S_OK) { av_log(avctx, AV_LOG_ERROR, "Could not open input device from '%s'\n", avctx->filename); ret = AVERROR(EIO); goto error; } /* List supported formats. */ if (ctx->list_formats) { ff_decklink_list_formats(avctx, DIRECTION_IN); ret = AVERROR_EXIT; goto error; } if (mode_num > 0) { if (ff_decklink_set_format(avctx, DIRECTION_IN, mode_num) < 0) { av_log(avctx, AV_LOG_ERROR, "Could not set mode %d for %s\n", mode_num, fname); ret = AVERROR(EIO); goto error; } } /* Setup streams. */ st = avformat_new_stream(avctx, NULL); if (!st) { av_log(avctx, AV_LOG_ERROR, "Cannot add stream\n"); ret = AVERROR(ENOMEM); goto error; } st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE; st->codecpar->sample_rate = bmdAudioSampleRate48kHz; st->codecpar->channels = cctx->audio_channels; avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ ctx->audio_st=st; st = avformat_new_stream(avctx, NULL); if (!st) { av_log(avctx, AV_LOG_ERROR, "Cannot add stream\n"); ret = AVERROR(ENOMEM); goto error; } st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; st->codecpar->width = ctx->bmd_width; st->codecpar->height = ctx->bmd_height; st->time_base.den = ctx->bmd_tb_den; st->time_base.num = ctx->bmd_tb_num; av_stream_set_r_frame_rate(st, av_make_q(st->time_base.den, st->time_base.num)); if (cctx->v210) { st->codecpar->codec_id = AV_CODEC_ID_V210; st->codecpar->codec_tag = MKTAG('V', '2', '1', '0'); st->codecpar->bit_rate = av_rescale(ctx->bmd_width * ctx->bmd_height * 64, st->time_base.den, st->time_base.num * 3); } else { st->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO; st->codecpar->format = AV_PIX_FMT_UYVY422; st->codecpar->codec_tag = MKTAG('U', 'Y', 'V', 'Y'); st->codecpar->bit_rate = av_rescale(ctx->bmd_width * ctx->bmd_height * 16, st->time_base.den, st->time_base.num); } avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ ctx->video_st=st; if (ctx->teletext_lines) { st = avformat_new_stream(avctx, NULL); if (!st) { av_log(avctx, AV_LOG_ERROR, "Cannot add stream\n"); ret = AVERROR(ENOMEM); goto error; } st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE; st->time_base.den = ctx->bmd_tb_den; st->time_base.num = ctx->bmd_tb_num; st->codecpar->codec_id = AV_CODEC_ID_DVB_TELETEXT; avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ ctx->teletext_st = st; } av_log(avctx, AV_LOG_VERBOSE, "Using %d input audio channels\n", ctx->audio_st->codecpar->channels); result = ctx->dli->EnableAudioInput(bmdAudioSampleRate48kHz, bmdAudioSampleType16bitInteger, ctx->audio_st->codecpar->channels); if (result != S_OK) { av_log(avctx, AV_LOG_ERROR, "Cannot enable audio input\n"); ret = AVERROR(EIO); goto error; } result = ctx->dli->EnableVideoInput(ctx->bmd_mode, cctx->v210 ? bmdFormat10BitYUV : bmdFormat8BitYUV, bmdVideoInputFlagDefault); if (result != S_OK) { av_log(avctx, AV_LOG_ERROR, "Cannot enable video input\n"); ret = AVERROR(EIO); goto error; } avpacket_queue_init (avctx, &ctx->queue); if (decklink_start_input (avctx) != S_OK) { av_log(avctx, AV_LOG_ERROR, "Cannot start input stream\n"); ret = AVERROR(EIO); goto error; } return 0; error: ff_decklink_cleanup(avctx); return ret; }
* * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libavutil/channel_layout.h" #include "libavutil/imgutils.h" #include "libavutil/intreadwrite.h" #include "libavutil/intfloat.h" #include "avformat.h" #include "internal.h" #include "riff.h" static const AVCodecTag nuv_audio_tags[] = { { AV_CODEC_ID_PCM_S16LE, MKTAG('R', 'A', 'W', 'A') }, { AV_CODEC_ID_MP3, MKTAG('L', 'A', 'M', 'E') }, { AV_CODEC_ID_NONE, 0 }, }; typedef struct NUVContext { int v_id; int a_id; int rtjpg_video; } NUVContext; typedef enum { NUV_VIDEO = 'V', NUV_EXTRADATA = 'D', NUV_AUDIO = 'A', NUV_SEEKP = 'R',
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; }
/** * @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 0 or AVERROR code */ static int get_codec_data(AVFormatContext *s, AVIOContext *pb, AVStream *vst, AVStream *ast, int myth) { nuv_frametype frametype; if (!vst && !myth) return 1; // no codec data needed while (!avio_feof(pb)) { int size, subtype; frametype = avio_r8(pb); switch (frametype) { case NUV_EXTRADATA: subtype = avio_r8(pb); avio_skip(pb, 6); size = PKTSIZE(avio_rl32(pb)); if (vst && subtype == 'R') { if (vst->codecpar->extradata) { av_freep(&vst->codecpar->extradata); vst->codecpar->extradata_size = 0; } if (ff_get_extradata(NULL, vst->codecpar, pb, size) < 0) return AVERROR(ENOMEM); size = 0; if (!myth) return 0; } break; case NUV_MYTHEXT: avio_skip(pb, 7); size = PKTSIZE(avio_rl32(pb)); if (size != 128 * 4) break; avio_rl32(pb); // version if (vst) { vst->codecpar->codec_tag = avio_rl32(pb); vst->codecpar->codec_id = ff_codec_get_id(ff_codec_bmp_tags, vst->codecpar->codec_tag); if (vst->codecpar->codec_tag == MKTAG('R', 'J', 'P', 'G')) vst->codecpar->codec_id = AV_CODEC_ID_NUV; } else avio_skip(pb, 4); if (ast) { int id; ast->codecpar->codec_tag = avio_rl32(pb); ast->codecpar->sample_rate = avio_rl32(pb); if (ast->codecpar->sample_rate <= 0) { av_log(s, AV_LOG_ERROR, "Invalid sample rate %d\n", ast->codecpar->sample_rate); return AVERROR_INVALIDDATA; } ast->codecpar->bits_per_coded_sample = avio_rl32(pb); ast->codecpar->channels = avio_rl32(pb); ast->codecpar->channel_layout = 0; id = ff_wav_codec_get_id(ast->codecpar->codec_tag, ast->codecpar->bits_per_coded_sample); if (id == AV_CODEC_ID_NONE) { id = ff_codec_get_id(nuv_audio_tags, ast->codecpar->codec_tag); if (id == AV_CODEC_ID_PCM_S16LE) id = ff_get_pcm_codec_id(ast->codecpar->bits_per_coded_sample, 0, 0, ~1); } ast->codecpar->codec_id = id; ast->need_parsing = AVSTREAM_PARSE_FULL; } else avio_skip(pb, 4 * 4); size -= 6 * 4; avio_skip(pb, size); return 0; case NUV_SEEKP: size = 11; break; default: avio_skip(pb, 7); size = PKTSIZE(avio_rl32(pb)); break; } avio_skip(pb, size); } return 0; }
#define SINGLE_PAYLOAD_DATA_LENGTH (\ PACKET_SIZE - \ PACKET_HEADER_MIN_SIZE - \ PAYLOAD_HEADER_SIZE_SINGLE_PAYLOAD \ ) #define MULTI_PAYLOAD_CONSTANT (\ PACKET_SIZE - \ PACKET_HEADER_MIN_SIZE - \ 1 - /*Payload Flags*/ \ 2*PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS \ ) static const AVCodecTag codec_asf_bmp_tags[] = { { CODEC_ID_MPEG4, MKTAG('M', 'P', '4', 'S') }, { CODEC_ID_MPEG4, MKTAG('M', '4', 'S', '2') }, { CODEC_ID_MSMPEG4V3, MKTAG('M', 'P', '4', '3') }, { CODEC_ID_NONE, 0 }, }; #define PREROLL_TIME 3100 static void put_guid(ByteIOContext *s, const ff_asf_guid *g) { assert(sizeof(*g) == 16); put_buffer(s, *g, sizeof(*g)); } static void put_str16(ByteIOContext *s, const char *tag) {
static int r3d_probe(AVProbeData *p) { if (AV_RL32(p->buf + 4) == MKTAG('R','E','D','1')) return AVPROBE_SCORE_MAX; return 0; }
void RenderManager::readImageToSurface(const Common::String &fileName, Graphics::Surface &destination) { Common::File file; if (!file.open(fileName)) { warning("Could not open file %s", fileName.c_str()); return; } // Read the magic number // Some files are true TGA, while others are TGZ uint32 fileType = file.readUint32BE(); uint32 imageWidth; uint32 imageHeight; Graphics::TGADecoder tga; uint16 *buffer; bool isTransposed = _renderTable.getRenderState() == RenderTable::PANORAMA; // All ZVision images are in RGB 555 Graphics::PixelFormat pixelFormat555 = Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0); destination.format = pixelFormat555; bool isTGZ; // Check for TGZ files if (fileType == MKTAG('T', 'G', 'Z', '\0')) { isTGZ = true; // TGZ files have a header and then Bitmap data that is compressed with LZSS uint32 decompressedSize = file.readSint32LE(); imageWidth = file.readSint32LE(); imageHeight = file.readSint32LE(); LzssReadStream lzssStream(&file); buffer = (uint16 *)(new uint16[decompressedSize]); lzssStream.read(buffer, decompressedSize); } else { isTGZ = false; // Reset the cursor file.seek(0); // Decode if (!tga.loadStream(file)) { warning("Error while reading TGA image"); return; } Graphics::Surface tgaSurface = *(tga.getSurface()); imageWidth = tgaSurface.w; imageHeight = tgaSurface.h; buffer = (uint16 *)tgaSurface.getPixels(); } // Flip the width and height if transposed if (isTransposed) { uint16 temp = imageHeight; imageHeight = imageWidth; imageWidth = temp; } // If the destination internal buffer is the same size as what we're copying into it, // there is no need to free() and re-create if (imageWidth != destination.w || imageHeight != destination.h) { destination.create(imageWidth, imageHeight, pixelFormat555); } // If transposed, 'un-transpose' the data while copying it to the destination // Otherwise, just do a simple copy if (isTransposed) { uint16 *dest = (uint16 *)destination.getPixels(); for (uint32 y = 0; y < imageHeight; ++y) { uint32 columnIndex = y * imageWidth; for (uint32 x = 0; x < imageWidth; ++x) { dest[columnIndex + x] = buffer[x * imageHeight + y]; } } } else { memcpy(destination.getPixels(), buffer, imageWidth * imageHeight * _pixelFormat.bytesPerPixel); } // Cleanup if (isTGZ) { delete[] buffer; } else { tga.destroy(); } // Convert in place to RGB 565 from RGB 555 destination.convertToInPlace(_pixelFormat); }
* Dump GFFs into XML files. */ #include "src/common/util.h" #include "src/common/strutil.h" #include "src/common/error.h" #include "src/common/readstream.h" #include "src/aurora/types.h" #include "src/xml/gffdumper.h" #include "src/xml/gff3dumper.h" #include "src/xml/gff4dumper.h" static const uint32 kGFFTypes[] = { MKTAG('A', 'R', 'E', ' '), MKTAG('B', 'I', 'C', ' '), MKTAG('B', 'T', 'C', ' '), MKTAG('B', 'T', 'D', ' '), MKTAG('B', 'T', 'E', ' '), MKTAG('B', 'T', 'G', ' '), MKTAG('B', 'T', 'I', ' '), MKTAG('B', 'T', 'M', ' '), MKTAG('B', 'T', 'P', ' '), MKTAG('B', 'T', 'S', ' '), MKTAG('B', 'T', 'T', ' '), MKTAG('C', 'A', 'M', ' '), MKTAG('C', 'R', 'E', ' '), MKTAG('C', 'U', 'T', ' '), MKTAG('C', 'W', 'A', ' '), MKTAG('D', 'L', 'G', ' '),
static int dshow_add_device(AVFormatContext *avctx, enum dshowDeviceType devtype) { struct dshow_ctx *ctx = avctx->priv_data; AM_MEDIA_TYPE type; AVCodecContext *codec; AVStream *st; int ret = AVERROR(EIO); st = avformat_new_stream(avctx, NULL); if (!st) { ret = AVERROR(ENOMEM); goto error; } st->id = devtype; ctx->capture_filter[devtype]->stream_index = st->index; libAVPin_ConnectionMediaType(ctx->capture_pin[devtype], &type); codec = st->codec; if (devtype == VideoDevice) { BITMAPINFOHEADER *bih = NULL; AVRational time_base; if (IsEqualGUID(&type.formattype, &FORMAT_VideoInfo)) { VIDEOINFOHEADER *v = (void *) type.pbFormat; time_base = (AVRational) { v->AvgTimePerFrame, 10000000 }; bih = &v->bmiHeader; } else if (IsEqualGUID(&type.formattype, &FORMAT_VideoInfo2)) { VIDEOINFOHEADER2 *v = (void *) type.pbFormat; time_base = (AVRational) { v->AvgTimePerFrame, 10000000 }; bih = &v->bmiHeader; } if (!bih) { av_log(avctx, AV_LOG_ERROR, "Could not get media type.\n"); goto error; } codec->time_base = time_base; codec->codec_type = AVMEDIA_TYPE_VIDEO; codec->width = bih->biWidth; codec->height = bih->biHeight; codec->codec_tag = bih->biCompression; codec->pix_fmt = dshow_pixfmt(bih->biCompression, bih->biBitCount); if (bih->biCompression == MKTAG('H', 'D', 'Y', 'C')) { av_log(avctx, AV_LOG_DEBUG, "attempt to use full range for HDYC...\n"); codec->color_range = AVCOL_RANGE_MPEG; // just in case it needs this... } if (codec->pix_fmt == AV_PIX_FMT_NONE) { codec->codec_id = ff_codec_get_id(avformat_get_riff_video_tags(), bih->biCompression); if (codec->codec_id == AV_CODEC_ID_NONE) { av_log(avctx, AV_LOG_ERROR, "Unknown compression type. " "Please report type 0x%X.\n", (int) bih->biCompression); return AVERROR_PATCHWELCOME; } codec->bits_per_coded_sample = bih->biBitCount; } else { codec->codec_id = AV_CODEC_ID_RAWVIDEO; if (bih->biCompression == BI_RGB || bih->biCompression == BI_BITFIELDS) { codec->bits_per_coded_sample = bih->biBitCount; codec->extradata = av_malloc(9 + FF_INPUT_BUFFER_PADDING_SIZE); if (codec->extradata) { codec->extradata_size = 9; memcpy(codec->extradata, "BottomUp", 9); } } } } else { WAVEFORMATEX *fx = NULL; if (IsEqualGUID(&type.formattype, &FORMAT_WaveFormatEx)) { fx = (void *) type.pbFormat; } if (!fx) { av_log(avctx, AV_LOG_ERROR, "Could not get media type.\n"); goto error; } codec->codec_type = AVMEDIA_TYPE_AUDIO; codec->sample_fmt = sample_fmt_bits_per_sample(fx->wBitsPerSample); codec->codec_id = waveform_codec_id(codec->sample_fmt); codec->sample_rate = fx->nSamplesPerSec; codec->channels = fx->nChannels; } avpriv_set_pts_info(st, 64, 1, 10000000); ret = 0; error: return ret; }
{ { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x07,0x04,0x02,0x02,0x01,0x7E,0x00,0x00,0x00 }, 13, AV_CODEC_ID_PCM_S16BE }, /* From Omneon MXF file */ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x04,0x04,0x02,0x02,0x02,0x03,0x01,0x01,0x00 }, 15, AV_CODEC_ID_PCM_ALAW }, /* XDCAM Proxy C0023S01.mxf */ { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x02,0x03,0x02,0x01,0x00 }, 15, AV_CODEC_ID_AC3 }, { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x02,0x03,0x02,0x05,0x00 }, 15, AV_CODEC_ID_MP2 }, /* MP2 or MP3 */ //{ { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x02,0x03,0x02,0x1C,0x00 }, 15, AV_CODEC_ID_DOLBY_E }, /* Dolby-E */ { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AV_CODEC_ID_NONE }, }; const MXFCodecUL ff_mxf_pixel_format_uls[] = { { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x01,0x01,0x02,0x01,0x01 }, 16, AV_PIX_FMT_UYVY422 }, { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x01,0x01,0x02,0x01,0x02 }, 16, AV_PIX_FMT_YUYV422 }, { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AV_PIX_FMT_NONE }, }; const MXFCodecUL ff_mxf_codec_tag_uls[] = { { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0E,0x04,0x03,0x01,0x01,0x03,0x01,0x00 }, 15, MKTAG('A', 'V', 'u', 'p') }, /* Avid 1:1 */ { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, 0 }, }; static const struct { enum AVPixelFormat pix_fmt; const char data[16]; } ff_mxf_pixel_layouts[] = { /** * See SMPTE 377M E.2.46 * * Note: Only RGB, palette based and "abnormal" YUV pixel formats like 4:2:2:4 go here. * For regular YUV, use CDCIPictureEssenceDescriptor. * * Note: Do not use these for encoding descriptors for little-endian formats until we * get samples or official word from SMPTE on how/if those can be encoded.
/* aiff input */ static int aiff_read_header(AVFormatContext *s) { int ret, size, filesize; int64_t offset = 0, position; uint32_t tag; unsigned version = AIFF_C_VERSION1; AVIOContext *pb = s->pb; AVStream * st; AIFFInputContext *aiff = s->priv_data; ID3v2ExtraMeta *id3v2_extra_meta = NULL; /* check FORM header */ filesize = get_tag(pb, &tag); if (filesize < 0 || tag != MKTAG('F', 'O', 'R', 'M')) return AVERROR_INVALIDDATA; /* AIFF data type */ tag = avio_rl32(pb); if (tag == MKTAG('A', 'I', 'F', 'F')) /* Got an AIFF file */ version = AIFF; else if (tag != MKTAG('A', 'I', 'F', 'C')) /* An AIFF-C file then */ return AVERROR_INVALIDDATA; filesize -= 4; st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); while (filesize > 0) { /* parse different chunks */ size = get_tag(pb, &tag); if (size == AVERROR_EOF && offset > 0 && st->codec->block_align) { av_log(s, AV_LOG_WARNING, "header parser hit EOF\n"); goto got_sound; } 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(s, size, version); if (st->nb_frames < 0) return st->nb_frames; if (offset > 0) // COMM is after SSND goto got_sound; break; case MKTAG('I', 'D', '3', ' '): position = avio_tell(pb); 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 (position + size > avio_tell(pb)) avio_skip(pb, position + size - avio_tell(pb)); break; case MKTAG('F', 'V', 'E', 'R'): /* Version chunk */ version = avio_rb32(pb); break; case MKTAG('N', 'A', 'M', 'E'): /* Sample name chunk */ get_meta(s, "title" , size); break; case MKTAG('A', 'U', 'T', 'H'): /* Author chunk */ get_meta(s, "author" , size); break; case MKTAG('(', 'c', ')', ' '): /* Copyright chunk */ get_meta(s, "copyright", size); break; case MKTAG('A', 'N', 'N', 'O'): /* Annotation chunk */ get_meta(s, "comment" , size); break; case MKTAG('S', 'S', 'N', 'D'): /* Sampled sound chunk */ aiff->data_end = avio_tell(pb) + size; offset = avio_rb32(pb); /* Offset of sound data */ avio_rb32(pb); /* BlockSize... don't care */ offset += avio_tell(pb); /* Compute absolute data offset */ if (st->codec->block_align && !pb->seekable) /* Assume COMM already parsed */ goto got_sound; if (!pb->seekable) { av_log(s, AV_LOG_ERROR, "file is not seekable\n"); return -1; } avio_skip(pb, size - 8); break; case MKTAG('w', 'a', 'v', 'e'): if ((uint64_t)size > (1<<30)) return -1; if (ff_get_extradata(st->codec, pb, size) < 0) return AVERROR(ENOMEM); if (st->codec->codec_id == AV_CODEC_ID_QDM2 && size>=12*4 && !st->codec->block_align) { st->codec->block_align = AV_RB32(st->codec->extradata+11*4); aiff->block_duration = AV_RB32(st->codec->extradata+9*4); } else if (st->codec->codec_id == AV_CODEC_ID_QCELP) { char rate = 0; if (size >= 25) rate = st->codec->extradata[24]; switch (rate) { case 'H': // RATE_HALF st->codec->block_align = 17; break; case 'F': // RATE_FULL default: st->codec->block_align = 35; } aiff->block_duration = 160; st->codec->bit_rate = st->codec->sample_rate * (st->codec->block_align << 3) / aiff->block_duration; } break; case MKTAG('C','H','A','N'): if(ff_mov_read_chan(s, pb, st, size) < 0) return AVERROR_INVALIDDATA; break; case 0: if (offset > 0 && st->codec->block_align) // COMM && SSND goto got_sound; default: /* Jump */ if (size & 1) /* Always even aligned */ size++; avio_skip(pb, size); } } got_sound: if (!st->codec->block_align) { av_log(s, AV_LOG_ERROR, "could not find COMM tag or invalid block_align value\n"); return -1; } /* Now positioned, get the sound data start and end */ avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); st->start_time = 0; st->duration = st->nb_frames * aiff->block_duration; /* Position the stream at the first block */ avio_seek(pb, offset, SEEK_SET); return 0; }
return 0; } static int ivf_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) { int ret = 1; AVStream *st = s->streams[pkt->stream_index]; if (st->codecpar->codec_id == AV_CODEC_ID_VP9) ret = ff_stream_add_bitstream_filter(st, "vp9_superframe", NULL); return ret; } static const AVCodecTag codec_ivf_tags[] = { { AV_CODEC_ID_VP8, MKTAG('V', 'P', '8', '0') }, { AV_CODEC_ID_VP9, MKTAG('V', 'P', '9', '0') }, { AV_CODEC_ID_AV1, MKTAG('A', 'V', '0', '1') }, { AV_CODEC_ID_NONE, 0 } }; AVOutputFormat ff_ivf_muxer = { .priv_data_size = sizeof(IVFEncContext), .name = "ivf", .long_name = NULL_IF_CONFIG_SMALL("On2 IVF"), .extensions = "ivf", .audio_codec = AV_CODEC_ID_NONE, .video_codec = AV_CODEC_ID_VP8, .write_header = ivf_write_header, .write_packet = ivf_write_packet, .write_trailer = ivf_write_trailer,