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

📄 ffplay.c

📁 F:图像处理资料264264书籍ffmpeg-0.4.9-pre1VideoStream.rar 一个视频解压缩源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
                           s->xleft + x, ys, 1, y,                            fgcolor);            i += channels;            if (i >= SAMPLE_ARRAY_SIZE)                i -= SAMPLE_ARRAY_SIZE;        }    }    fgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0xff);    for(ch = 1;ch < nb_display_channels; ch++) {        y = s->ytop + ch * h;        fill_rectangle(screen,                        s->xleft, y, s->width, 1,                        fgcolor);    }    SDL_UpdateRect(screen, s->xleft, s->ytop, s->width, s->height);}/* display the current picture, if any */static void video_display(VideoState *is){    if (is->audio_st && is->show_audio)         video_audio_display(is);    else if (is->video_st)        video_image_display(is);}static Uint32 sdl_refresh_timer_cb(Uint32 interval, void *opaque){    SDL_Event event;    event.type = FF_REFRESH_EVENT;    event.user.data1 = opaque;    SDL_PushEvent(&event);    return 0; /* 0 means stop timer */}/* schedule a video refresh in 'delay' ms */static void schedule_refresh(VideoState *is, int delay){    SDL_AddTimer(delay, sdl_refresh_timer_cb, is);}/* get the current audio clock value */static double get_audio_clock(VideoState *is){    double pts;    int hw_buf_size, bytes_per_sec;    pts = is->audio_clock;    hw_buf_size = audio_write_get_buf_size(is);    bytes_per_sec = 0;    if (is->audio_st) {        bytes_per_sec = is->audio_st->codec.sample_rate *             2 * is->audio_st->codec.channels;    }    if (bytes_per_sec)        pts -= (double)hw_buf_size / bytes_per_sec;    return pts;}/* get the current video clock value */static double get_video_clock(VideoState *is){    double delta;    if (is->paused) {        delta = 0;    } else {        delta = (av_gettime() - is->video_current_pts_time) / 1000000.0;    }    return is->video_current_pts + delta;}/* get the current external clock value */static double get_external_clock(VideoState *is){    int64_t ti;    ti = av_gettime();    return is->external_clock + ((ti - is->external_clock_time) * 1e-6);}/* get the current master clock value */static double get_master_clock(VideoState *is){    double val;    if (is->av_sync_type == AV_SYNC_VIDEO_MASTER) {        if (is->video_st)            val = get_video_clock(is);        else            val = get_audio_clock(is);    } else if (is->av_sync_type == AV_SYNC_AUDIO_MASTER) {        if (is->audio_st)            val = get_audio_clock(is);        else            val = get_video_clock(is);    } else {        val = get_external_clock(is);    }    return val;}/* seek in the stream */static void stream_seek(VideoState *is, int64_t pos){    is->seek_pos = pos;    is->seek_req = 1;}/* pause or resume the video */static void stream_pause(VideoState *is){    is->paused = !is->paused;    if (is->paused) {        is->video_current_pts = get_video_clock(is);    }}/* called to display each frame */static void video_refresh_timer(void *opaque){    VideoState *is = opaque;    VideoPicture *vp;    double actual_delay, delay, sync_threshold, ref_clock, diff;    if (is->video_st) {        if (is->pictq_size == 0) {            /* if no picture, need to wait */            schedule_refresh(is, 1);        } else {            /* dequeue the picture */            vp = &is->pictq[is->pictq_rindex];            /* update current video pts */            is->video_current_pts = vp->pts;            is->video_current_pts_time = av_gettime();            /* compute nominal delay */            delay = vp->pts - is->frame_last_pts;            if (delay <= 0 || delay >= 1.0) {                /* if incorrect delay, use previous one */                delay = is->frame_last_delay;            }            is->frame_last_delay = delay;            is->frame_last_pts = vp->pts;            /* update delay to follow master synchronisation source */            if (((is->av_sync_type == AV_SYNC_AUDIO_MASTER && is->audio_st) ||                 is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {                /* if video is slave, we try to correct big delays by                   duplicating or deleting a frame */                ref_clock = get_master_clock(is);                diff = vp->pts - ref_clock;                                /* skip or repeat frame. We take into account the                   delay to compute the threshold. I still don't know                   if it is the best guess */                sync_threshold = AV_SYNC_THRESHOLD;                if (delay > sync_threshold)                    sync_threshold = delay;                if (fabs(diff) < AV_NOSYNC_THRESHOLD) {                    if (diff <= -sync_threshold)                        delay = 0;                    else if (diff >= sync_threshold)                        delay = 2 * delay;                }            }            is->frame_timer += delay;            /* compute the REAL delay (we need to do that to avoid               long term errors */            actual_delay = is->frame_timer - (av_gettime() / 1000000.0);            if (actual_delay < 0.010) {                /* XXX: should skip picture */                actual_delay = 0.010;            }            /* launch timer for next picture */            schedule_refresh(is, (int)(actual_delay * 1000 + 0.5));#if defined(DEBUG_SYNC)            printf("video: delay=%0.3f actual_delay=%0.3f pts=%0.3f A-V=%f\n",                    delay, actual_delay, vp->pts, -diff);#endif            /* display picture */            video_display(is);                        /* update queue size and signal for next picture */            if (++is->pictq_rindex == VIDEO_PICTURE_QUEUE_SIZE)                is->pictq_rindex = 0;                        SDL_LockMutex(is->pictq_mutex);            is->pictq_size--;            SDL_CondSignal(is->pictq_cond);            SDL_UnlockMutex(is->pictq_mutex);        }    } else if (is->audio_st) {        /* draw the next audio frame */        schedule_refresh(is, 40);        /* if only audio stream, then display the audio bars (better           than nothing, just to test the implementation */                /* display picture */        video_display(is);    } else {        schedule_refresh(is, 100);    }    if (show_status) {        static int64_t last_time;        int64_t cur_time;        int aqsize, vqsize;        double av_diff;                cur_time = av_gettime();        if (!last_time || (cur_time - last_time) >= 500 * 1000) {            aqsize = 0;            vqsize = 0;            if (is->audio_st)                aqsize = is->audioq.size;            if (is->video_st)                vqsize = is->videoq.size;            av_diff = 0;            if (is->audio_st && is->video_st)                av_diff = get_audio_clock(is) - get_video_clock(is);            printf("%7.2f A-V:%7.3f aq=%5dKB vq=%5dKB    \r",                    get_master_clock(is), av_diff, aqsize / 1024, vqsize / 1024);            fflush(stdout);            last_time = cur_time;        }    }}/* allocate a picture (needs to do that in main thread to avoid   potential locking problems */static void alloc_picture(void *opaque){    VideoState *is = opaque;    VideoPicture *vp;    vp = &is->pictq[is->pictq_windex];    if (vp->bmp)        SDL_FreeYUVOverlay(vp->bmp);#if 0    /* XXX: use generic function */    /* XXX: disable overlay if no hardware acceleration or if RGB format */    switch(is->video_st->codec.pix_fmt) {    case PIX_FMT_YUV420P:    case PIX_FMT_YUV422P:    case PIX_FMT_YUV444P:    case PIX_FMT_YUV422:    case PIX_FMT_YUV410P:    case PIX_FMT_YUV411P:        is_yuv = 1;        break;    default:        is_yuv = 0;        break;    }#endif    vp->bmp = SDL_CreateYUVOverlay(is->video_st->codec.width,                                   is->video_st->codec.height,                                   SDL_YV12_OVERLAY,                                    screen);    vp->width = is->video_st->codec.width;    vp->height = is->video_st->codec.height;    SDL_LockMutex(is->pictq_mutex);    vp->allocated = 1;    SDL_CondSignal(is->pictq_cond);    SDL_UnlockMutex(is->pictq_mutex);}static int queue_picture(VideoState *is, AVFrame *src_frame, double pts){    VideoPicture *vp;    int dst_pix_fmt;    AVPicture pict;        /* wait until we have space to put a new picture */    SDL_LockMutex(is->pictq_mutex);    while (is->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE &&           !is->videoq.abort_request) {        SDL_CondWait(is->pictq_cond, is->pictq_mutex);    }    SDL_UnlockMutex(is->pictq_mutex);        if (is->videoq.abort_request)        return -1;    vp = &is->pictq[is->pictq_windex];    /* alloc or resize hardware picture buffer */    if (!vp->bmp ||         vp->width != is->video_st->codec.width ||        vp->height != is->video_st->codec.height) {        SDL_Event event;        vp->allocated = 0;        /* the allocation must be done in the main thread to avoid           locking problems */        event.type = FF_ALLOC_EVENT;        event.user.data1 = is;        SDL_PushEvent(&event);                /* wait until the picture is allocated */        SDL_LockMutex(is->pictq_mutex);        while (!vp->allocated && !is->videoq.abort_request) {            SDL_CondWait(is->pictq_cond, is->pictq_mutex);        }        SDL_UnlockMutex(is->pictq_mutex);        if (is->videoq.abort_request)            return -1;    }    /* if the frame is not skipped, then display it */    if (vp->bmp) {        /* get a pointer on the bitmap */        SDL_LockYUVOverlay (vp->bmp);        dst_pix_fmt = PIX_FMT_YUV420P;        pict.data[0] = vp->bmp->pixels[0];        pict.data[1] = vp->bmp->pixels[2];        pict.data[2] = vp->bmp->pixels[1];        pict.linesize[0] = vp->bmp->pitches[0];        pict.linesize[1] = vp->bmp->pitches[2];        pict.linesize[2] = vp->bmp->pitches[1];        img_convert(&pict, dst_pix_fmt,                     (AVPicture *)src_frame, is->video_st->codec.pix_fmt,                     is->video_st->codec.width, is->video_st->codec.height);        /* update the bitmap content */        SDL_UnlockYUVOverlay(vp->bmp);        vp->pts = pts;        /* now we can update the picture count */        if (++is->pictq_windex == VIDEO_PICTURE_QUEUE_SIZE)            is->pictq_windex = 0;        SDL_LockMutex(is->pictq_mutex);        is->pictq_size++;        SDL_UnlockMutex(is->pictq_mutex);    }    return 0;}/* compute the exact PTS for the picture if it is omitted in the stream */static int output_picture2(VideoState *is, AVFrame *src_frame, double pts1){    double frame_delay, pts;        pts = pts1;    /* if B frames are present, and if the current picture is a I       or P frame, we use the last pts */    if (is->video_st->codec.has_b_frames &&         src_frame->pict_type != FF_B_TYPE) {        /* use last pts */        pts = is->video_last_P_pts;        /* get the pts for the next I or P frame if present */        is->video_last_P_pts = pts1;    }    if (pts != 0) {        /* update video clock with pts, if present */        is->video_clock = pts;    } else {        pts = is->video_clock;    }    /* update video clock for next frame */    frame_delay = (double)is->video_st->codec.frame_rate_base /         (double)is->video_st->codec.frame_rate;    /* for MPEG2, the frame can be repeated, so we update the       clock accordingly */    if (src_frame->repeat_pict) {        frame_delay += src_frame->repeat_pict * (frame_delay * 0.5);    }    is->video_clock += frame_delay;#if defined(DEBUG_SYNC) && 0    {        int ftype;        if (src_frame->pict_type == FF_B_TYPE)            ftype = 'B';        else if (src_frame->pict_type == FF_I_TYPE)            ftype = 'I';        else            ftype = 'P';        printf("frame_type=%c clock=%0.3f pts=%0.3f\n",                ftype, pts, pts1);    }#endif    return queue_picture(is, src_frame, pts);}static int video_thread(void *arg){    VideoState *is = arg;    AVPacket pkt1, *pkt = &pkt1;    int len1, got_picture;    AVFrame *frame= avcodec_alloc_frame();    double pts;    for(;;) {        while (is->paused && !is->videoq.abort_request) {            SDL_Delay(10);        }        if (packet_queue_get(&is->videoq, pkt, 1) < 0)            break;        /* NOTE: ipts is the PTS of the _first_ picture beginning in           this packet, if any */        pts = 0;        if (pkt->pts != AV_NOPTS_VALUE)            pts = (double)pkt->pts / AV_TIME_BASE;        if (is->video_st->codec.codec_id == CODEC_ID_RAWVIDEO) {            avpicture_fill((AVPicture *)frame, pkt->data,                            is->video_st->codec.pix_fmt,                           is->video_st->codec.width,                           is->video_st->codec.height);            frame->pict_type = FF_I_TYPE;            if (output_picture2(is, frame, pts) < 0)                goto the_end;        } else {            len1 = avcodec_decode_video(&is->video_st->codec,                                         frame, &got_picture,                                         pkt->data, pkt->size);//            if (len1 < 0)//                break;            if (got_picture) {                if (output_picture2(is, frame, pts) < 0)                    goto the_end;            }        }        av_free_packet(pkt);        if (step)             if (cur_stream)                stream_pause(cur_stream);    } the_end:    av_free(frame);    return 0;}/* copy samples for viewing in editor window */static void update_sample_display(VideoState *is, short *samples, int samples_size){    int size, len, channels;    channels = is->audio_st->codec.channels;    size = samples_size / sizeof(short);    while (size > 0) {        len = SAMPLE_ARRAY_SIZE - is->sample_array_index;        if (len > size)            len = size;        memcpy(is->sample_array + is->sample_array_index, samples, len * sizeof(short));        samples += len;        is->sample_array_index += len;        if (is->sample_array_index >= SAMPLE_ARRAY_SIZE)            is->sample_array_index = 0;        size -= len;    }}/* return the new audio buffer size (samples can be added or deleted   to get better sync if video or external master clock) */static int synchronize_audio(VideoState *is, short *samples,                              int samples_size1, double pts){    int n, samples_size;    double ref_clock;        n = 2 * is->audio_st->codec.channels;    samples_size = samples_size1;    /* if not master, then we try to remove or add samples to correct the clock */    if (((is->av_sync_type == AV_SYNC_VIDEO_MASTER && is->video_st) ||         is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {        double diff, avg_diff;

⌨️ 快捷键说明

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