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

📄 ffplay.c

📁 F:图像处理资料264264书籍ffmpeg-0.4.9-pre1VideoStream.rar 一个视频解压缩源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
        int wanted_size, min_size, max_size, nb_samples;                    ref_clock = get_master_clock(is);        diff = get_audio_clock(is) - ref_clock;                if (diff < AV_NOSYNC_THRESHOLD) {            is->audio_diff_cum = diff + is->audio_diff_avg_coef * is->audio_diff_cum;            if (is->audio_diff_avg_count < AUDIO_DIFF_AVG_NB) {                /* not enough measures to have a correct estimate */                is->audio_diff_avg_count++;            } else {                /* estimate the A-V difference */                avg_diff = is->audio_diff_cum * (1.0 - is->audio_diff_avg_coef);                if (fabs(avg_diff) >= is->audio_diff_threshold) {                    wanted_size = samples_size + ((int)(diff * is->audio_st->codec.sample_rate) * n);                    nb_samples = samples_size / n;                                    min_size = ((nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;                    max_size = ((nb_samples * (100 + SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;                    if (wanted_size < min_size)                        wanted_size = min_size;                    else if (wanted_size > max_size)                        wanted_size = max_size;                                        /* add or remove samples to correction the synchro */                    if (wanted_size < samples_size) {                        /* remove samples */                        samples_size = wanted_size;                    } else if (wanted_size > samples_size) {                        uint8_t *samples_end, *q;                        int nb;                                                /* add samples */                        nb = (samples_size - wanted_size);                        samples_end = (uint8_t *)samples + samples_size - n;                        q = samples_end + n;                        while (nb > 0) {                            memcpy(q, samples_end, n);                            q += n;                            nb -= n;                        }                        samples_size = wanted_size;                    }                }#if 0                printf("diff=%f adiff=%f sample_diff=%d apts=%0.3f vpts=%0.3f %f\n",                        diff, avg_diff, samples_size - samples_size1,                        is->audio_clock, is->video_clock, is->audio_diff_threshold);#endif            }        } else {            /* too big difference : may be initial PTS errors, so               reset A-V filter */            is->audio_diff_avg_count = 0;            is->audio_diff_cum = 0;        }    }    return samples_size;}/* decode one audio frame and returns its uncompressed size */static int audio_decode_frame(VideoState *is, uint8_t *audio_buf, double *pts_ptr){    AVPacket *pkt = &is->audio_pkt;    int n, len1, data_size;    double pts;    for(;;) {        /* NOTE: the audio packet can contain several frames */        while (is->audio_pkt_size > 0) {            len1 = avcodec_decode_audio(&is->audio_st->codec,                                         (int16_t *)audio_buf, &data_size,                                         is->audio_pkt_data, is->audio_pkt_size);            if (len1 < 0) {                /* if error, we skip the frame */                is->audio_pkt_size = 0;                break;            }                        is->audio_pkt_data += len1;            is->audio_pkt_size -= len1;            if (data_size <= 0)                continue;            /* if no pts, then compute it */            pts = is->audio_clock;            *pts_ptr = pts;            n = 2 * is->audio_st->codec.channels;            is->audio_clock += (double)data_size /                 (double)(n * is->audio_st->codec.sample_rate);#if defined(DEBUG_SYNC)            {                static double last_clock;                printf("audio: delay=%0.3f clock=%0.3f pts=%0.3f\n",                       is->audio_clock - last_clock,                       is->audio_clock, pts);                last_clock = is->audio_clock;            }#endif            return data_size;        }        /* free the current packet */        if (pkt->data)            av_free_packet(pkt);                if (is->paused || is->audioq.abort_request) {            return -1;        }                /* read next packet */        if (packet_queue_get(&is->audioq, pkt, 1) < 0)            return -1;        is->audio_pkt_data = pkt->data;        is->audio_pkt_size = pkt->size;                /* if update the audio clock with the pts */        if (pkt->pts != AV_NOPTS_VALUE) {            is->audio_clock = (double)pkt->pts / AV_TIME_BASE;        }    }}/* get the current audio output buffer size, in samples. With SDL, we   cannot have a precise information */static int audio_write_get_buf_size(VideoState *is){    return is->audio_hw_buf_size - is->audio_buf_index;}/* prepare a new audio buffer */void sdl_audio_callback(void *opaque, Uint8 *stream, int len){    VideoState *is = opaque;    int audio_size, len1;    double pts;    audio_callback_time = av_gettime();        while (len > 0) {        if (is->audio_buf_index >= is->audio_buf_size) {           audio_size = audio_decode_frame(is, is->audio_buf, &pts);           if (audio_size < 0) {                /* if error, just output silence */               is->audio_buf_size = 1024;               memset(is->audio_buf, 0, is->audio_buf_size);           } else {               if (is->show_audio)                   update_sample_display(is, (int16_t *)is->audio_buf, audio_size);               audio_size = synchronize_audio(is, (int16_t *)is->audio_buf, audio_size,                                               pts);               is->audio_buf_size = audio_size;           }           is->audio_buf_index = 0;        }        len1 = is->audio_buf_size - is->audio_buf_index;        if (len1 > len)            len1 = len;        memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);        len -= len1;        stream += len1;        is->audio_buf_index += len1;    }}/* open a given stream. Return 0 if OK */static int stream_component_open(VideoState *is, int stream_index){    AVFormatContext *ic = is->ic;    AVCodecContext *enc;    AVCodec *codec;    SDL_AudioSpec wanted_spec, spec;    if (stream_index < 0 || stream_index >= ic->nb_streams)        return -1;    enc = &ic->streams[stream_index]->codec;        /* prepare audio output */    if (enc->codec_type == CODEC_TYPE_AUDIO) {        wanted_spec.freq = enc->sample_rate;        wanted_spec.format = AUDIO_S16SYS;        /* hack for AC3. XXX: suppress that */        if (enc->channels > 2)            enc->channels = 2;        wanted_spec.channels = enc->channels;        wanted_spec.silence = 0;        wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;        wanted_spec.callback = sdl_audio_callback;        wanted_spec.userdata = is;        if (SDL_OpenAudio(&wanted_spec, &spec) < 0) {            fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError());            return -1;        }        is->audio_hw_buf_size = spec.size;    }    codec = avcodec_find_decoder(enc->codec_id);    enc->debug_mv = debug_mv;    enc->debug = debug;    enc->workaround_bugs = workaround_bugs;    if (!codec ||        avcodec_open(enc, codec) < 0)        return -1;#if defined(HAVE_PTHREADS) || defined(HAVE_W32THREADS)    if(thread_count>1)        avcodec_thread_init(enc, thread_count);#endif    enc->thread_count= thread_count;    switch(enc->codec_type) {    case CODEC_TYPE_AUDIO:        is->audio_stream = stream_index;        is->audio_st = ic->streams[stream_index];        is->audio_buf_size = 0;        is->audio_buf_index = 0;        /* init averaging filter */        is->audio_diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB);        is->audio_diff_avg_count = 0;        /* since we do not have a precise anough audio fifo fullness,           we correct audio sync only if larger than this threshold */        is->audio_diff_threshold = 2.0 * SDL_AUDIO_BUFFER_SIZE / enc->sample_rate;        memset(&is->audio_pkt, 0, sizeof(is->audio_pkt));        packet_queue_init(&is->audioq);	SDL_PauseAudio(0);        break;    case CODEC_TYPE_VIDEO:        is->video_stream = stream_index;        is->video_st = ic->streams[stream_index];        is->frame_last_delay = 40e-3;        is->frame_timer = (double)av_gettime() / 1000000.0;        is->video_current_pts_time = av_gettime();        packet_queue_init(&is->videoq);        is->video_tid = SDL_CreateThread(video_thread, is);        break;    default:        break;    }    return 0;}static void stream_component_close(VideoState *is, int stream_index){    AVFormatContext *ic = is->ic;    AVCodecContext *enc;        enc = &ic->streams[stream_index]->codec;    switch(enc->codec_type) {    case CODEC_TYPE_AUDIO:        packet_queue_abort(&is->audioq);        SDL_CloseAudio();        packet_queue_end(&is->audioq);        break;    case CODEC_TYPE_VIDEO:        packet_queue_abort(&is->videoq);        /* note: we also signal this mutex to make sure we deblock the           video thread in all cases */        SDL_LockMutex(is->pictq_mutex);        SDL_CondSignal(is->pictq_cond);        SDL_UnlockMutex(is->pictq_mutex);        SDL_WaitThread(is->video_tid, NULL);        packet_queue_end(&is->videoq);        break;    default:        break;    }    avcodec_close(enc);    switch(enc->codec_type) {    case CODEC_TYPE_AUDIO:        is->audio_st = NULL;        is->audio_stream = -1;        break;    case CODEC_TYPE_VIDEO:        is->video_st = NULL;        is->video_stream = -1;        break;    default:        break;    }}void dump_stream_info(AVFormatContext *s){    if (s->track != 0)        fprintf(stderr, "Track: %d\n", s->track);    if (s->title[0] != '\0')        fprintf(stderr, "Title: %s\n", s->title);    if (s->author[0] != '\0')        fprintf(stderr, "Author: %s\n", s->author);    if (s->album[0] != '\0')        fprintf(stderr, "Album: %s\n", s->album);    if (s->year != 0)        fprintf(stderr, "Year: %d\n", s->year);    if (s->genre[0] != '\0')        fprintf(stderr, "Genre: %s\n", s->genre);}/* since we have only one decoding thread, we can use a global   variable instead of a thread local variable */static VideoState *global_video_state;static int decode_interrupt_cb(void){    return (global_video_state && global_video_state->abort_request);}/* this thread gets the stream from the disk or the network */static int decode_thread(void *arg){    VideoState *is = arg;    AVFormatContext *ic;    int err, i, ret, video_index, audio_index, use_play;    AVPacket pkt1, *pkt = &pkt1;    AVFormatParameters params, *ap = &params;    video_index = -1;    audio_index = -1;    is->video_stream = -1;    is->audio_stream = -1;    global_video_state = is;    url_set_interrupt_cb(decode_interrupt_cb);    memset(ap, 0, sizeof(*ap));    ap->image_format = image_format;    ap->initial_pause = 1; /* we force a pause when starting an RTSP                              stream */        err = av_open_input_file(&ic, is->filename, is->iformat, 0, ap);    if (err < 0) {        print_error(is->filename, err);        ret = -1;        goto fail;    }    is->ic = ic;#ifdef CONFIG_NETWORK    use_play = (ic->iformat == &rtsp_demux);#else    use_play = 0;#endif    if (!use_play) {        err = av_find_stream_info(ic);        if (err < 0) {            fprintf(stderr, "%s: could not find codec parameters\n", is->filename);            ret = -1;            goto fail;        }    }    /* if seeking requested, we execute it */    if (start_time != AV_NOPTS_VALUE) {        int64_t timestamp;        timestamp = start_time;        /* add the stream start time */        if (ic->start_time != AV_NOPTS_VALUE)            timestamp += ic->start_time;        ret = av_seek_frame(ic, -1, timestamp);        if (ret < 0) {            fprintf(stderr, "%s: could not seek to position %0.3f\n",                     is->filename, (double)timestamp / AV_TIME_BASE);        }    }    /* now we can begin to play (RTSP stream only) */    av_read_play(ic);    if (use_play) {        err = av_find_stream_info(ic);        if (err < 0) {            fprintf(stderr, "%s: could not find codec parameters\n", is->filename);            ret = -1;            goto fail;        }    }    for(i = 0; i < ic->nb_streams; i++) {        AVCodecContext *enc = &ic->streams[i]->codec;        switch(enc->codec_type) {        case CODEC_TYPE_AUDIO:            if (audio_index < 0 && !audio_disable)                audio_index = i;            break;        case CODEC_TYPE_VIDEO:            if (video_index < 0 && !video_disable)                video_index = i;            break;        default:            break;        }    }    if (show_status) {        dump_format(ic, 0, is->filename, 0);        dump_stream_info(ic);    }    /* open the streams */    if (audio_index >= 0) {        stream_component_open(is, audio_index);    }    if (video_index >= 0) {        stream_component_open(is, video_index);    } else {        if (!display_disable)            is->show_audio = 1;    }    if (is->video_stream < 0 && is->audio_stream < 0) {        fprintf(stderr, "%s: could not open codecs\n", is->filename);        ret = -1;        goto fail;    }    for(;;) {        if (is->abort_request)            break;#ifdef CONFIG_NETWORK        if (is->paused != is->last_paused) {            is->last_paused = is->paused;            if (is->paused)                av_read_pause(ic);            else                av_read_play(ic);        }        if (is->paused && ic->iformat == &rtsp_demux) {            /* wait 10 ms to avoid trying to get another packet */            /* XXX: horrible */            SDL_Delay(10);            continue;        }#endif        if (is->seek_req) {            /* XXX: must lock decoder threads */            ret = av_seek_frame(is->ic, -1, is->seek_pos);            if (ret < 0) {                fprintf(stderr, "%s: error while seeking\n", is->ic->filename);            }else{                if (is->audio_stream >= 0) {                    packet_queue_flush(&is->audioq);                }                if (is->video_stream >= 0) {                    packet_queue_flush(&is->videoq);                    avcodec_flush_buffers(&ic->streams[video_index]->codec);                }            }            is->seek_req = 0;        }        /* if the queue are full, no need to read more */        if (is->audioq.size > MAX_AUDIOQ_SIZE ||            is->videoq.size > MAX_VIDEOQ_SIZE ||             url_feof(&ic->pb)) {            /* wait 10 ms */            SDL_Delay(10);            continue;        }        ret = av_read_frame(ic, pkt);        if (ret < 0) {            break;        }        if (pkt->stream_index == is->audio_stream) {            packet_queue_put(&is->audioq, pkt);        } else if (pkt->stream_index == is->video_stream) {            packet_queue_put(&is->videoq, pkt);        } else {            av_free_packet(pkt);        }    }    /* wait until the end */    while (!is->abort_request) {        SDL_Delay(100);    }

⌨️ 快捷键说明

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