/* * a simple video server * by Hoang Nguyen (hnguyen5@illinois.edu) * * Note: * No buffering/sync/rate control mechanism is used. * The server simply reads frames and sends to the client * 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 */ #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" AVFormatContext *pFormatCtx; int i, videoStream; AVCodecContext *pCodecCtx; AVCodec *pCodec; AVFrame *pFrame; AVPacket packet; int frameFinished; float aspect_ratio; void serverfunc(int sockfd) { int duration; // in frames printf("Sending AVCodecContext structure..."); int len = send(sockfd, (char *) pCodecCtx, sizeof(AVCodecContext), 0); printf("%d finished\n", len); while (recv(sockfd, &duration, sizeof(duration), MSG_WAITALL) <= 0); printf("Client wants %d frames\n", duration); int ready; printf("Waiting for client to be ready...\n"); while (recv(sockfd, &ready, sizeof(ready), MSG_WAITALL) <= 0); printf("\tfinished\n"); printf("Start sending packets\n"); long count = 1; while(av_read_frame(pFormatCtx, &packet)>=0) { // Free the packet that was allocated by av_read_frame if(packet.stream_index==videoStream) { len = send(sockfd, (char *) packet.data, packet.size, 0); printf("Sent packet %ld, len = %d\n", count++, len); SDL_Delay(40); } av_free_packet(&packet); if (count > duration) break; } // Close the video file av_close_input_file(pFormatCtx); exit(0); } int main(int argc, char *argv[]) { if(argc < 3) { fprintf(stderr, "Usage: mp3server <port> <file>\n"); exit(1); } // Register all formats and codecs av_register_all(); // Open video file if(av_open_input_file(&pFormatCtx, argv[2], NULL, 0, NULL)!=0) return -1; // Couldn't open file // Retrieve stream information if(av_find_stream_info(pFormatCtx)<0) return -1; // Couldn't find stream information // Dump information about file onto standard error dump_format(pFormatCtx, 0, argv[1], 0); // Find the first video stream videoStream=-1; for(i=0; i<pFormatCtx->nb_streams; i++) if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO) { videoStream=i; break; } if(videoStream==-1) return -1; // Didn't find a video stream // Get a pointer to the codec context for the video stream pCodecCtx=pFormatCtx->streams[videoStream]->codec; startServer(argv[1], (void *)(serverfunc)); return 0; }