Member 11549235 Ответов: 0

Ошибка кодирования 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.

0 Ответов