Ошибка кодирования MP4 видео с помощью libav
Прямо сейчас я пытаюсь закодировать некоторые изображения в файл mp4 с помощью заголовков libav. кодировка была успешной, после кодирования я получаю некоторый вывод, и генерируется файл 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); } }
И функция добавления кадра:
<pre lang="C++">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) { AVRational rat = {1,30}; av_packet_rescale_ts(&encoded,rat, st->time_base); encoded.stream_index=st->index; 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, но это приводит к сбою кодировки!!!!!!!
Sergey Alexandrovich Kryukov
Какие "нормальные игроки"? Вы имеете в виду, что вы можете воспроизвести файл с помощью утилиты *play, поставляемой вместе с библиотекой, но не с другими игроками?
Какова ваша платформа?
Обратите внимание, что такого понятия, как файл "MP4", не существует. Каждый медиафайл представляет собой комбинацию медиаконтейнера и одного или нескольких каналов на основе различных кодеков. MPEG-4-это целый набор различных (и альтернативных) стандартов. Что именно вы используете? (Вы можете найти ответ, если используете свою утилиту * probe, в FFMpeg она называется ffprobe, ffprobe.exe.) это может быть такая простая вещь, как отсутствие кодеков, установленных в вашей системе. А некоторые плееры, такие как Windows Media Player, заведомо бедны с точки зрения поддержки набора современных стандартов.
—СА
Member 11549235
Привет,
Созданное видео можно открыть с помощью ffplay,но нельзя открыть с помощью проигрывателя Windows Media. Я попытался открыть еще один контейнер mp4 с помощью WMP, он работает.
KarstenK
Проигрыватель windows media дерьмовый. У меня есть много видео, которое не может быть воспроизведено. Попробуйте VLC Player.