# FFMPEG and SDL

This topic is 2356 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

This problem is just impossible so I'll get right to it. I've gotten a video to play in SDL using FFMPEG.

If I remove this one line of code:

 printf("Creating test.\n"); 

It won't work. I've got everything working except with the slight problem that the program crashes when it gets to the end if I don't remove this line.

I don't get it printf is a simple print to console command, how the hell is it doing anything?

Alright before my head explodes here's my code:

 //SDL_Movie.h #include "SDL.h" #include "libavcodec/avcodec.h" #include "libavutil/avutil.h" #include "libavformat/avformat.h" #include "libswscale/swscale.h" int SDL_MOVIE_ERROR = 0; typedef struct SDL_Movie { int videoStream, audioStream; AVFormatContext* pFormatCtx; AVCodecContext* pCodecCtx; AVCodecContext* aCodecCtx; AVCodec* pCodec; AVCodec* aCodec; AVFrame* pFrame; AVFrame* pFrameRGB; } SDL_Movie; char *SDL_Movie_GetError() { char* error; switch (SDL_MOVIE_ERROR) { case 0: error = "Unknown/No error."; break; case 1: error = "Error opening file."; break; case 2: error = "Couldn't find stream information."; break; case 3: error = "Couldn't find video stream."; break; case 4: error = "Couldn't find audio stream"; break; case 5: error = "Unsupported video codec."; break; case 6: error = "Unsupported audio codec."; break; case 7: error = "Video codec could not be opened."; break; case 8: error = "Couldn't allocate frame."; break; default: error = "Unknown/No error."; break; } SDL_MOVIE_ERROR = 0; return error; } SDL_Movie *SDL_LoadMovie(const char *file) { SDL_Movie *mov; printf("Entered.\n"); int ret; mov->pFormatCtx = NULL; if ((ret = avformat_open_input(&mov->pFormatCtx, file, NULL, NULL)) < 0) { printf("Failure.\n"); SDL_MOVIE_ERROR = 1; return NULL; } printf("Opened.\n"); if (avformat_find_stream_info(mov->pFormatCtx, NULL) < 0) { SDL_MOVIE_ERROR = 2; return NULL; } int i; mov->videoStream = -1; mov->audioStream = -1; for (i=0; i < mov->pFormatCtx->nb_streams; i++) { if (mov->pFormatCtx->streams->codec->codec_type == AVMEDIA_TYPE_VIDEO && mov->videoStream < 0) mov->videoStream=i; if (mov->pFormatCtx->streams->codec->codec_type == AVMEDIA_TYPE_AUDIO && mov->audioStream < 0) mov->audioStream = i; } if (mov->videoStream == -1) { SDL_MOVIE_ERROR = 3; return NULL; } if (mov->audioStream == -1) { SDL_MOVIE_ERROR = 4; return NULL; } mov->pCodecCtx = mov->pFormatCtx->streams[mov->videoStream]->codec; mov->aCodecCtx = mov->pFormatCtx->streams[mov->audioStream]->codec; if (!(mov->pCodec = avcodec_find_decoder(mov->pCodecCtx->codec_id))) { SDL_MOVIE_ERROR = 5; return NULL; } if (!(mov->aCodec = avcodec_find_decoder(mov->aCodecCtx->codec_id))) { SDL_MOVIE_ERROR = 6; return NULL; } if (avcodec_open(mov->pCodecCtx, mov->pCodec) < 0) { SDL_MOVIE_ERROR = 7; return NULL; } avcodec_open(mov->aCodecCtx, mov->aCodec); mov->pFrame = avcodec_alloc_frame(); mov->pFrameRGB = avcodec_alloc_frame(); if (!mov->pFrameRGB) { SDL_MOVIE_ERROR = 8; return NULL; } uint8_t* buffer; int numBytes = avpicture_get_size(PIX_FMT_RGB24, mov->pCodecCtx->width, mov->pCodecCtx->height); buffer = (uint8_t *)av_malloc(numBytes*sizeof(uint8_t)); avpicture_fill((AVPicture *)mov->pFrameRGB, buffer, PIX_FMT_RGB24, mov->pCodecCtx->width, mov->pCodecCtx->height); int frameFinished; AVPacket packet; av_free(buffer); return mov; } 

 //main.c #include <SDL.h> #include "SDL_Movie.h" #include <SDL_mixer.h> #include <SDL_thread.h> #include <libavcodec/avcodec.h> #include <libavutil/avutil.h> #include <libavformat/avformat.h> #include <libswscale/swscale.h> SDL_Surface* screen = NULL; int quit = 0; SDL_Event event; /* void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame) { FILE *pFile; char szFilename[32]; int y; // Open file sprintf(szFilename, "frame%d.ppm", iFrame); pFile=fopen(szFilename, "wb"); if(pFile==NULL) return; // Write header fprintf(pFile, "P6\n%d %d\n255\n", width, height); // Write pixel data for(y=0; y<height; y++) fwrite(pFrame->data[0]+y*pFrame->linesize[0], 1, width*3, pFile); // Close file fclose(pFile); } */ int main(int argc, char* argv[]) { if (SDL_Init(SDL_INIT_EVERYTHING) < 0) return 1; atexit(SDL_Quit); av_register_all(); printf("Creating test.\n"); SDL_Movie* test = SDL_LoadMovie("nuke.mp4"); printf("Created test.\n"); if (!test) printf("%s", SDL_Movie_GetError()); if (!(screen = SDL_SetVideoMode(/*pCodecCtx->width, pCodecCtx->height,*/ 1680, 1050, 24, SDL_HWSURFACE | SDL_ANYFORMAT))) return 1; SDL_Overlay* bmp = SDL_CreateYUVOverlay(test->pCodecCtx->width, test->pCodecCtx->height, SDL_YV12_OVERLAY, screen); int frameFinished; AVPacket packet; int i = 0; while (av_read_frame(test->pFormatCtx, &packet) >= 0) { if (packet.stream_index == test->videoStream) { avcodec_decode_video2(test->pCodecCtx, test->pFrame, &frameFinished, &packet); SDL_Rect rect; if (frameFinished) { SDL_LockYUVOverlay(bmp); /*struct SwsContext* swsContext = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL); sws_scale(swsContext, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize); if (++i <= 70) SaveFrame(pFrameRGB, pCodecCtx->width, pCodecCtx->height, i); */ 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]; struct SwsContext* swsContext = sws_getContext(test->pCodecCtx->width, test->pCodecCtx->height, test->pCodecCtx->pix_fmt, test->pCodecCtx->width, test->pCodecCtx->height, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL); sws_scale(swsContext, test->pFrame->data, test->pFrame->linesize, 0, test->pCodecCtx->height, pict.data, pict.linesize); SDL_UnlockYUVOverlay(bmp); rect.x = 0; rect.y = 0; //rect.w = pCodecCtx->width; //rect.h = pCodecCtx->height; rect.w = 1680; rect.h = 1050; SDL_DisplayYUVOverlay(bmp, &rect); } } } //av_free(buffer); av_free(test->pFrameRGB); av_free(test->pFrame); avcodec_close(test->pCodecCtx); av_close_input_file(test->pFormatCtx); return 0; } 

The main function is where I use the printf function that fixes almost everything.

If I don't have it, the program returns 3 when I call avformat_open_input in the SDL_LoadMovie function.

I just don't get it. Can anyone make sense of this?

##### Share on other sites
have you checked if that library redefined printf? (adding some obscure side effect) it is really strange. Maybe some broken binary? :?

##### Share on other sites

have you checked if that library redefined printf? (adding some obscure side effect) it is really strange. Maybe some broken binary? :?

It would make no sense for something to redefine printf. I had a hard time with some version conflicts between tutorials when I was compiling FFMPEG so I just went with a precompiled binary. The only possible way I could see this making sense is that I compiled SDL with --disable-stdio-redirect to get it to stop creating the files "stderr.txt" and "stdout.txt." Even then it' a long shot because again, why would it make any sort of sense to redefine printf? It's just so weird. Here's something else that's weird, if I move t

### he AVFormat* pFormatCtx at all within the struct I created, it will stop at the same point and return 3. I'll mess with it some more, but this basically killed my brain.

##### Share on other sites
Something like this hints to me that you're invoking undefined behavior somewhere. Try:

• Doing a clean rebuild of the project (no need to rebuild FFmpeg though)
• Stepping through with a debugger, starting at the beginning of main and stepping through the program until it crashes

As far as I can tell, a return code of 3 indicates [font=courier new,courier,monospace]ESRCH 3 /* No such process */ [font=arial,helvetica,sans-serif](assuming that's being returned from FFmpeg), which I have no clue about. Your best bet will be to step through it with a debugger though, line by line (after doing a clean rebuild). Post back here with your results.[/font][/font]

##### Share on other sites

Something like this hints to me that you're invoking undefined behavior somewhere. Try:

• Doing a clean rebuild of the project (no need to rebuild FFmpeg though)
• Stepping through with a debugger, starting at the beginning of main and stepping through the program until it crashes

As far as I can tell, a return code of 3 indicates [font=courier new,courier,monospace]ESRCH 3 /* No such process */ [font=arial,helvetica,sans-serif](assuming that's being returned from FFmpeg), which I have no clue about. Your best bet will be to step through it with a debugger though, line by line (after doing a clean rebuild). Post back here with your results.[/font][/font]

I assume by clean rebuild you mean right clicking on the project and clicking rebuild? I did that and ran the debugger and I got a SIGSEGV segmentation fault. I also caught where it was crashing. It crashed setting the pFormatCtx to NULL I removed that, and I got the same exact problem although with less information and I haven't found where it's crashing yet.

I remember reading about segmentation faults in earlier versions of FFMPEG if the AVFormatContext* is not set to NULL, but that was apparently fixed in the newer versions. What I was doing before I created the struct was simply create and initialize it as NULL in the same line. If I didn't it initialize it as NULL then, the program would crash. Unfortunately you can't set it to NULL in the same line in a struct, at least that I am aware of.

##### Share on other sites
[font=courier new,courier,monospace]SDL_Movie *mov;[/font] creates a pointer, but it doesn't allocate memory for that pointer. Hence, when you do[font=courier new,courier,monospace] mov->pFormatCtx = NULL;[/font] you get a SIGSEV (which means you're doing things with memory that you don't own), because [font=courier new,courier,monospace]mov [/font]doesn't point to any valid memory. You have to allocate memory for mov first ([font=courier new,courier,monospace]SDL_Movie *mov = new SDL_Movie;[/font]).

And yes, that's what I meant by doing a clean rebuild. Edited by Cornstalks

##### Share on other sites

[font=courier new,courier,monospace]SDL_Movie *mov;[/font] creates a pointer, but it doesn't allocate memory for that pointer. Hence, when you do[font=courier new,courier,monospace] mov->pFormatCtx = NULL;[/font] you get a SIGSEV (which means you're doing things with memory that you don't own), because [font=courier new,courier,monospace]mov [/font]doesn't point to any valid memory. You have to allocate memory for mov first ([font=courier new,courier,monospace]SDL_Movie *mov = new SDL_Movie;[/font]).

And yes, that's what I meant by doing a clean rebuild.

I'm not too worried about a memory leak, but do I have to "delete mov"?

edit:

Actually I'm just using C right now, not C++ (for compatibility reasons, I'll leave it at that), but I assume I could use malloc? I've never really used it or know how to, but I'll look into it. Edited by Spirrwell

##### Share on other sites
Yup I got it to work using malloc, but I have a couple of questions, how much memory should I allocate and how do I free memory allocated to mov?

##### Share on other sites
Sorry, I made the poor assumption that you were using C++ (since that's what I use every day, my brain defaulted to that). It would be:

 SDL_Movie *mov = (SDL_Movie*)malloc(sizeof(SDL_Movie)); 

[font=courier new,courier,monospace]sizeof(SDL_Movie)[/font] returns the size (in bytes) of an [font=courier new,courier,monospace]SDL_Movie[/font], and [font=courier new,courier,monospace]malloc()[/font] then uses that to allocate that many bytes, which is the perfect size for storing one [font=courier new,courier,monospace]SDL_Movie[/font] structure. Don't forget to [font=courier new,courier,monospace]free()[/font] the memory ([font=courier new,courier,monospace]free(mov)[/font]) when you're done and want to deallocate the memory (probably at the end of your program, just before [font=courier new,courier,monospace]main()[/font] exits). If you don't [font=courier new,courier,monospace]free()[/font] what you [font=courier new,courier,monospace]malloc()[/font], you'll leak memory (but if you [font=courier new,courier,monospace]free()[/font] too early and try to use the memory you just deallocated, you'll invoke undefined behavior and probably get a SIGSEV).

Alternatively, you could just get rid of the pointer all together. That is, make [font=courier new,courier,monospace]mov[/font] an actual structure and not a pointer ([font=courier new,courier,monospace]SDL_Movie mov;[/font]), so that you don't have to [font=courier new,courier,monospace]malloc()[/font] or [font=courier new,courier,monospace]free()[/font] anything. You would have to change the code to do [font=courier new,courier,monospace]mov.[/font] instead of [font=courier new,courier,monospace]mov->[/font] and make [font=courier new,courier,monospace]SDL_LoadMovie[/font] return a plain [font=courier new,courier,monospace]SDL_Movie[/font] instead of a pointer. Edited by Cornstalks

##### Share on other sites

Sorry, I made the poor assumption that you were using C++ (since that's what I use every day, my brain defaulted to that). It would be:

 SDL_Movie *mov = (SDL_Movie*)malloc(sizeof(SDL_Movie)); 

[font=courier new,courier,monospace]sizeof(SDL_Movie)[/font] returns the size (in bytes) of an [font=courier new,courier,monospace]SDL_Movie[/font], and [font=courier new,courier,monospace]malloc()[/font] then uses that to allocate that many bytes, which is the perfect size for storing one [font=courier new,courier,monospace]SDL_Movie[/font] structure. Don't forget to [font=courier new,courier,monospace]free()[/font] the memory ([font=courier new,courier,monospace]free(mov)[/font]) when you're done and want to deallocate the memory (probably at the end of your program, just before [font=courier new,courier,monospace]main()[/font] exits). If you don't [font=courier new,courier,monospace]free()[/font] what you [font=courier new,courier,monospace]malloc()[/font], you'll leak memory (but if you [font=courier new,courier,monospace]free()[/font] too early and try to use the memory you just deallocated, you'll invoke undefined behavior and probably get a SIGSEV).

Alternatively, you could just get rid of the pointer all together. That is, make [font=courier new,courier,monospace]mov[/font] an actual structure and not a pointer ([font=courier new,courier,monospace]SDL_Movie mov;[/font]), so that you don't have to [font=courier new,courier,monospace]malloc()[/font] or [font=courier new,courier,monospace]free()[/font] anything. You would have to change the code to do [font=courier new,courier,monospace]mov.[/font] instead of [font=courier new,courier,monospace]mov->[/font] and make [font=courier new,courier,monospace]SDL_LoadMovie[/font] return a plain [font=courier new,courier,monospace]SDL_Movie[/font] instead of a pointer.

Ah thank you so much! Everything is running fine now. I actually tried making it into structure instead of a pointer to see if that would fix the problem, but it never did, I might've done something wrong, but that doesn't matter now. The original reason I was doing it this way was to make it feel like an SDL struct pointer like SDL_Surface. There was a tutorial posted about using SDL with SMPEG on here, but the links are dead and it used the SDL_movie concept. So I'm making my own little SDL_movie.h for people to eventually use after I test it in a project.

Anyway, onto another problem (there always seems to be one when you program).

I'm not a fan of the SDL_Overlay and if I could use an SDL_Surface I could solve this problem I'm having when switching to fullscreen. If set the video mode with the SDL_ANYFORMAT flag, no video appears in fullscreen. If I use fullscreen, the end frame freezes for a second, and then moves on. Does anyone know how to convert an AVFrame to an SDL_Surface? For the YUV Overlay I would just do this:

 SDL_Rect rect; 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]; struct SwsContext* swsContext = sws_getContext(test->pCodecCtx->width, test->pCodecCtx->height, test->pCodecCtx->pix_fmt, test->pCodecCtx->width, test->pCodecCtx->height, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL); sws_scale(swsContext, test->pFrame->data, test->pFrame->linesize, 0, test->pCodecCtx->height, pict.data, pict.linesize); SDL_UnlockYUVOverlay(bmp); rect.x = 0; rect.y = 0; rect.w = 1680; rect.h = 1050; SDL_DisplayYUVOverlay(bmp, &rect); SDL_FillRect(screen, &rect, SDL_MapRGB(screen->format, 0, 0, 0)); } 

1. 1
Rutin
37
2. 2
3. 3
4. 4
5. 5

• 11
• 10
• 13
• 104
• 11
• ### Forum Statistics

• Total Topics
632978
• Total Posts
3009681
• ### Who's Online (See full list)

There are no registered users currently online

×