在尝试使用x264编码器在Windows上构建ffmpeg静态库时,我花了相当多的时间来编写一些示例。当然,有一大堆关于如何构建,如何使用,诸如此类的“说明”。但是,它们都不能在Windows上运行。我猜Linux的人在这里处于更好的位置。现在,数十亿美元的问题是“这一切的目的是什么?”这不仅在Windows上没有用,而且我可以买一些实际有效的第三方库。
如果有人要说“但是,它起作用了!”我必须说,给我一个有效的证明。我不关心10fps下的200x100。我不需要H264来解决这个问题。演示如何压缩一秒的1080i素材。它是H264,它是跨平台的(如果你问我,听起来很有趣),谷歌正在使用它(它必须是完美的,对吧?),还有更多的hipe……
发布于 2011-12-10 07:37:00
首先,不要尝试在windows上构建--特别是如果你使用VS --从here获取
那么序列是这样的:
// in ctor
ffmpeg::avcodec_register_all();
ffmpeg::avcodec_init();
ffmpeg::av_register_all();
bool createFile(const String &fileName,unsigned int width,unsigned int height,unsigned int fps)
{
close();
pFormatCtx=ffmpeg::avformat_alloc_context();
if(!pFormatCtx)
{
printf("Error allocating format context\n");
return false;
}
pOutputFormat = ffmpeg::av_guess_format( "mp4", filename,NULL);
pFormatCtx->oformat = pOutputFormat;
_snprintf(pFormatCtx->filename, sizeof(pFormatCtx->filename), "%s",filename);
// Add the video stream
pVideoStream = av_new_stream(pFormatCtx,0);
if(!pVideoStream )
{
printf("Could not allocate stream\n");
return false;
}
pCodecCtx=pVideoStream->codec;
pCodecCtx->codec_id = pOutputFormat->video_codec;
pCodecCtx->codec_type = ffmpeg::AVMEDIA_TYPE_VIDEO;
pCodecCtx->width = Width = width;
pCodecCtx->height = Height = height;
pCodecCtx->time_base.num = 1;
pCodecCtx->time_base.den = Fps = fps;
pCodecCtx->pix_fmt = ffmpeg::PIX_FMT_YUV420P;
// needed for x264 to work
pCodecCtx->me_range = 16;
pCodecCtx->max_qdiff = 4;
pCodecCtx->qmin = 10;
pCodecCtx->qmax = 51;
pCodecCtx->qcompress = 0.6;
pCodecCtx->gop_size = 12;
avcodec_thread_init(pCodecCtx, 10);
// some formats want stream headers to be separate
if(pFormatCtx->oformat->flags & AVFMT_GLOBALHEADER)
pCodecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;
if (av_set_parameters(pFormatCtx, NULL) < 0)
{
printf("Invalid output format parameters\n");
return false;
}
ffmpeg::dump_format(pFormatCtx, 0, pFormatCtx->filename, 1);
// open_video
// find the video encoder
pCodec = avcodec_find_encoder(pCodecCtx->codec_id);
if (!pCodec)
{
printf("codec not found\n");
return false;
}
// open the codec
if (avcodec_open(pCodecCtx, pCodec) < 0)
{
printf("could not open codec\n");
return false;
}
// Allocate memory for output
if(!initOutputBuf())
{
printf("Can't allocate memory for output bitstream\n");
return false;
}
// Allocate the YUV frame
if(!initFrame())
{
printf("Can't init frame\n");
return false;
}
if (url_fopen(&pFormatCtx->pb,pFormatCtx->filename, URL_WRONLY) < 0)
{
printf( "Could not open '%s'\n", pFormatCtx->filename);
return false;
}
av_write_header(pFormatCtx);
return true;
}然后,对于每个帧
int encodeImage(const QImage &img)
{
if (!convertImage_sws(img)) { // SWS conversion
return false;
}
ppicture->pts=pCodecCtx->frame_number;
//memset(outbuf,0,outbuf_size);
int out_size = ffmpeg::avcodec_encode_video(pCodecCtx,outbuf,outbuf_size,ppicture);
if (out_size > 0) {
ffmpeg::AVPacket pkt;
av_init_packet(&pkt);
if (pCodecCtx->coded_frame->pts != (0x8000000000000000LL))
pkt.pts= av_rescale_q(pCodecCtx->coded_frame->pts, pCodecCtx->time_base, pVideoStream->time_base);
if(pCodecCtx->coded_frame->key_frame)
pkt.flags |= AV_PKT_FLAG_KEY;
pkt.stream_index= pVideoStream->index;
pkt.data= outbuf;
pkt.size= out_size;
if (av_write_frame(pFormatCtx, &pkt) < 0 ) {
return 0;
}
}
return out_size;
}
void close()
{
av_write_trailer(pFormatCtx);
// close_video
avcodec_close(pVideoStream->codec);
freeFrame();
freeOutputBuf();
/* free the streams */
for(int i = 0; i < pFormatCtx->nb_streams; i++)
{
av_freep(&pFormatCtx->streams[i]->codec);
av_freep(&pFormatCtx->streams[i]);
}
// Close file
url_fclose(pFormatCtx->pb);
// Free the stream
av_free(pFormatCtx);
}
bool initFrame()
{
ppicture = ffmpeg::avcodec_alloc_frame();
if(ppicture==0)
return false;
int size = avpicture_get_size(pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);
picture_buf = new uint8_t[size];
if(picture_buf==0)
{
av_free(ppicture);
ppicture=0;
return false;
}
// Setup the planes
avpicture_fill((ffmpeg::AVPicture *)ppicture, picture_buf,pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);
ppicture->pts = 0;
return true;
}发布于 2012-01-25 11:14:56
如果要在隔行扫描模式下使用libavcodec+libx264进行编码,请使用CODEC_FLAG_INTERLACED_DCT。如果可能,您应该直接使用libx264或CLI程序,这样做的工作量会更少。
https://stackoverflow.com/questions/8452985
复制相似问题