static int resizePlayer(ffmpegPlayer *me) { /* resizePlayer may be called before any size allocation */ int widget_w = AGWIDGET(me)->w > 0 ? AGWIDGET(me)->w : me->w; int widget_h = AGWIDGET(me)->h > 0 ? AGWIDGET(me)->h : me->h; if (me->flags & AG_FFMPEGPLAYER_KEEPRATIO) { int film_w, film_h; float aspect; SDL_ffmpegGetVideoSize(me->file, &film_w, &film_h); aspect = (float)film_h / film_w; if (widget_w * aspect > widget_h) { me->disp_w = SCALE_FLOOR((int)(widget_h / aspect)); me->disp_h = SCALE_FLOOR(widget_h); } else { me->disp_w = SCALE_FLOOR(widget_w); me->disp_h = SCALE_FLOOR((int)(widget_w * aspect)); } } else { me->disp_w = SCALE_FLOOR(widget_w); me->disp_h = SCALE_FLOOR(widget_h); } #ifndef USE_OVERLAY for (int i = 0; i < FFMPEGPLAYER_BUFSIZE; i++) { SDL_ffmpegVideoFrame *frame = me->videoFrame[i]; if (frame->surface != NULL) SDL_FreeSurface(frame->surface); frame->surface = SDL_CreateRGBSurface(SDL_HWSURFACE, me->disp_w, me->disp_h, 24, htonl(0xFF000000), htonl(0x00FF0000), htonl(0x0000FF00), 0x0); if (frame->surface == NULL) /* FIXME */ return -1; SDL_ffmpegGetVideoFrame(me->file, frame); } me->curVideoFrame = 0; #endif return 0; }
int main(int argc, char** argv) { SDL_ffmpegFile* film; int s; SDL_ffmpegStream *str; SDL_AudioSpec *specs; int w,h; int done = 0; SDL_Surface *screen; /* check if we got an argument */ if(argc < 2) { printf("usage: \"%s\" \"filename\"\n", argv[0]); return -1; } /* standard SDL initialization stuff */ if(SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO|SDL_DOUBLEBUF) < 0) { fprintf(stderr, "problem initializing SDL: %s\n", SDL_GetError()); return -1; } /* open file from arg[1] */ film = SDL_ffmpegOpen(argv[1]); if(!film) { printf("error opening file\n"); return -1; } /* print some info on detected stream to output */ for(s = 0; s<film->AStreams; s++) { str = SDL_ffmpegGetAudioStream(film, s); printf("Info on audiostream #%i:\n", s); printf("\tChannels: %i\n", str->channels); if(strlen(str->language)) printf("\tLanguage: %s\n", str->language); printf("\tSampleRate: %i\n", str->sampleRate); } for(s = 0; s<film->VStreams; s++) { str = SDL_ffmpegGetVideoStream(film, s); printf("Info on videostream #%i:\n", s); if(strlen(str->language)) printf("\tLanguage: %s\n", str->language); printf("\tFrame: %ix%i\n", str->width, str->height); printf("\tFrameRate: %.2ffps\n", 1.0 / (str->frameRate[0] / str->frameRate[1])); } /* select the streams you want to decode (example just uses 0 as a default) */ SDL_ffmpegSelectVideoStream(film, 0); SDL_ffmpegSelectAudioStream(film, 0); /* get the audiospec which fits the selected videostream, if no videostream */ /* is selected, default values are used (2 channel, 48Khz) */ specs = SDL_ffmpegGetAudioSpec(film, 512, audioCallback); /* we get the size from our active video stream, if no active video stream */ /* exists, width and height are set to default values (320x240) */ SDL_ffmpegGetVideoSize(film, &w, &h); /* Open the Video device */ screen = SDL_SetVideoMode(w, h, 32, SDL_DOUBLEBUF|SDL_HWSURFACE); if(!screen) { printf("Couldn't open video: %s\n", SDL_GetError()); return -1; } /* Open the Audio device */ if( SDL_OpenAudio(specs, 0) < 0 ) { printf("Couldn't open audio: %s\n", SDL_GetError()); return -1; } /* we start our decode thread, this always tries to buffer in some frames */ /* so we can enjoy smooth playback */ SDL_ffmpegStartDecoding(film); /* we unpause the audio so our audiobuffer gets read */ SDL_PauseAudio(0); while( !done ) { SDL_ffmpegVideoFrame* frame; /* just some standard SDL event stuff */ SDL_Event event; while(SDL_PollEvent(&event)) { if(event.type == SDL_QUIT) { done = 1; break; } if(event.type == SDL_MOUSEBUTTONDOWN) { int x,y; int64_t time; SDL_PumpEvents(); SDL_GetMouseState(&x, &y); /* by clicking you turn on the stream, seeking to the percentage */ /* in time, based on the x-position you clicked on */ time = ((double)x / w) * SDL_ffmpegGetDuration(film); /* we seek to time (milliseconds) */ SDL_ffmpegSeek(film, time); /* by passing 0(false) as our second argument, we play the file */ /* passing a non-zero value would mean we pause our file */ SDL_ffmpegPause(film, 0); } } /* we retrieve the current image from the file */ /* we get 0 if no file could be retrieved */ /* important! please note this call should be paired with SDL_ffmpegReleaseVideo */ frame = SDL_ffmpegGetVideoFrame(film); if(frame) { /* we got a frame, so we better show this one */ SDL_BlitSurface(frame->buffer, 0, screen, 0); /* After releasing this frame, you can no longer use it. */ /* you should call this function every time you get a frame! */ SDL_ffmpegReleaseVideo(film, frame); /* we flip the double buffered screen so we might actually see something */ SDL_Flip(screen); } /* we wish not to kill our poor cpu, so we give it some timeoff */ SDL_Delay(5); } /* after all is said and done, we should call this */ SDL_ffmpegFree(film); /* the SDL_Quit function offcourse... */ SDL_Quit(); return 0; }
static void * drawVideoThread(void *data) { ffmpegPlayer *me = data; AG_ObjectLock(me); for (;;) { SDL_ffmpegVideoFrame *frame = me->videoFrame[me->curVideoFrame]; if (!frame->ready) { DEBUG("Video buffer underrun!"); SDL_ffmpegGetVideoFrame(me->file, frame); } uint64_t sync = getSync(me); uint64_t pts = frame->pts; if (pts >= sync) { AG_ObjectUnlock(me); /* condition variable waiting may be faster, test with 500mhz */ AG_Delay(pts - sync); AG_ObjectLock(me); if (me->file == NULL) { /* FIXME */ break; } if (pts > getSync(me)) continue; #ifdef USE_OVERLAY if (frame->overlay != NULL) { if (AG_WidgetVisible(me)) { int frame_x = (AGWIDGET(me)->w - me->disp_w) / 2; int frame_y = (AGWIDGET(me)->h - me->disp_h) / 2; SDL_Rect rect = { .x = AGWIDGET(me)->rView.x1 + frame_x, .y = AGWIDGET(me)->rView.y1 + frame_y, .w = me->disp_w, .h = me->disp_h }; SDL_DisplayYUVOverlay(frame->overlay, &rect); } } #else if (frame->surface != NULL) { #ifdef USE_SDL_SHADOWSURFACE if (me->surface != NULL) AG_SDL_ShadowSurfaceFree(me->surface); me->surface = AG_SDL_ShadowSurface(frame->surface); #else if (me->surface != NULL) AG_SurfaceFree(me->surface); me->surface = AG_SurfaceFromSDL(frame->surface); #endif if (me->surface == NULL) { /* FIXME */ break; } AG_Redraw(AGWIDGET(me)); } #endif } else { /* frame is skipped */ DEBUG("skip frame: %lums late", sync - frame->pts); } frame->ready = 0; RR_INC(me->curVideoFrame, FFMPEGPLAYER_BUFSIZE); /* wake up buffer-fill thread */ AG_CondSignal(&me->video_cond); }