[Libav-user] Using ffmpeg with SDL2 - Bad src image pointers / New decoding flow - questions
Jan
jan at dwrox.net
Sun Feb 5 17:07:39 EET 2017
Hello,
Im currently working on a video player software, which should be based
on ffmpeg tools and at the moment of writing, using SDL2 for display of
the video content.
The documentation for ffmpeg is a bit difficult to get through, as most
example code seems to be outdated or using deprecated features.
The SDL tutorial is also not valid anymore, as well as the updated
version on Github or other information which can be found using a search
engine of choice.
So I would be glad about assistance.
I seem to struggle at one point: using libswscale's swscale.
I receive the error: "swscaler @ [address] bad src image pointer"
Following parts of the code I use, perhaps the issue is easy to spot?
Also I am not sure if I use "av_read_frame" and "avcodec_send_packet"
correctly in the code which should be the new way to go.
I try to set comments where output is displayed. And some in the code.
Following what I have done so far.
The error I get:
[swscaler @ 0x555e2af7ff60] bad src image pointers
//--------------------------------------------------------------------
// Listing of player.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_video.h>
#include <SDL2/SDL_timer.h>
#include <SDL2/SDL_render.h>
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
#include "libavutil/avutil.h"
#include "libavutil/imgutils.h"
#include "libavutil/opt.h"
int main(int argc, char *argv[]) {
//----------------------------------------------------------------------------
// SDL
//----------------------------------------------------------------------------
if (SDL_VideoInit(NULL) != 0) {
fprintf(stderr, "\nCould not initialize SDL2 video: %s\n",
SDL_GetError());
return -1;
}
SDL_Window *playerWindow = SDL_CreateWindow("Playerwindow",
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, 0);
if (playerWindow == NULL) {
fprintf(stderr, "\nCould not create application window.\n");
return -1;
}
SDL_Event event;
SDL_Renderer* gfxRenderer = SDL_CreateRenderer(playerWindow, -1,
SDL_RENDERER_ACCELERATED);
//----------------------------------------------------------------------------
// Init AV backend
//----------------------------------------------------------------------------
av_register_all();
//----------------------------------------------------------------------------
// Video handling
//----------------------------------------------------------------------------
AVFormatContext *avFormatContext = NULL;
AVCodecContext *videoCodecContext = NULL;
AVDictionary *avOptions = NULL;
AVPacket framePackage;
AVFrame *videoFrame = NULL;
AVFrame *videoFrameRGB = NULL;
AVCodec *videoCodec = NULL;
if (avformat_open_input(&avFormatContext, "test.avi", NULL, NULL) != 0) {
fprintf(stderr, "Error opening video file.\n");
return -1;
}
/* retrieve stream information */
if (avformat_find_stream_info(avFormatContext, NULL) < 0) {
avformat_close_input(&avFormatContext);
fprintf(stderr, "No stream information present.\n");
return -1;
}
av_dump_format(avFormatContext, 0, "test.avi", 0);
// Output of av_dump_format (please note that the duration is shown as
well as the "pix fmt" YUV420P... later on this is not and its enforced!
// Input #0, avi, from 'test.avi':
// Metadata:
// encoder : Lavf57.56.100
// Duration: 00:08:37.43, start: 0.000000, bitrate: 1081 kb/s
// Stream #0:0: Video: mpeg4 (Simple Profile) (xvid / 0x64697678),
yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 1075 kb/s, 30 fps, 30 tbr, 30 tbn,
30 tbc
int foundStream = av_find_best_stream(avFormatContext,
AVMEDIA_TYPE_VIDEO, -1, -1, &videoCodec, 0);
int width = 0;
int height = 0;
if (foundStream >= 0) {
videoCodec =
avcodec_find_decoder(avFormatContext->streams[foundStream]->codecpar->codec_id);
videoCodecContext = avcodec_alloc_context3(videoCodec);
if (avcodec_open2(videoCodecContext, videoCodec, NULL) < 0) {
fprintf(stderr, "Could not open codec\n");
return -1;
}
// FPS
int videoFramePerSecond =
av_q2d(avFormatContext->streams[foundStream]->r_frame_rate);
// Base time unit
int videoBaseTime =
av_q2d(avFormatContext->streams[foundStream]->time_base);
// Duration of video clip
unsigned long videoDuration = (unsigned long)
avFormatContext->streams[foundStream]->duration * (videoFramePerSecond *
videoBaseTime);
// Frame width
width = avFormatContext->streams[foundStream]->codecpar->width;
// Frame height
height = avFormatContext->streams[foundStream]->codecpar->height;
printf("fps: %d, basetime: %d, duration: %ld, width: %d, height:
%d\n", videoFramePerSecond, videoBaseTime, videoDuration, width, height);
// Output:
// fps: 30, basetime: 0, duration: 0, width: 1280, height: 720
printf("inside - pix format : %d\n", videoCodecContext->pix_fmt);
// Output:
// inside - pix format : -1 (why -1 ?, should this not be in line with
the av_dump_format output?)
struct SwsContext *sws_context = NULL;
sws_context = sws_getContext(width, height, AV_PIX_FMT_YUV420P,
width, height, AV_PIX_FMT_RGB24, SWS_FAST_BILINEAR, NULL, NULL, NULL);
videoFrame = av_frame_alloc();
videoFrameRGB = av_frame_alloc();
//avcodec_align_dimensions(videoCodecContext, &width, &height); //
this always crashes
videoFrameRGB->format = AV_PIX_FMT_RGB24;
videoFrameRGB->width = width;
videoFrameRGB->height = height;
printf("buffer allocated: %d\n",av_frame_get_buffer(videoFrameRGB,
AV_INPUT_BUFFER_PADDING_SIZE));
// Output:
// buffer allocated: 0
printf("made writeable: %d\n", av_frame_make_writable(videoFrameRGB));
// Output:
// made writeable: 0
printf("is writeable: %d\n", av_frame_is_writable(videoFrameRGB));
// Output:
// is writeable: 1
av_init_packet(&framePackage);
int frameIndex = 1;
framePackage.data = NULL; // packet data will be allocated by the
encoder
framePackage.size = 0;
// SDL
SDL_Rect displayRect = {0, 0, width, height};
SDL_Texture *videoTexture = SDL_CreateTexture(gfxRenderer,
SDL_PIXELFORMAT_RGB24, SDL_TEXTUREACCESS_STREAMING,
videoCodecContext->width, videoCodecContext->height);
//----------------------------------------------------------------
while (av_read_frame(avFormatContext, &framePackage) == 0) {
if (framePackage.stream_index == foundStream) {
int retVal = avcodec_send_packet(videoCodecContext, &framePackage);
if (retVal == 0) {
printf("Success\n");
// Outputs success, so the frame should be read as displayable?
} else {
printf("%s\n", av_err2str(retVal));
continue;
}
printf("Frame #%8d | pts: %ld | dts: %ld | size: %10d |
stream_index: %d | flags: %d | duration: %ld | pos: %ld\n",
frameIndex,
framePackage.pts, framePackage.dts, framePackage.size,
framePackage.stream_index, framePackage.flags,
framePackage.duration, framePackage.pos
);
videoFrame->width = width;
videoFrame->height = height;
videoFrameRGB->format = AV_PIX_FMT_RGB24;
videoFrameRGB->width = width;
videoFrameRGB->height = height;
printf("width: %d, height: %d\n", width, height);
av_frame_get_buffer(videoFrameRGB, AV_INPUT_BUFFER_PADDING_SIZE);
sws_getCachedContext(sws_context, width, height,
AV_PIX_FMT_YUV420P, width, height, AV_PIX_FMT_RGB24, SWS_FAST_BILINEAR,
NULL, NULL, NULL);
printf("%d\n", sws_scale(sws_context, (const uint8_t * const *)
videoFrame->data, videoFrame->linesize, 0, height, videoFrameRGB->data,
videoFrameRGB->linesize));
SDL_RenderClear(gfxRenderer);
SDL_UpdateTexture(videoTexture, NULL, videoFrameRGB->data,
videoFrameRGB->linesize[0]);
SDL_RenderCopy(gfxRenderer, videoTexture, NULL, &displayRect);
SDL_RenderPresent(gfxRenderer);
SDL_Delay(1000 / 25);
bool doQuit = false;
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
doQuit = true;
break;
default:
break;
}
}
avcodec_send_packet(videoCodecContext, NULL);
if (doQuit) {
break;
}
++frameIndex;
av_frame_unref(videoFrameRGB);
av_frame_unref(videoFrame);
}
avcodec_flush_buffers(videoCodecContext);
}
//av_free_packet(&framePackage);
SDL_DestroyTexture(videoTexture);
}
// Cleanup video
av_packet_unref(&framePackage);
av_frame_free(&videoFrame);
av_frame_free(&videoFrameRGB);
// Cleanup ffmpeg components
av_dict_free(&avOptions);
avformat_close_input(&avFormatContext);
// Cleanup SDL
SDL_DestroyRenderer(gfxRenderer);
SDL_DestroyWindow(playerWindow);
printf("Done.\n");
return 0;
}
//----------------------------------------------------------------
What am I missing out here, the alignment?
If you need any other information, please let me know.
Thank you for any help in advance.
Jan
More information about the Libav-user
mailing list