⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mov.c

📁 F:图像处理资料264264书籍ffmpeg-0.4.9-pre1VideoStream.rar 一个视频解压缩源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    if(sc) {        av_free(sc->chunk_offsets);        av_free(sc->sample_to_chunk);        av_free(sc->sample_sizes);        av_free(sc->keyframes);        av_free(sc->header_data);        av_free(sc->stts_data);                av_free(sc);    }}static inline uint32_t mov_to_tag(uint8_t *buf){    return MKTAG(buf[0], buf[1], buf[2], buf[3]);}static inline uint32_t to_be32(uint8_t *buf){    return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];}/* XXX: is it sufficient ? */static int mov_probe(AVProbeData *p){    unsigned int offset;    uint32_t tag;    /* check file header */    if (p->buf_size <= 12)        return 0;    offset = 0;    for(;;) {        /* ignore invalid offset */        if ((offset + 8) > (unsigned int)p->buf_size)            return 0;        tag = mov_to_tag(p->buf + offset + 4);        switch(tag) {        case MKTAG( 'm', 'o', 'o', 'v' ):        case MKTAG( 'w', 'i', 'd', 'e' ):        case MKTAG( 'f', 'r', 'e', 'e' ):        case MKTAG( 'm', 'd', 'a', 't' ):        case MKTAG( 'p', 'n', 'o', 't' ): /* detect movs with preview pics like ew.mov and april.mov */        case MKTAG( 'u', 'd', 't', 'a' ): /* Packet Video PVAuthor adds this and a lot of more junk */            return AVPROBE_SCORE_MAX;        case MKTAG( 'f', 't', 'y', 'p' ):        case MKTAG( 's', 'k', 'i', 'p' ):            offset = to_be32(p->buf+offset) + offset;            break;        default:            /* unrecognized tag */            return 0;        }    }    return 0;}static int mov_read_header(AVFormatContext *s, AVFormatParameters *ap){    MOVContext *mov = (MOVContext *) s->priv_data;    ByteIOContext *pb = &s->pb;    int i, j, nb, err;    MOV_atom_t atom = { 0, 0, 0 };    mov->fc = s;    mov->parse_table = mov_default_parse_table;#if 0    /* XXX: I think we should auto detect */    if(s->iformat->name[1] == 'p')        mov->mp4 = 1;#endif    if(!url_is_streamed(pb)) /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */	atom.size = url_filesize(url_fileno(pb));    else	atom.size = 0x7FFFFFFFFFFFFFFFLL;#ifdef DEBUG    av_log(NULL, AV_LOG_DEBUG, "filesz=%Ld\n", atom.size);#endif    /* check MOV header */    err = mov_read_default(mov, pb, atom);    if (err<0 || (!mov->found_moov && !mov->found_mdat)) {	av_log(s, AV_LOG_ERROR, "mov: header not found !!! (err:%d, moov:%d, mdat:%d) pos:%lld\n",		err, mov->found_moov, mov->found_mdat, url_ftell(pb));	return -1;    }#ifdef DEBUG    av_log(NULL, AV_LOG_DEBUG, "on_parse_exit_offset=%d\n", (int) url_ftell(pb));#endif    /* some cleanup : make sure we are on the mdat atom */    if(!url_is_streamed(pb) && (url_ftell(pb) != mov->mdat_offset))        url_fseek(pb, mov->mdat_offset, SEEK_SET);    mov->next_chunk_offset = mov->mdat_offset; /* initialise reading */#ifdef DEBUG    av_log(NULL, AV_LOG_DEBUG, "mdat_reset_offset=%d\n", (int) url_ftell(pb));#endif#ifdef DEBUG    av_log(NULL, AV_LOG_DEBUG, "streams= %d\n", s->nb_streams);#endif    mov->total_streams = nb = s->nb_streams;#if 1    for(i=0; i<s->nb_streams;) {        if(s->streams[i]->codec.codec_type == CODEC_TYPE_MOV_OTHER) {/* not audio, not video, delete */            av_free(s->streams[i]);            for(j=i+1; j<s->nb_streams; j++)                s->streams[j-1] = s->streams[j];            s->nb_streams--;        } else            i++;    }    for(i=0; i<s->nb_streams;i++) {        MOVStreamContext *sc;        sc = (MOVStreamContext *)s->streams[i]->priv_data;        sc->ffindex = i;        sc->is_ff_stream = 1;    }#endif#ifdef DEBUG    av_log(NULL, AV_LOG_DEBUG, "real streams= %d\n", s->nb_streams);#endif    return 0;}/* Yes, this is ugly... I didn't write the specs of QT :p *//* XXX:remove useless commented code sometime */static int mov_read_packet(AVFormatContext *s, AVPacket *pkt){    MOVContext *mov = (MOVContext *) s->priv_data;    MOVStreamContext *sc;    int64_t offset = 0x0FFFFFFFFFFFFFFFLL;    int i, a, b, m;    int size;    size = 0x0FFFFFFF;#ifdef MOV_SPLIT_CHUNKS    if (mov->partial) {        int idx;	sc = mov->partial;	idx = sc->sample_to_chunk_index;        if (idx < 0) return 0;	size = sc->sample_sizes[sc->current_sample];        sc->current_sample++;        sc->left_in_chunk--;        if (sc->left_in_chunk <= 0)            mov->partial = 0;        offset = mov->next_chunk_offset;        /* extract the sample */        goto readchunk;    }#endifagain:    sc = 0;    for(i=0; i<mov->total_streams; i++) {	MOVStreamContext *msc = mov->streams[i];	//av_log(NULL, AV_LOG_DEBUG, "MOCHUNK %ld  %d   %p  pos:%Ld\n", mov->streams[i]->next_chunk, mov->total_streams, mov->streams[i], url_ftell(&s->pb));        if ((msc->next_chunk < msc->chunk_count) && msc->next_chunk >= 0	   && (msc->chunk_offsets[msc->next_chunk] < offset)) {	    sc = msc;	    offset = msc->chunk_offsets[msc->next_chunk];	    //av_log(NULL, AV_LOG_DEBUG, "SELETED  %Ld  i:%d\n", offset, i);        }    }    if (!sc || offset==0x0FFFFFFFFFFFFFFFLL)	return -1;    sc->next_chunk++;    if(mov->next_chunk_offset < offset) { /* some meta data */        url_fskip(&s->pb, (offset - mov->next_chunk_offset));        mov->next_chunk_offset = offset;    }//av_log(NULL, AV_LOG_DEBUG, "chunk: [%i] %lli -> %lli\n", st_id, mov->next_chunk_offset, offset);    if(!sc->is_ff_stream) {        url_fskip(&s->pb, (offset - mov->next_chunk_offset));        mov->next_chunk_offset = offset;	offset = 0x0FFFFFFFFFFFFFFFLL;        goto again;    }    /* now get the chunk size... */    for(i=0; i<mov->total_streams; i++) {	MOVStreamContext *msc = mov->streams[i];	if ((msc->next_chunk < msc->chunk_count)	    && ((msc->chunk_offsets[msc->next_chunk] - offset) < size))	    size = msc->chunk_offsets[msc->next_chunk] - offset;    }#ifdef MOV_MINOLTA_FIX    //Make sure that size is according to sample_size (Needed by .mov files     //created on a Minolta Dimage Xi where audio chunks contains waste data in the end)    //Maybe we should really not only check sc->sample_size, but also sc->sample_sizes    //but I have no such movies    if (sc->sample_size > 0) {         int foundsize=0;        for(i=0; i<(sc->sample_to_chunk_sz); i++) {            if( (sc->sample_to_chunk[i].first)<=(sc->next_chunk) && (sc->sample_size>0) )            {		// I can't figure out why for PCM audio sample_size is always 1		// (it should actually be channels*bits_per_second/8) but it is.		AVCodecContext* cod = &s->streams[sc->ffindex]->codec;                if (sc->sample_size == 1 && (cod->codec_id == CODEC_ID_PCM_S16BE || cod->codec_id == CODEC_ID_PCM_S16LE))		    foundsize=(sc->sample_to_chunk[i].count*cod->channels*cod->bits_per_sample)/8;		else		    foundsize=sc->sample_to_chunk[i].count*sc->sample_size;            }#ifdef DEBUG            /*av_log(NULL, AV_LOG_DEBUG, "sample_to_chunk first=%ld count=%ld, id=%ld\n", sc->sample_to_chunk[i].first, sc->sample_to_chunk[i].count, sc->sample_to_chunk[i].id);*/#endif        }        if( (foundsize>0) && (foundsize<size) )        {#ifdef DEBUG            /*av_log(NULL, AV_LOG_DEBUG, "this size should actually be %d\n",foundsize);*/#endif            size=foundsize;        }    }#endif //MOV_MINOLTA_FIX#ifdef MOV_SPLIT_CHUNKS    /* split chunks into samples */    if (sc->sample_size == 0) {        int idx = sc->sample_to_chunk_index;        if ((idx + 1 < sc->sample_to_chunk_sz)	    && (sc->next_chunk >= sc->sample_to_chunk[idx + 1].first))           idx++;        sc->sample_to_chunk_index = idx;        if (idx >= 0 && sc->sample_to_chunk[idx].count != 1) {	    mov->partial = sc;            /* we'll have to get those samples before next chunk */            sc->left_in_chunk = sc->sample_to_chunk[idx].count - 1;            size = sc->sample_sizes[sc->current_sample];        }        sc->current_sample++;    }#endifreadchunk://av_log(NULL, AV_LOG_DEBUG, "chunk: [%i] %lli -> %lli (%i)\n", st_id, offset, offset + size, size);    if(size == 0x0FFFFFFF)        size = mov->mdat_size + mov->mdat_offset - offset;    if(size < 0)        return -1;    if(size == 0)        return -1;    url_fseek(&s->pb, offset, SEEK_SET);    //av_log(NULL, AV_LOG_DEBUG, "READCHUNK hlen: %d  %d off: %Ld   pos:%Ld\n", size, sc->header_len, offset, url_ftell(&s->pb));    if (sc->header_len > 0) {        av_new_packet(pkt, size + sc->header_len);        memcpy(pkt->data, sc->header_data, sc->header_len);        get_buffer(&s->pb, pkt->data + sc->header_len, size);        /* free header */        av_freep(&sc->header_data);        sc->header_len = 0;    } else {        av_new_packet(pkt, size);        get_buffer(&s->pb, pkt->data, pkt->size);    }    pkt->stream_index = sc->ffindex;        // If the keyframes table exists, mark any samples that are in the table as key frames.    // If no table exists, treat very sample as a key frame.    if (sc->keyframes) {                a = 0;        b = sc->keyframe_count - 1;                while (a < b) {            m = (a + b + 1) >> 1;            if (sc->keyframes[m] > sc->current_sample) {                b = m - 1;            } else {                a = m;            }            }                if (sc->keyframes[a] == sc->current_sample)            pkt->flags |= PKT_FLAG_KEY;    }    else        pkt->flags |= PKT_FLAG_KEY;#ifdef DEBUG/*    av_log(NULL, AV_LOG_DEBUG, "Packet (%d, %d, %ld) ", pkt->stream_index, st_id, pkt->size);    for(i=0; i<8; i++)        av_log(NULL, AV_LOG_DEBUG, "%02x ", pkt->data[i]);    for(i=0; i<8; i++)        av_log(NULL, AV_LOG_DEBUG, "%c ", (pkt->data[i]) & 0x7F);    puts("");*/#endif    mov->next_chunk_offset = offset + size;    return 0;}#if defined(MOV_SPLIT_CHUNKS) && defined(MOV_SEEK)/** * Seek method based on the one described in the Appendix C of QTFileFormat.pdf */static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp){    MOVContext* mov = (MOVContext *) s->priv_data;    MOVStreamContext* sc;    int32_t i, a, b, m;    int64_t sample_time;    int64_t start_time;    int32_t seek_sample, sample;    int32_t duration;    int32_t count;    int32_t chunk;    int32_t left_in_chunk;    int64_t chunk_file_offset;    int64_t sample_file_offset;    int32_t first_chunk_sample;    int32_t sample_to_chunk_idx;    int mov_idx;    // Find the corresponding mov stream    for (mov_idx = 0; mov_idx < mov->total_streams; mov_idx++)        if (mov->streams[mov_idx]->ffindex == stream_index)            break;    if (mov_idx == mov->total_streams) {        av_log(s, AV_LOG_ERROR, "mov: requested stream was not found in mov streams (idx=%i)\n", stream_index);        return -1;    }    sc = mov->streams[mov_idx];    // Step 1. Find the edit that contains the requested time (elst)    if (sc->edit_count) {        // FIXME should handle edit list        av_log(s, AV_LOG_ERROR, "mov: does not handle seeking in files that contain edit list (c:%d)\n", sc->edit_count);        return -1;    }    // Step 2. Find the corresponding sample using the Time-to-sample atom (stts) */#ifdef DEBUG  av_log(s, AV_LOG_DEBUG, "Searching for time %li in stream #%i (time_scale=%i)\n", (long)timestamp, mov_idx, sc->time_scale);#endif    // convert timestamp from time_base unit to timescale unit    sample_time = av_rescale( timestamp,                            (int64_t)sc->time_scale * s->streams[stream_index]->time_base.num,                            (int64_t)s->streams[stream_index]->time_base.den);    start_time = 0; // FIXME use elst atom    sample = 1; // sample are 0 based in table#ifdef DEBUG    av_log(s, AV_LOG_DEBUG, "Searching for sample_time %li \n", (long)sample_time);#endif    for (i = 0; i < sc->stts_count; i++) {        count = (uint32_t)(sc->stts_data[i]>>32);        duration = (uint32_t)(sc->stts_data[i]&0xffff);//av_log(s, AV_LOG_DEBUG, "> sample_time %lli \n", (long)sample_time);                //av_log(s, AV_LOG_DEBUG, "> count=%i duration=%i\n", count, duration);                if ((start_time + count*duration) > sample_time) {            sample += (sample_time - start_time) / duration;            break;        }        sample += count;        start_time += count * duration;    }       /* NOTE: despite what qt doc say, the dt value (Display Time in qt vocabulary) computed with the stts atom       is a decoding time stamp (dts

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -