#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
void extract_frame(const char *filename, int frame_number, int *width, int *height, uint8_t **outputBuffer) {
AVFormatContext *pFormatCtx = NULL;
if (avformat_open_input(&pFormatCtx, filename, NULL, NULL) != 0) {
mexErrMsgTxt("Unable to open video file");
if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
avformat_close_input(&pFormatCtx);
mexErrMsgTxt("Unable to get stream information");
for (unsigned int i = 0; i < pFormatCtx->nb_streams; i++) {
if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
avformat_close_input(&pFormatCtx);
mexErrMsgTxt("No video stream found");
AVCodecParameters *pCodecPar = pFormatCtx->streams[videoStream]->codecpar;
const AVCodec *pCodec = avcodec_find_decoder(pCodecPar->codec_id);
avformat_close_input(&pFormatCtx);
mexErrMsgTxt("No decoder found");
AVCodecContext *pCodecCtx = avcodec_alloc_context3(pCodec);
avformat_close_input(&pFormatCtx);
mexErrMsgTxt("Unable to create decode context");
if (avcodec_parameters_to_context(pCodecCtx, pCodecPar) < 0) {
avcodec_free_context(&pCodecCtx);
avformat_close_input(&pFormatCtx);
mexErrMsgTxt("Unable to copy codec parameters");
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
avcodec_free_context(&pCodecCtx);
avformat_close_input(&pFormatCtx);
mexErrMsgTxt("Unable to open the decoder");
AVFrame *pFrame = av_frame_alloc();
AVFrame *pFrameRGB = av_frame_alloc();
struct SwsContext *sws_ctx = NULL;
while (av_read_frame(pFormatCtx, &packet) >= 0) {
if (packet.stream_index == videoStream) {
if (avcodec_send_packet(pCodecCtx, &packet) < 0) {
av_packet_unref(&packet);
while (avcodec_receive_frame(pCodecCtx, pFrame) >= 0) {
if (frame_count == frame_number) {
const enum AVPixelFormat dst_format = AV_PIX_FMT_RGB24;
sws_ctx = sws_getCachedContext(sws_ctx,
pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,
pCodecCtx->width, pCodecCtx->height, dst_format,
SWS_BILINEAR, NULL, NULL, NULL);
*width = pCodecCtx->width;
*height = pCodecCtx->height;
int buffer_size = av_image_get_buffer_size(dst_format, *width, *height, 1);
*outputBuffer = (uint8_t*)av_malloc(buffer_size);
av_image_fill_arrays(pFrameRGB->data, pFrameRGB->linesize,
*outputBuffer, dst_format, *width, *height, 1);
sws_scale(sws_ctx, (const uint8_t* const*)pFrame->data,
pFrame->linesize, 0, pFrame->height,
pFrameRGB->data, pFrameRGB->linesize);
av_packet_unref(&packet);
av_packet_unref(&packet);
av_frame_free(&pFrameRGB);
sws_freeContext(sws_ctx);
avcodec_free_context(&pCodecCtx);
avformat_close_input(&pFormatCtx);
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
mexErrMsgTxt("frame = extract_frame_mex(filename, frame_number)");
mxGetString(prhs[0], filename, sizeof(filename));
int frame_number = (int)mxGetScalar(prhs[1]);
uint8_t *frame_data = NULL;
extract_frame(filename, frame_number, &width, &height, &frame_data);
mexErrMsgTxt("Description Failed to extract the video frame");
const mwSize dims[3] = {width,height,3};
plhs[0] = mxCreateNumericArray(3, dims, mxUINT8_CLASS, mxREAL);
// memcpy(mxGetData(plhs[0]), frame_data, width * height * 3);
uint8_t *matlab_data = (uint8_t*)mxGetData(plhs[0]);
// printf("%d %d %d %d %d\n",frame_data[0],frame_data[1],frame_data[2],frame_data[3],frame_data[4]);
const int plane_size = width * height;
#pragma omp parallel for collapse(2)
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width;++x) {
const size_t idx = y + x * height;
matlab_data[idx] = frame_data[idx*3]; // r
matlab_data[idx + plane_size] = frame_data[idx*3 + 1]; // g
matlab_data[idx + 2 * plane_size] = frame_data[idx*3 + 2]; // b
const mwSize dims2[3] = {height,width, 3};
plhs[0] = mxCreateNumericArray(3, dims2, mxUINT8_CLASS, mxREAL);
uint8_t *matlab_data2 = (uint8_t*)mxGetData(plhs[0]);
#pragma omp parallel for collapse(2)
for(int i = 0;i<height;++i)
int idx_old = j + i*width;
int idx_new = i + j*height;
// printf("%d %d\n",idx_old,idx_new);
matlab_data2 [idx_new] = matlab_data[idx_old];
matlab_data2 [idx_new+plane_size] = matlab_data[idx_old+plane_size];
matlab_data2 [idx_new+ 2 * plane_size] = matlab_data[idx_old+ 2 * plane_size];
// printf("%d %d\n",matlab_data[idx_old],matlab_data2 [idx_new] );
// printf("-----------------------\n");