/* * a simple video client * by Hoang Nguyen (hnguyen5@illinois.edu) * * Note: * No buffering/sync/rate control mechanism is used. * The client simply receives frames from the server, decodes and displays * TCP is used. * * Feel free to use/modify this code * at YOUR OWN RISK * * Protocol: * 1) Server reads the avi file, setup AVCodecContext * 2) Client connects, receives AVCodecContext, fixes interal pointers of AVCodecContext * 3) Client sends requested duration in frames, following by a READY signal * 4) Server receives requested duration and starts sending frames right after receiving READY signal from the client * 5) Server reads frames and sends to the client for every 40ms */ // mp3client // #include <ffmpeg/avcodec.h> #include <ffmpeg/avformat.h> #include <SDL.h> #include <SDL_thread.h> #ifdef __MINGW32__ #undef main /* Prevents SDL from overriding main() */ #endif #include <stdio.h> #include "msg.h" void fixCodecContext(AVCodecContext *s) { // setup default pointers for AVCodecContext AVCodecContext temp; avcodec_get_context_defaults(&temp); s->av_class= temp.av_class; s->get_buffer= avcodec_default_get_buffer; s->release_buffer= avcodec_default_release_buffer; s->get_format= avcodec_default_get_format; s->execute= avcodec_default_execute; s->palctrl = NULL; s->reget_buffer= avcodec_default_reget_buffer; } int main(int argc, char *argv[]) { int i, videoStream; AVCodecContext codecCtx; AVCodecContext *pCodecCtx = &codecCtx; AVCodec *pCodec; AVFrame *pFrame; AVPacket packet; int frameFinished; float aspect_ratio; SDL_Overlay *bmp; SDL_Surface *screen; SDL_Rect rect; SDL_Event event; if(argc < 4) { fprintf(stderr, "Usage: mp3client server port duration(in frames) \n"); exit(1); } int duration = atoi(argv[3]); int sockfd = connectToServer(argv[1], argv[2]); if (sockfd < 0) { printf("Cannot connect to %s:%s\n", argv[1], argv[2]); return 1; } printf("Waiting for AVCodecContext..."); int len = recv(sockfd, pCodecCtx, sizeof(AVCodecContext), MSG_WAITALL); printf("len = %d finished\n", len); fixCodecContext(pCodecCtx); printf("Request for %d frames from the server\n", duration); send(sockfd, (char *) &duration, sizeof(duration), 0); // Register all formats and codecs av_register_all(); if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) { fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError()); exit(1); } // Find the decoder for the video stream pCodec=avcodec_find_decoder(pCodecCtx->codec_id); if(pCodec==NULL) { fprintf(stderr, "Unsupported codec!\n"); return -1; // Codec not found } // Open codec if(avcodec_open(pCodecCtx, pCodec)<0) { printf("Cannot find codec\n"); return -1; // Could not open codec } // Allocate video frame pFrame=avcodec_alloc_frame(); // Make a screen to put our video #ifndef __DARWIN__ screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 0, 0); #else screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 24, 0); #endif if(!screen) { fprintf(stderr, "SDL: could not set video mode - exiting\n"); exit(1); } // Allocate a place to put our YUV image on that screen bmp = SDL_CreateYUVOverlay(pCodecCtx->width, pCodecCtx->height, SDL_YV12_OVERLAY, screen); // Read frames and save first five frames to disk i=0; double pts; int64_t last_time = 0; double last_pts = 0, delay; double actual_delay; // in ms int step = 1; int s = 0; //if (step < 0) //s = pFormatCtx->streams[videoStream]->duration-1; char buf[32000]; int ready = 1; printf("Start receiving packets\n"); send(sockfd, (char *) &ready, sizeof(ready), 0); long count = 1; while (count <= duration) { // Is this a packet from the video stream? // Decode video frame // while ((len = recv(sockfd, buf, sizeof(buf), 0)) <= 0); printf("Received a packet %ld of len %d\n", count++, len); avcodec_decode_video(pCodecCtx, pFrame, &frameFinished, buf, len); printf("Decoded\n"); if(frameFinished) { SDL_LockYUVOverlay(bmp); AVPicture pict; pict.data[0] = bmp->pixels[0]; pict.data[1] = bmp->pixels[2]; pict.data[2] = bmp->pixels[1]; pict.linesize[0] = bmp->pitches[0]; pict.linesize[1] = bmp->pitches[2]; pict.linesize[2] = bmp->pitches[1]; // Convert the image into YUV format that SDL uses img_convert(&pict, PIX_FMT_YUV420P, (AVPicture *)pFrame, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height); SDL_UnlockYUVOverlay(bmp); rect.x = 0; rect.y = 0; rect.w = pCodecCtx->width; rect.h = pCodecCtx->height; SDL_DisplayYUVOverlay(bmp, &rect); } } // Free the YUV frame av_free(pFrame); // Close the codec avcodec_close(pCodecCtx); return 0; }