[FFmpeg-user] Segmentation Faults - avcodec_encode_video Please Help
Aditya
adi235 at gmail.com
Mon May 9 14:01:51 CEST 2011
I am writing a simple C program to accept video input decode it encode it into
flv and then save output video file. I have looked at danger's tutorials,
output-example.c,api-example.c and such. But i seem to be missing something very
essential. And always end up encountering , segmentation faults, ( sometimes
buffer under flows or warning max analysis time reached. The below is the
program. I would very much appreciate for a clear solution to this problem. I
have spend to many days trying to figure this out already.
[CODE]
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
static void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame);
AVFormatContext *pFormatCtx;
static int i, videoStream;
AVCodecContext *pCodecCtx;
AVCodec *pCodec;
AVFrame *pFrame;
AVFrame *pFrameRGB;
AVPacket packet;
static int frameFinished;
static int numBytes;
static uint8_t *buffer;
AVCodec *codec;
AVCodecContext *c = NULL;
int out_size, size, outbuf_size;
uint8_t *outbuf;
FILE *f;
int init_video_file(char *inputFileName) {
// Register all formats and codecs
av_register_all();
// Open video file
if (av_open_input_file(&pFormatCtx, inputFileName, 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, inputFileName, false);
// 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
return 0;
}
int init_video_codec() {
// Get a pointer to the codec context for the video stream
pCodecCtx = pFormatCtx->streams[videoStream]->codec;
// Find the decoder for the video stream
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if (pCodec == NULL)
return -1; // Codec not found
// Open codec
if (avcodec_open(pCodecCtx, pCodec) < 0)
return -1; // Could not open codec
return 0;
}
int set_frame_data() {
// Hack to correct wrong frame rates that seem to be generated by some codecs
if (pCodecCtx->time_base.num > 1000 && pCodecCtx->time_base.den == 1)
pCodecCtx->time_base.den = 1000;
// Allocate video frame
pFrame = avcodec_alloc_frame();
// Allocate an AVFrame structure
pFrameRGB = avcodec_alloc_frame();
if (pFrameRGB == NULL)
return -1;
// Determine required buffer size and allocate buffer
numBytes = avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width,
pCodecCtx->height);
buffer = malloc(numBytes);
// Assign appropriate parts of buffer to image planes in pFrameRGB
avpicture_fill((AVPicture *) pFrameRGB, buffer, PIX_FMT_RGB24,
pCodecCtx->width, pCodecCtx->height);
return 0;
}
void process_packet_data(char *outFileName) {
// Read frames and save first five frames to disk
i = 0;
while (av_read_frame(pFormatCtx, &packet) >= 0) {
// Is this a packet from the video stream?
if (packet.stream_index == videoStream) {
// Decode video frame
avcodec_decode_video(pCodecCtx, pFrame, &frameFinished,
packet.data, packet.size);
// Did we get a video frame?
if (frameFinished) {
//printf("\n packet size= %d \t pframe number=n%d ", packet.size,
// pFrame->coded_picture_number);
// Insane segmentation faults when encoding the got frame.. !!Help.
//out_size = avcodec_encode_video(c, outbuf, outbuf_size, pFrame);
save_frame_as_image();
}
}
// Free the packet that was allocated by av_read_frame
av_free_packet(&packet);
}
}
void set_encoder_for_output(const char *filename) {
uint8_t *outbuf;
printf("Video encoding\n");
/* find the mpeg1 video encoder */
codec = avcodec_find_encoder(CODEC_ID_FLASHSV);
if (!codec) {
fprintf(stderr, "codec not found\n");
exit(1);
}
c = avcodec_alloc_context();
pFrame = avcodec_alloc_frame();
/* put sample parameters */
c->bit_rate = 128000;
/* resolution must be a multiple of two */
c->width = 320;
c->height = 240;
/* frames per second */
c->time_base = (AVRational) {1,25};
c->gop_size = 10; /* emit one intra frame every ten frames */
c->max_b_frames=1;
c->pix_fmt = PIX_FMT_YUV420P;
/* open it */
if (avcodec_open(c, codec) < 0) {
fprintf(stderr, "could not open codec\n");
exit(1);
}
f = fopen(filename, "wb");
if (!f) {
fprintf(stderr, "could not open ______::: %s\n", filename);
exit(1);
}
/* alloc image and output buffer */
outbuf_size = 230400;
outbuf = malloc(outbuf_size);
size = c->width * c->height;
//out_size = avcodec_encode_video(c, outbuf, outbuf_size, picture);
}
void cleanup() {
// Free the RGB image'
free(outbuf);
avcodec_close(c);
av_free(c);
printf("\n");
free(buffer);
av_free(pFrameRGB);
// Free the YUV frame
av_free(pFrame);
// Close the codec
avcodec_close(pCodecCtx);
// Close the video file
av_close_input_file(pFormatCtx);
}
void encode_frames_to_video() {
}
void save_frame_as_image() {
static struct SwsContext *img_convert_ctx;
// Convert the image into YUV format that SDL uses
if (img_convert_ctx == NULL) {
int w = pCodecCtx->width;
int h = pCodecCtx->height;
img_convert_ctx = sws_getContext(w, h, pCodecCtx->pix_fmt, w, h,
PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
if (img_convert_ctx == NULL) {
fprintf(stderr, "Cannot initialize the conversion context!\n");
exit(1);
}
}
int ret = sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0,
pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
// Save the frame to disk
if (i++ <= 5)
SaveFrame(pFrameRGB, pCodecCtx->width, pCodecCtx->height, i);
}
int main(int argc, char * argv[]) {
init_video_file(argv[1]);
init_video_codec();
set_frame_data();
set_encoder_for_output(argv[2]);
process_packet_data(argv[2]);
cleanup();
return 0;
}
static 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);
}
[/CODE]
[b] Kindly help in resolving the segmentation faults in the above program [/b]
I have been unable to find any straight forward example on how to do this.
Thanks
More information about the ffmpeg-user
mailing list