Skip to content

Instantly share code, notes, and snippets.

@skayred
Created November 3, 2013 13:41
Show Gist options
  • Save skayred/7290391 to your computer and use it in GitHub Desktop.
Save skayred/7290391 to your computer and use it in GitHub Desktop.
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
}
#include <SDL2/SDL.h>
#include <stdio.h>
#include <iostream>
SDL_Texture *texture;
SDL_mutex* PictureMutex;
SDL_cond* PictureReadyCond;
bool PictureReady;
uint8_t * ToYUV420(AVFrame* frame, AVCodecContext *codecContext) {
static int numPixels = avpicture_get_size (
PIX_FMT_YUV420P,
codecContext->width,
codecContext->height);
static uint8_t * buffer = (uint8_t *) malloc (numPixels);
//Set context for conversion
static struct SwsContext *swsContext = sws_getCachedContext (
swsContext,
codecContext->width,
codecContext->height,
codecContext->pix_fmt,
codecContext->width,
codecContext->height,
PIX_FMT_YUV420P,
SWS_BILINEAR,
NULL,
NULL,
NULL
);
AVFrame* frameYUV420P = avcodec_alloc_frame();
avpicture_fill(
(AVPicture *) frameYUV420P,
buffer,
PIX_FMT_YUV420P,
codecContext->width,
codecContext->height);
// Convert the image into YUV format that SDL uses
sws_scale(swsContext,
frame->data, frame->linesize,
0, codecContext->height,
frameYUV420P->data, frameYUV420P->linesize );
return buffer;
}
void PreparePicture(AVFrame *frame, AVCodecContext *codecContext) {
SDL_LockMutex(PictureMutex);
// while (PictureReady)
// SDL_CondWait(PictureReadyCond, PictureMutex);
SDL_UnlockMutex(PictureMutex);
int pitch = codecContext->width * SDL_BYTESPERPIXEL(SDL_PIXELFORMAT_IYUV);
uint8_t * buffer = ToYUV420(frame, codecContext);
SDL_UpdateTexture(texture, NULL, buffer, pitch);
SDL_LockMutex(PictureMutex);
PictureReady = true;
SDL_CondSignal(PictureReadyCond);
SDL_UnlockMutex(PictureMutex);
}
void sdl_init(AVFormatContext* format_context, AVCodecContext* codecContext, int videoStream ) {
SDL_Init(SDL_INIT_EVERYTHING);
AVFrame* frame;
AVFrame *pFrameRGB;
AVPacket avpacket;
AVPicture picture;
int w = 640;
int h = 480;
SDL_Window *screen = SDL_CreateWindow("SDL", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, w, h, 0);
SDL_Renderer *renderer = SDL_CreateRenderer(screen, -1, 0);
texture = SDL_CreateTexture(renderer,
SDL_PIXELFORMAT_IYUV, // YUV420P
SDL_TEXTUREACCESS_STREAMING,
codecContext->width,
codecContext->height);
PictureMutex = SDL_CreateMutex();
PictureReadyCond = SDL_CreateCond();
PictureReady = false;
frame = avcodec_alloc_frame();
pFrameRGB = avcodec_alloc_frame();
if (pFrameRGB == NULL) {
printf("Cannot allocate pFrame\n");
exit(-1);
}
unsigned char* pixels;
int pitch;
uint8_t *buffer;
int numBytes;
// Determine required buffer size and allocate buffer
numBytes=avpicture_get_size(PIX_FMT_RGB24, codecContext->width, codecContext->height);
buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));
// Assign appropriate parts of buffer to image planes in pFrameRGB
// Note that pFrameRGB is an AVFrame, but AVFrame is a superset
// of AVPicture
avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24, codecContext->width, codecContext->height);
while (av_read_frame(format_context, &avpacket) >= 0) {
if (avpacket.stream_index == videoStream) {
// Video stream packet
int frame_finished;
avcodec_decode_video2(codecContext, frame, &frame_finished, &avpacket);
if(frame_finished) {
std::cout << "--" << std::endl;
PreparePicture(frame, codecContext);
}//frame
av_free_packet(&avpacket);
}//avpacket
SDL_Delay(20);
}
SDL_Quit();
}
int main(int argc, char * argv[]) {
AVCodecContext* codec_context;
int videoStream;
if (argc < 2) {
printf("Usage: %s filename\n", argv[0]);
return 0;
}
// Register all available file formats and codecs
av_register_all();
int err;
// Init SDL with video support
err = SDL_Init(SDL_INIT_VIDEO);
if (err < 0) {
fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
return -1;
}
// Open video file
const char* filename = argv[1];
AVFormatContext* format_context = NULL;
err = avformat_open_input(&format_context, filename, NULL, NULL);
if (err < 0) {
fprintf(stderr, "ffmpeg: Unable to open input\n");
return -1;
}
// Retrieve stream information
err = avformat_find_stream_info(format_context, NULL);
if (err < 0) {
fprintf(stderr, "ffmpeg: Unable to find stream info\n");
return -1;
}
// Dump information about file onto standard error
av_dump_format(format_context, 0, argv[1], 0);
// Find the first video stream
for (videoStream = 0; videoStream < format_context->nb_streams; ++videoStream) {
if (format_context->streams[videoStream]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
break;
}
}
if (videoStream == format_context->nb_streams) {
fprintf(stderr, "ffmpeg: Unable to find video stream\n");
return -1;
}
codec_context = format_context->streams[videoStream]->codec;
AVCodec* codec = avcodec_find_decoder(codec_context->codec_id);
avcodec_alloc_context3(codec);
if (avcodec_open2(codec_context, codec, NULL) < 0) {
fprintf(stderr, "ffmpeg: Unable to allocate codec context\n");
} else {
printf("Codec initialized\n");
}
printf("Width:%d\n",codec_context->width);
printf("height:%d\n",codec_context->height);
sdl_init(format_context, codec_context,videoStream);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment