我试图通过以下在线示例来了解FFmpeg API,但似乎FFmpeg API随着时间的推移而发生了变化,使得大部分示例都已过时;我希望你们中的一些人可以帮助我更好地理解FFmpeg API的例子。
我目前正在尝试了解FFmpeg中的encoding-example,但我在此行收到了访问冲突错误:
out_size = avcodec_encode_video2(codecCtx, &avpkt, picture, &got_packet);
我在test01_encode.exe中的0x77c29e42处获得“未处理的异常:0xC0000005:访问冲突读取位置0xccccccc8。”来自Visual Studio。
我了解 avcodec_encode_video()已弃用,而使用AVPacket的 avcodec_encode_video2()。我已经为AVPacket的数据成员分配了一个缓冲区并设置了它的大小,但仍然是相同的。我错过了什么?
我正在使用的库是 ffmpeg-20160219-git-98a0053-win32-dev 。如果你能帮我解决这个困惑,我真的很感激。
(侧面:“获取延迟帧”是什么意思,为什么我们通过将AVFrame *参数指定为NULL进行编码?)
/*
* Video encoding example
*/
char filename[] = "test.mpg";
int main(int argc, char** argv)
{
AVCodec *codec;
AVCodecContext *codecCtx= NULL;
int i, out_size, size, x, y, outbuf_size;
FILE *f;
AVFrame *picture;
uint8_t *outbuf, *picture_buf;
printf("Video encoding\n");
// Register all formats and codecs
av_register_all();
/* find the mpeg1 video encoder */
codec = avcodec_find_encoder(AV_CODEC_ID_MPEG1VIDEO);
if (!codec) {
fprintf(stderr, "codec not found\n");
exit(1);
}
codecCtx= avcodec_alloc_context3(codec);
picture= av_frame_alloc();
/* put sample parameters */
codecCtx->bit_rate = 400000;
/* resolution must be a multiple of two */
codecCtx->width = 352;
codecCtx->height = 288;
/* frames per second */
//codecCtx->time_base= (AVRational){1,25};
codecCtx->time_base.num = 1;
codecCtx->time_base.den = 25;
codecCtx->gop_size = 10; /* emit one intra frame every ten frames */
codecCtx->max_b_frames=1;
codecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
/* open it */
if (avcodec_open2(codecCtx, codec, NULL) < 0) {
fprintf(stderr, "could not open codec\n");
exit(1);
}
fopen_s(&f,filename, "wb");
if (!f) {
fprintf(stderr, "could not open %s\n", filename);
exit(1);
}
/* alloc image and output buffer */
outbuf_size = 100000;
outbuf = (uint8_t*) malloc(outbuf_size);
size = codecCtx->width * codecCtx->height;
picture_buf = (uint8_t*) malloc((size * 3) / 2); /* size for YUV 420 */
picture->data[0] = picture_buf;
picture->data[1] = picture->data[0] + size;
picture->data[2] = picture->data[1] + size / 4;
picture->linesize[0] = codecCtx->width;
picture->linesize[1] = codecCtx->width / 2;
picture->linesize[2] = codecCtx->width / 2;
picture->width = codecCtx->width;
picture->height = codecCtx->height;
picture->format = codecCtx->pix_fmt;
AVPacket avpkt;
int got_packet;
avpkt.size=av_image_get_buffer_size(codecCtx->pix_fmt, codecCtx->width,
codecCtx->height,1);
avpkt.data = (uint8_t *)av_malloc(avpkt.size*sizeof(uint8_t));
/* encode 1 second of video */
for(i=0;i<25;i++) {
fflush(stdout);
/* prepare a dummy image */
/* Y */
for(y=0;y<codecCtx->height;y++) {
for(x=0;x<codecCtx->width;x++) {
picture->data[0][y * picture->linesize[0] + x] = x + y + i * 3;
}
}
/* Cb and Cr */
for(y=0;y<codecCtx->height/2;y++) {
for(x=0;x<codecCtx->width/2;x++) {
picture->data[1][y * picture->linesize[1] + x] = 128 + y + i * 2;
picture->data[2][y * picture->linesize[2] + x] = 64 + x + i * 5;
}
}
/* encode the image */
//out_size = avcodec_encode_video(codecCtx, outbuf, outbuf_size, picture);
// <Access violation>
out_size = avcodec_encode_video2(codecCtx, &avpkt, picture, &got_packet);
printf("encoding frame %3d (size=%5d)\n", i, out_size);
//fwrite(outbuf, 1, out_size, f);
fwrite(avpkt.data, 1, avpkt.size, f);
}
/* get the delayed frames */
for(; out_size; i++) {
fflush(stdout);
//out_size = avcodec_encode_video(codecCtx, outbuf, outbuf_size, NULL);
out_size = avcodec_encode_video2(codecCtx, &avpkt, NULL, &got_packet);
printf("write frame %3d (size=%5d)\n", i, out_size);
//fwrite(outbuf, 1, out_size, f);
fwrite(avpkt.data, 1, avpkt.size, f);
}
/* add sequence end code to have a real mpeg file */
outbuf[0] = 0x00;
outbuf[1] = 0x00;
outbuf[2] = 0x01;
outbuf[3] = 0xb7;
fwrite(outbuf, 1, 4, f);
fclose(f);
free(picture_buf);
free(outbuf);
avcodec_close(codecCtx);
av_free(codecCtx);
av_free(picture);
printf("\n");
}