📄 avidec.c
字号:
} /* * else, leave duration alone; timing estimation in utils.c * will make a guess based on bitrate. */ stream_index = s->nb_streams - 1; url_fskip(pb, size - 9*4); break; } assert(stream_index < s->nb_streams); st->codec->stream_codec_tag= handler; get_le32(pb); /* flags */ get_le16(pb); /* priority */ get_le16(pb); /* language */ get_le32(pb); /* initial frame */ ast->scale = get_le32(pb); ast->rate = get_le32(pb); if(!(ast->scale && ast->rate)){ av_log(s, AV_LOG_WARNING, "scale/rate is %u/%u which is invalid. (This file has been generated by broken software.)\n", ast->scale, ast->rate); if(frame_period){ ast->rate = 1000000; ast->scale = frame_period; }else{ ast->rate = 25; ast->scale = 1; } } av_set_pts_info(st, 64, ast->scale, ast->rate); ast->cum_len=get_le32(pb); /* start */ nb_frames = get_le32(pb); st->start_time = 0; st->duration = nb_frames; get_le32(pb); /* buffer size */ get_le32(pb); /* quality */ ast->sample_size = get_le32(pb); /* sample ssize */ ast->cum_len *= FFMAX(1, ast->sample_size);// av_log(NULL, AV_LOG_DEBUG, "%d %d %d %d\n", ast->rate, ast->scale, ast->start, ast->sample_size); switch(tag1) { case MKTAG('v', 'i', 'd', 's'): codec_type = CODEC_TYPE_VIDEO; ast->sample_size = 0; break; case MKTAG('a', 'u', 'd', 's'): codec_type = CODEC_TYPE_AUDIO; break; case MKTAG('t', 'x', 't', 's'): //FIXME codec_type = CODEC_TYPE_DATA; //CODEC_TYPE_SUB ? FIXME break; case MKTAG('d', 'a', 't', 's'): codec_type = CODEC_TYPE_DATA; break; default: av_log(s, AV_LOG_ERROR, "unknown stream type %X\n", tag1); goto fail; } ast->frame_offset= ast->cum_len; url_fskip(pb, size - 12 * 4); break; case MKTAG('s', 't', 'r', 'f'): /* stream header */ if (stream_index >= (unsigned)s->nb_streams || avi->dv_demux) { url_fskip(pb, size); } else { st = s->streams[stream_index]; switch(codec_type) { case CODEC_TYPE_VIDEO: if(amv_file_format){ st->codec->width=avih_width; st->codec->height=avih_height; st->codec->codec_type = CODEC_TYPE_VIDEO; st->codec->codec_id = CODEC_ID_AMV; url_fskip(pb, size); break; } get_le32(pb); /* size */ st->codec->width = get_le32(pb); st->codec->height = get_le32(pb); get_le16(pb); /* panes */ st->codec->bits_per_sample= get_le16(pb); /* depth */ tag1 = get_le32(pb); get_le32(pb); /* ImageSize */ get_le32(pb); /* XPelsPerMeter */ get_le32(pb); /* YPelsPerMeter */ get_le32(pb); /* ClrUsed */ get_le32(pb); /* ClrImportant */ if (tag1 == MKTAG('D', 'X', 'S', 'B')) { st->codec->codec_type = CODEC_TYPE_SUBTITLE; st->codec->codec_tag = tag1; st->codec->codec_id = CODEC_ID_XSUB; break; } if(size > 10*4 && size<(1<<30)){ st->codec->extradata_size= size - 10*4; st->codec->extradata= av_malloc(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); get_buffer(pb, st->codec->extradata, st->codec->extradata_size); } if(st->codec->extradata_size & 1) //FIXME check if the encoder really did this correctly get_byte(pb); /* Extract palette from extradata if bpp <= 8. */ /* This code assumes that extradata contains only palette. */ /* This is true for all paletted codecs implemented in FFmpeg. */ if (st->codec->extradata_size && (st->codec->bits_per_sample <= 8)) { st->codec->palctrl = av_mallocz(sizeof(AVPaletteControl));#ifdef WORDS_BIGENDIAN for (i = 0; i < FFMIN(st->codec->extradata_size, AVPALETTE_SIZE)/4; i++) st->codec->palctrl->palette[i] = bswap_32(((uint32_t*)st->codec->extradata)[i]);#else memcpy(st->codec->palctrl->palette, st->codec->extradata, FFMIN(st->codec->extradata_size, AVPALETTE_SIZE));#endif st->codec->palctrl->palette_changed = 1; }#ifdef DEBUG print_tag("video", tag1, 0);#endif st->codec->codec_type = CODEC_TYPE_VIDEO; st->codec->codec_tag = tag1; st->codec->codec_id = codec_get_id(codec_bmp_tags, tag1); st->need_parsing = AVSTREAM_PARSE_HEADERS; // This is needed to get the pict type which is necessary for generating correct pts.// url_fskip(pb, size - 5 * 4); break; case CODEC_TYPE_AUDIO: get_wav_header(pb, st->codec, size); if(ast->sample_size && st->codec->block_align && ast->sample_size != st->codec->block_align){ av_log(s, AV_LOG_WARNING, "sample size (%d) != block align (%d)\n", ast->sample_size, st->codec->block_align); ast->sample_size= st->codec->block_align; } if (size%2) /* 2-aligned (fix for Stargate SG-1 - 3x18 - Shades of Grey.avi) */ url_fskip(pb, 1); /* Force parsing as several audio frames can be in * one packet and timestamps refer to packet start. */ st->need_parsing = AVSTREAM_PARSE_TIMESTAMPS; /* ADTS header is in extradata, AAC without header must be * stored as exact frames. Parser not needed and it will * fail. */ if (st->codec->codec_id == CODEC_ID_AAC && st->codec->extradata_size) st->need_parsing = AVSTREAM_PARSE_NONE; /* AVI files with Xan DPCM audio (wrongly) declare PCM * audio in the header but have Axan as stream_code_tag. */ if (st->codec->stream_codec_tag == ff_get_fourcc("Axan")){ st->codec->codec_id = CODEC_ID_XAN_DPCM; st->codec->codec_tag = 0; } if (amv_file_format) st->codec->codec_id = CODEC_ID_ADPCM_IMA_AMV; break; default: st->codec->codec_type = CODEC_TYPE_DATA; st->codec->codec_id= CODEC_ID_NONE; st->codec->codec_tag= 0; url_fskip(pb, size); break; } } break; case MKTAG('i', 'n', 'd', 'x'): i= url_ftell(pb); if(!url_is_streamed(pb) && !(s->flags & AVFMT_FLAG_IGNIDX)){ read_braindead_odml_indx(s, 0); } url_fseek(pb, i+size, SEEK_SET); break; case MKTAG('v', 'p', 'r', 'p'): if(stream_index < (unsigned)s->nb_streams && size > 9*4){ AVRational active, active_aspect; st = s->streams[stream_index]; get_le32(pb); get_le32(pb); get_le32(pb); get_le32(pb); get_le32(pb); active_aspect.den= get_le16(pb); active_aspect.num= get_le16(pb); active.num = get_le32(pb); active.den = get_le32(pb); get_le32(pb); //nbFieldsPerFrame if(active_aspect.num && active_aspect.den && active.num && active.den){ st->codec->sample_aspect_ratio= av_div_q(active_aspect, active);//av_log(s, AV_LOG_ERROR, "vprp %d/%d %d/%d\n", active_aspect.num, active_aspect.den, active.num, active.den); } size -= 9*4; } url_fseek(pb, size, SEEK_CUR); break; case MKTAG('I', 'N', 'A', 'M'): avi_read_tag(pb, s->title, sizeof(s->title), size); break; case MKTAG('I', 'A', 'R', 'T'): avi_read_tag(pb, s->author, sizeof(s->author), size); break; case MKTAG('I', 'C', 'O', 'P'): avi_read_tag(pb, s->copyright, sizeof(s->copyright), size); break; case MKTAG('I', 'C', 'M', 'T'): avi_read_tag(pb, s->comment, sizeof(s->comment), size); break; case MKTAG('I', 'G', 'N', 'R'): avi_read_tag(pb, s->genre, sizeof(s->genre), size); break; case MKTAG('I', 'P', 'R', 'D'): avi_read_tag(pb, s->album, sizeof(s->album), size); break; case MKTAG('I', 'P', 'R', 'T'): avi_read_tag(pb, str_track, sizeof(str_track), size); sscanf(str_track, "%d", &s->track); break; default: if(size > 1000000){ av_log(s, AV_LOG_ERROR, "Something went wrong during header parsing, " "I will ignore it and try to continue anyway.\n"); avi->movi_list = url_ftell(pb) - 4; avi->movi_end = url_fsize(pb); goto end_of_header; } /* skip tag */ size += (size & 1); url_fskip(pb, size); break; } } end_of_header: /* check stream number */ if (stream_index != s->nb_streams - 1) { fail: return -1; } if(!avi->index_loaded && !url_is_streamed(pb)) avi_load_index(s); avi->index_loaded = 1; avi->non_interleaved |= guess_ni_flag(s); if(avi->non_interleaved) { av_log(s, AV_LOG_INFO, "non-interleaved AVI\n"); clean_index(s); } return 0;}static int avi_read_packet(AVFormatContext *s, AVPacket *pkt){ AVIContext *avi = s->priv_data; ByteIOContext *pb = s->pb; int n, d[8], size; offset_t i, sync; void* dstr; if (ENABLE_DV_DEMUXER && avi->dv_demux) { size = dv_get_packet(avi->dv_demux, pkt); if (size >= 0) return size; } if(avi->non_interleaved){ int best_stream_index = 0; AVStream *best_st= NULL; AVIStream *best_ast; int64_t best_ts= INT64_MAX; int i; for(i=0; i<s->nb_streams; i++){ AVStream *st = s->streams[i]; AVIStream *ast = st->priv_data; int64_t ts= ast->frame_offset; if(ast->sample_size) ts /= ast->sample_size; ts= av_rescale(ts, AV_TIME_BASE * (int64_t)st->time_base.num, st->time_base.den);// av_log(NULL, AV_LOG_DEBUG, "%"PRId64" %d/%d %"PRId64"\n", ts, st->time_base.num, st->time_base.den, ast->frame_offset); if(ts < best_ts && st->nb_index_entries){ best_ts= ts; best_st= st; best_stream_index= i; } } if(!best_st) return -1; best_ast = best_st->priv_data; best_ts= av_rescale(best_ts, best_st->time_base.den, AV_TIME_BASE * (int64_t)best_st->time_base.num); //FIXME a little ugly if(best_ast->remaining) i= av_index_search_timestamp(best_st, best_ts, AVSEEK_FLAG_ANY | AVSEEK_FLAG_BACKWARD); else i= av_index_search_timestamp(best_st, best_ts, AVSEEK_FLAG_ANY);// av_log(NULL, AV_LOG_DEBUG, "%d\n", i); if(i>=0){ int64_t pos= best_st->index_entries[i].pos; pos += best_ast->packet_size - best_ast->remaining; url_fseek(s->pb, pos + 8, SEEK_SET);// av_log(NULL, AV_LOG_DEBUG, "pos=%"PRId64"\n", pos); assert(best_ast->remaining <= best_ast->packet_size); avi->stream_index= best_stream_index; if(!best_ast->remaining) best_ast->packet_size= best_ast->remaining= best_st->index_entries[i].size; } }resync: if(avi->stream_index >= 0){ AVStream *st= s->streams[ avi->stream_index ]; AVIStream *ast= st->priv_data; int size; if(ast->sample_size <= 1) // minorityreport.AVI block_align=1024 sample_size=1 IMA-ADPCM size= INT_MAX; else if(ast->sample_size < 32) size= 64*ast->sample_size; else size= ast->sample_size; if(size > ast->remaining) size= ast->remaining; av_get_packet(pb, pkt, size); if(ast->has_pal && pkt->data && pkt->size<(unsigned)INT_MAX/2){ ast->has_pal=0; pkt->size += 4*256; pkt->data = av_realloc(pkt->data, pkt->size + FF_INPUT_BUFFER_PADDING_SIZE); if(pkt->data) memcpy(pkt->data + pkt->size - 4*256, ast->pal, 4*256); } if (ENABLE_DV_DEMUXER && avi->dv_demux) { dstr = pkt->destruct; size = dv_produce_packet(avi->dv_demux, pkt, pkt->data, pkt->size); pkt->destruct = dstr; pkt->flags |= PKT_FLAG_KEY; } else { /* XXX: How to handle B-frames in AVI? */ pkt->dts = ast->frame_offset;// pkt->dts += ast->start; if(ast->sample_size) pkt->dts /= ast->sample_size;//av_log(NULL, AV_LOG_DEBUG, "dts:%"PRId64" offset:%"PRId64" %d/%d smpl_siz:%d base:%d st:%d size:%d\n", pkt->dts, ast->frame_offset, ast->scale, ast->rate, ast->sample_size, AV_TIME_BASE, avi->stream_index, size); pkt->stream_index = avi->stream_index; if (st->codec->codec_type == CODEC_TYPE_VIDEO) { AVIndexEntry *e; int index; assert(st->index_entries); index= av_index_search_timestamp(st, pkt->dts, 0); e= &st->index_entries[index]; if(index >= 0 && e->timestamp == ast->frame_offset){ if (e->flags & AVINDEX_KEYFRAME) pkt->flags |= PKT_FLAG_KEY;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -