我是靠谱客的博主 单身蓝天,最近开发中收集的这篇文章主要介绍SkeyeExPlayer(Windows)开发系列之采用ffmpeg进行截图,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

下面我们讲解下SkeyeExPlayer的截图功能,截图原理就是将YUV/RGB原始数据压缩成jpg或者png等格式(当然bmp格式是不需要压缩的),然后存储成文件的过程;我们以jpg格式为例进行讲解;一般情况下可以使用libjpeg库进行jpeg格式压缩,在不使用libjpeg的情况下,可以使用ffmpeg(内部也集成了libjpeg库)提供的接口进行压缩并写文件,这个方式也普遍适用于写MP4或者其他文件,下面我们讲解下ffmpeg进行截图的流程。

1.数据源转换


// init ffmpeg
av_register_all();
fileext = file + strlen(file) - 3;
codecid = AV_CODEC_ID_MJPEG;
swsofmt = AV_PIX_FMT_YUVJ420P;
// alloc frame
frame.format = swsofmt;
frame.width
= w > 0 ? w : video->width;
frame.height = h > 0 ? h : video->height;
if (av_frame_get_buffer(&frame, 32) < 0) {
av_log(NULL, AV_LOG_ERROR, "failed to allocate frame !n", file);
goto done;
}
// scale frame
sws_ctx = sws_getContext(video->width, video->height, (AVPixelFormat)Format/*video->format*/,
frame.width, frame.height, swsofmt, SWS_FAST_BILINEAR, NULL, NULL, NULL);
if (!sws_ctx) {
av_log(NULL, AV_LOG_ERROR, "could not initialize the conversion context jpgn");
goto done;
}
sws_scale(sws_ctx, video->data, video->linesize, 0, video->height, frame.data, frame.linesize);

这段代码很简单,首先初始化ffmpeg,然后进行格式转换,注意,为了格式统一,这里统一将格式转换成YUV420,以便进行编码,指定输入格式为YUV420,输出格式为JPEG;如果要编码为PNG,这里指定格式为PNG即可:

 if (_stricmp(fileext, "png") == 0)
{
codecid = AV_CODEC_ID_APNG;
swsofmt = AV_PIX_FMT_RGB24;
}

2.数据源编码


// jpeg encoding
fmt_ctxt = avformat_alloc_context();
out_fmt
= av_guess_format("mjpeg", NULL, NULL);
fmt_ctxt->oformat = out_fmt;
if (!out_fmt) {
av_log(NULL, AV_LOG_ERROR, "failed to guess format !n");
goto done;
}
if (avio_open(&fmt_ctxt->pb, file, AVIO_FLAG_READ_WRITE) < 0) {
av_log(NULL, AV_LOG_ERROR, "failed to open output file: %s !n", file);
goto done;
}
stream = avformat_new_stream(fmt_ctxt, 0);
if (!stream) {
av_log(NULL, AV_LOG_ERROR, "failed to create a new stream !n");
goto done;
}
codec_ctxt
= stream->codec;
codec_ctxt->codec_id
= out_fmt->video_codec;
codec_ctxt->codec_type
= AVMEDIA_TYPE_VIDEO;
codec_ctxt->pix_fmt
= swsofmt;
codec_ctxt->width
= frame.width;
codec_ctxt->height
= frame.height;
codec_ctxt->time_base.num = 1;
codec_ctxt->time_base.den = 25;
codec = avcodec_find_encoder(codec_ctxt->codec_id);
if (!codec) {
av_log(NULL, AV_LOG_ERROR, "failed to find encoder !n");
goto done;
}
if (avcodec_open2(codec_ctxt, codec, NULL) < 0) {
av_log(NULL, AV_LOG_ERROR, "failed to open encoder !n");
goto done;
}
while (retry-- && !got)
{
if (avcodec_encode_video2(codec_ctxt, &packet, &frame, &got) < 0) {
av_log(NULL, AV_LOG_ERROR, "failed to do frame encoding !n");
goto done;
}
if (got) {
ret = avformat_write_header(fmt_ctxt, NULL);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "error occurred when opening output file !n");
goto done;
}
av_write_frame(fmt_ctxt, &packet);
av_write_trailer(fmt_ctxt);
}
}

avcodec_find_encoder找到一个编码器,指定一个格式为JPEG进行编码,avcodec_encode_video2函数进行编码。

3.jpeg编码数据写文件

从2中代码段可以看出,通过avcodec_open2打开一个文件,通过avformat_new_stream新建一个输出流,avformat_write_header
写入文件头,av_write_frame写入一帧数据,av_write_trailer写入文件尾,存入一帧数据成jpeg结束。

最后

以上就是单身蓝天为你收集整理的SkeyeExPlayer(Windows)开发系列之采用ffmpeg进行截图的全部内容,希望文章能够帮你解决SkeyeExPlayer(Windows)开发系列之采用ffmpeg进行截图所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(33)

评论列表共有 0 条评论

立即
投稿
返回
顶部