热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

开发笔记:ffmpeg结合SDL编写播放器

篇首语:本文由编程笔记#小编为大家整理,主要介绍了ffmpeg结合SDL编写播放器相关的知识,希望对你有一定的参考价值。接下来是解析影片的帧

篇首语:本文由编程笔记#小编为大家整理,主要介绍了ffmpeg结合SDL编写播放器相关的知识,希望对你有一定的参考价值。


接下来是解析影片的帧


/***
project.c
**
*/
#include

#include

#include

#include

void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame)
{
FILE
*pFile;
char szFilename[32];
int y;

//open file
sprintf(szFilename,"frame%d.ppm",iFrame);
pFile
= fopen(szFilename, "wb");
if (NULL == pFile)
return;

//write header
fprintf(pFile, "P6
%d %d
255
",width,height);
//write pixel data
for (y = 0; y )
{
fwrite(pFrame->data[0] + y * pFrame->linesize[0],
1, width * 3, pFile);
}

//close file
fclose(pFile);
}
int main(int argc, char *argv[])
{
AVFormatContext
*pFormatCtx = NULL;
AVCodecContext
*pCodecCtx = NULL;
AVCodec
*pCodec = NULL;
AVFrame
*pFrame = NULL;
AVFrame
*pFrameRGB = NULL;
AVPacket packet;
int i,videoStream;
int frameFinished;
int numBytes;
uint8_t
*buffer = NULL;

AVDictionary
*optiOnsDict= NULL;
struct SwsContext *sws_ctx = NULL;
if (argc <2)
{
printf(
"Please provide a movie file
");
return -1;
}

//register all formats and codecs
av_register_all();

//open video file
if (avformat_open_input(&pFormatCtx,argv[1], NULL, NULL) != 0)
{
return -1; //couldn‘t open file
}

//retrive stream information
if (avformat_find_stream_info(pFormatCtx, NULL) <0)
{
return -1; //couldn‘t find stream information
}

//dump information about file onto standard error
av_dump_format(pFormatCtx, 0, argv[1], 0);

//find the first video stream
videoStream = -1;
for (i = 0; i nb_streams; i++)
{
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
videoStream
= i;
break;
}
}
if (videoStream == -1)
{
return -1; //Don‘t find a video stream
}

//Get a pointer to the codec context for the video stream
pCodecCtx = pFormatCtx->streams[videoStream]->codec;

//Find the decoder for the video stream
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if (pCodec == NULL)
{
fprintf(stderr,
"Unsupported codec!
");
return -1; //Codec not found
}
//open codec
if (avcodec_open2(pCodecCtx, pCodec, &optionsDict) <0)
{
return -1; //Could not open codec
}

//Allcocate an AVFrame structure
pFrame = av_frame_alloc();
pFrameRGB
= av_frame_alloc();
if (pFrameRGB == NULL)
{
return -1;
}

//Determine required buffer size and allocate buffer
numBytes = avpicture_get_size(AV_PIX_FMT_RGB24, pCodecCtx->width,
pCodecCtx
->height);
buffer
= (uint8_t *)av_malloc(numBytes * sizeof(uint8_t));
sws_ctx
= sws_getContext
(
pCodecCtx
->width,
pCodecCtx
->height,
pCodecCtx
->pix_fmt,
pCodecCtx
->width,
pCodecCtx
->height,
AV_PIX_FMT_RGB24,
SWS_BILINEAR,
NULL, NULL, NULL
);

//Assign appropriate parts of buffer to image planes in pFrameRGB
//Note that pFrameRGB is an AVFrame, but AVFrame is a superset
// of AVFPicture
avpicture_fill((AVPicture *)pFrameRGB, buffer,
AV_PIX_FMT_RGB24, pCodecCtx
->width, pCodecCtx->height);
//Read frames and save first five frames to disk
i = 0;
while (av_read_frame(pFormatCtx, &packet) >= 0)
{
//Is this a packet from video stream
if (packet.stream_index == videoStream)
{
//decode video frame
avcodec_decode_video2(pCodecCtx, pFrame,
&frameFinished, &packet);

//Did wo get a video frame
if (frameFinished)
{
//Convert the image from its native format to RGB
sws_scale(sws_ctx,
(uint8_t
const * const *)pFrame->data,
pFrame
->linesize,
0,
pCodecCtx
->height,
pFrameRGB
->data,
pFrameRGB
->linesize
);

//Save the frame to disk
SaveFrame(pFrameRGB,pCodecCtx->width,
pCodecCtx
->height,i);
printf(
"decde %d frame
",i);
i
++;
}
}

//Free the packet that was allocated by av_read_frame
av_free_packet(&packet);
}
//Free the RGB image
av_free(buffer);
av_free(pFrameRGB);

//Free the YUV frame
av_free(pFrame);

//Close the codec
avcodec_close(pCodecCtx);

//Close the video file
avformat_close_input(&pFormatCtx);
return 0;
}

makefile如下:


//makefile

DIR_INC
= -I/usr/local/include
DIR_LIB
= -L/usr/local/lib
LIBS
= -lavformat -lavcodec -lva-x11 -lva -lxcb-shm -lxcb-xfixes -lxcb-render -lxcb-shape -lxcb -lX11 -lasound -lz -lswresample -lswscale -lavutil -lm -pthread
FLAGS
= -Wall -ggdb
project : project.c
gcc project.c ${FLAGS} ${DIR_INC} ${DIR_LIB} ${LIBS} -o project

.PHONY:clean
clean:
rm project

运行结果:

技术图片

完成后有很多ppm文件,可以将ppm转为jpg:

编写一个脚本转化,内容如下:


/***
1.sh
**
*/
#
!/bin/bash
ff
=`ls *.ppm`
for f in $ff
do
file=`echo ${f%.*}`
ffmpeg
-i "$file".ppm "$file".jpg
done
mkdir -p jpgs
mv *.jpg jpgs
rm *.ppm

运行脚本:

sh 1.sh

可以在当前文件夹下找到jpgs文件夹下找到所有转化的jpg图片。


推荐阅读
  • 在Android平台中,播放音频的采样率通常固定为44.1kHz,而录音的采样率则固定为8kHz。为了确保音频设备的正常工作,底层驱动必须预先设定这些固定的采样率。当上层应用提供的采样率与这些预设值不匹配时,需要通过重采样(resample)技术来调整采样率,以保证音频数据的正确处理和传输。本文将详细探讨FFMpeg在音频处理中的基础理论及重采样技术的应用。 ... [详细]
  • 深入解析Android 4.4中的Fence机制及其应用
    在Android 4.4中,Fence机制是处理缓冲区交换和同步问题的关键技术。该机制广泛应用于生产者-消费者模式中,确保了不同组件之间高效、安全的数据传输。通过深入解析Fence机制的工作原理和应用场景,本文探讨了其在系统性能优化和资源管理中的重要作用。 ... [详细]
  • WinMain 函数详解及示例
    本文详细介绍了 WinMain 函数的参数及其用途,并提供了一个具体的示例代码来解析 WinMain 函数的实现。 ... [详细]
  • [转]doc,ppt,xls文件格式转PDF格式http:blog.csdn.netlee353086articledetails7920355确实好用。需要注意的是#import ... [详细]
  • 本文详细介绍了如何在Unity中实现一个简单的广告牌着色器,帮助开发者更好地理解和应用这一技术。 ... [详细]
  • 字节流(InputStream和OutputStream),字节流读写文件,字节流的缓冲区,字节缓冲流
    字节流抽象类InputStream和OutputStream是字节流的顶级父类所有的字节输入流都继承自InputStream,所有的输出流都继承子OutputStreamInput ... [详细]
  • 本文详细介绍了 PHP 中对象的生命周期、内存管理和魔术方法的使用,包括对象的自动销毁、析构函数的作用以及各种魔术方法的具体应用场景。 ... [详细]
  • 在尝试对 QQmlPropertyMap 类进行测试驱动开发时,发现其派生类中无法正常调用槽函数或 Q_INVOKABLE 方法。这可能是由于 QQmlPropertyMap 的内部实现机制导致的,需要进一步研究以找到解决方案。 ... [详细]
  • 深入解析C语言中结构体的内存对齐机制及其优化方法
    为了提高CPU访问效率,C语言中的结构体成员在内存中遵循特定的对齐规则。本文详细解析了这些对齐机制,并探讨了如何通过合理的布局和编译器选项来优化结构体的内存使用,从而提升程序性能。 ... [详细]
  • 本文详细解析了使用C++实现的键盘输入记录程序的源代码,该程序在Windows应用程序开发中具有很高的实用价值。键盘记录功能不仅在远程控制软件中广泛应用,还为开发者提供了强大的调试和监控工具。通过具体实例,本文深入探讨了C++键盘记录程序的设计与实现,适合需要相关技术的开发者参考。 ... [详细]
  • 本文详细解析了 Android 系统启动过程中的核心文件 `init.c`,探讨了其在系统初始化阶段的关键作用。通过对 `init.c` 的源代码进行深入分析,揭示了其如何管理进程、解析配置文件以及执行系统启动脚本。此外,文章还介绍了 `init` 进程的生命周期及其与内核的交互方式,为开发者提供了深入了解 Android 启动机制的宝贵资料。 ... [详细]
  • 深入剖析Java中SimpleDateFormat在多线程环境下的潜在风险与解决方案
    深入剖析Java中SimpleDateFormat在多线程环境下的潜在风险与解决方案 ... [详细]
  • 在使用 Qt 进行 YUV420 图像渲染时,由于 Qt 本身不支持直接绘制 YUV 数据,因此需要借助 QOpenGLWidget 和 OpenGL 技术来实现。通过继承 QOpenGLWidget 类并重写其绘图方法,可以利用 GPU 的高效渲染能力,实现高质量的 YUV420 图像显示。此外,这种方法还能显著提高图像处理的性能和流畅性。 ... [详细]
  • 当使用 `new` 表达式(即通过 `new` 动态创建对象)时,会发生两件事:首先,内存被分配用于存储新对象;其次,该对象的构造函数被调用以初始化对象。为了确保资源管理的一致性和避免内存泄漏,建议在使用 `new` 和 `delete` 时保持形式一致。例如,如果使用 `new[]` 分配数组,则应使用 `delete[]` 来释放内存;同样,如果使用 `new` 分配单个对象,则应使用 `delete` 来释放内存。这种一致性有助于防止常见的编程错误,提高代码的健壮性和可维护性。 ... [详细]
  • 使用Maven JAR插件将单个或多个文件及其依赖项合并为一个可引用的JAR包
    本文介绍了如何利用Maven中的maven-assembly-plugin插件将单个或多个Java文件及其依赖项打包成一个可引用的JAR文件。首先,需要创建一个新的Maven项目,并将待打包的Java文件复制到该项目中。通过配置maven-assembly-plugin,可以实现将所有文件及其依赖项合并为一个独立的JAR包,方便在其他项目中引用和使用。此外,该方法还支持自定义装配描述符,以满足不同场景下的需求。 ... [详细]
author-avatar
辛勤的核桃4dr_797
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有