现在我正在尝试使用libav标头将一些图像编码为mp4文件。编码成功后,编码我收到一些输出,并生成一个mp4文件。但不知何故,我无法与普通玩家一起播放视频。我错过了什么吗?
这是我创建输出容器的方式:
void create_video(char *filename)
{
AVOutputFormat *fmt;
AVCodecContext *codecctx;
AVFormatContext *fmtctx;
fmt=av_guess_format(NULL,filename,NULL);
if(!fmt)
printf("Das Format kann nicht erkannt werden. MPEG wird verwendet");
AVCodec *codec = avcodec_find_encoder(fmt->video_codec);
if(codec==NULL)
printf("Codec nicht gefunden");
codecctx = avcodec_alloc_context3(codec);
codecctx->codec_id = fmt->video_codec;
codecctx->codec_type = AVMEDIA_TYPE_VIDEO;
codecctx->gop_size = 12;
codecctx->bit_rate = 800*280*4;
codecctx->width = 800;
codecctx->height = 280;
codecctx->time_base.den = 30;
codecctx->time_base.num =1;
//codecctx->time_base =(AVRational){1,FPS};
codecctx->max_b_frames=1;
codecctx->pix_fmt= STREAM_PIX_FMT;
fmtctx = avformat_alloc_context();
fmtctx->oformat = fmt;
fmtctx->video_codec_id = fmt->video_codec;
avcodec_open2(codecctx, codec, NULL);
if(avcodec_open2(codecctx, codec, NULL)<0)
printf("Error opening the codec \n");
AVStream *VideoStream = avformat_new_stream(fmtctx,0);
VideoStream->codecpar->codec_id=fmt->video_codec;
VideoStream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
VideoStream->codecpar->format = STREAM_PIX_FMT;
VideoStream->codecpar->width=800;
VideoStream->codecpar->height=280;
VideoStream->time_base.den=30;
VideoStream->time_base.num=1;
VideoStream->codec=codecctx;
avio_open(&fmtctx->pb,filename,AVIO_FLAG_WRITE);
if(avformat_write_header(fmtctx,NULL)==0)
{
Write_Video_Frame(fmtctx,VideoStream,"1.png");
Write_Video_Frame(fmtctx,VideoStream,"C:/Users/delemi/Desktop/Images/img002.png");
Write_Video_Frame(fmtctx,VideoStream,"C:/Users/delemi/Desktop/Images/img003.png");
Write_Video_Frame(fmtctx,VideoStream,"C:/Users/delemi/Desktop/Images/img004.png");
Write_Video_Frame(fmtctx,VideoStream,"C:/Users/delemi/Desktop/Images/img005.png");
Write_Video_Frame(fmtctx,VideoStream,"C:/Users/delemi/Desktop/Images/img006.png");
Write_Video_Frame(fmtctx,VideoStream,"C:/Users/delemi/Desktop/Images/img007.png");
av_write_trailer(fmtctx);
}
}
添加帧功能:
static void Write_Video_Frame(AVFormatContext *oc, AVStream *st, char* datei)
{
frame_count++;
double pts;
int test, videoStream,frameFinished,x,y;
AVFormatContext *pFormatCtx =avformat_alloc_context();
int i;
int size = WIDTH*HEIGHT;
if (avformat_open_input(&pFormatCtx, datei, NULL, NULL) !=0)
printf("Das Bild kann nicht geoeffnet werden!");
test = avformat_find_stream_info(pFormatCtx, NULL);
if(test<0)
printf("Es konnte kein Stream von dem Bild gefunden werden. \n");
AVCodecContext *c = NULL;
AVCodecContext *pCodecCtx = NULL;
c=st->codec;
// Find the first video stream
videoStream=-1;
for(i=0; i<pFormatCtx->nb_streams; i++)
if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO) {
videoStream=i;
break;
}
// Get a pointer to the codec context for the video stream
pCodecCtx=pFormatCtx->streams[videoStream]->codec;
if(pCodecCtx == NULL)
printf("CodecCtx not found");
AVCodec *pCodec = NULL;
// Find the decoder for the video stream
pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
if(pCodec==NULL) {
fprintf(stderr, "Unsupported codec of the picture \n");
}
// Oeffnet den Codec
if(avcodec_open2(pCodecCtx, pCodec,NULL)<0)
fprintf(stderr,"Error opening the codec of the picture \n");
AVFrame *pFrame;
AVFrame *pFrameYUV;
pFrame = av_frame_alloc();
pFrameYUV = av_frame_alloc();
int numBytes;
uint8_t *buffer= NULL;
numBytes=avpicture_get_size(AV_PIX_FMT_YUV420P, pCodecCtx->width,pCodecCtx->height);
buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));
uint8_t *picture_buf = (uint8_t *)av_malloc(numBytes*sizeof(uint8_t));
struct SwsContext *sws_ctx = NULL;
av_image_alloc( pFrameYUV->data, //data to be filled
pFrameYUV->linesize,//line sizes to be filled
800, 280,
AV_PIX_FMT_YUV420P, //pixel format
32 //alingn
);
sws_ctx = sws_getContext(800,280,AV_PIX_FMT_RGB24,800,280,AV_PIX_FMT_YUV420P,SWS_BICUBIC,0,0,0);
if(sws_ctx==NULL)
printf("Error");
AVPacket packet;
int zahl =0;
// initialize SWS context for software scaling
pFrameYUV->height = pFrame->height = pCodecCtx->height;
pFrameYUV->width = pFrame->width = pCodecCtx->width;
pFrameYUV->format = AV_PIX_FMT_YUV420P;
fflush(stdout);
while (av_read_frame(pFormatCtx,&packet)>=0)
{
if(packet.stream_index == videoStream)
{
avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
if(frameFinished)
{
zahl++;
sws_scale(sws_ctx,pFrame->data,pFrame->linesize,0,pCodecCtx->height,pFrameYUV->data,pFrameYUV->linesize);
printf("Packet size : %d \n ",packet.size);
}
}
av_free_packet(&packet);
}
printf("Total frames found: %d \n",zahl);
avcodec_close(pCodecCtx);
/*Find the encoder of the stream and open it*/
pCodec=avcodec_find_encoder(c->codec_id);
if(avcodec_find_encoder(c->codec_id)==NULL)
printf("Could not find the codec of ouput");
if(avcodec_open2(c,pCodec,NULL)<0)
printf("Error opening the codec of output");
AVPacket encoded;
int got_packet;
for(i=0;i<30;i++)
{
av_init_packet(&encoded);
encoded.data = NULL; // packet data will be allocated by the encoder
encoded.size = 0;
fflush(stdout);
test=avcodec_encode_video2(c,&encoded,pFrameYUV,&got_packet);
if(got_packet)
{
printf("Got_packet= %d ",got_packet);
test=av_interleaved_write_frame(oc,&encoded);
printf("Test= %d ",test);
printf("Write frame %3d (size=%5d)\n", i, encoded.size);
av_free_packet(&encoded);
}
}
avcodec_close(c);
//av_free(c);
av_freep(&pFrameYUV->data[0]);
av_frame_free(&pFrameYUV);
count++;
}
我已经尝试设置pts值,但它会使编码失败!!!!!!!