diff --git a/ffplay源码和书籍/ffdoc.pdf b/ffplay源码和书籍/ffdoc.pdf new file mode 100644 index 0000000..1687d5d Binary files /dev/null and b/ffplay源码和书籍/ffdoc.pdf differ diff --git a/ffplay源码和书籍/ffplay/CLOCKTXT_320.avi b/ffplay源码和书籍/ffplay/CLOCKTXT_320.avi new file mode 100644 index 0000000..931fd3e Binary files /dev/null and b/ffplay源码和书籍/ffplay/CLOCKTXT_320.avi differ diff --git a/ffplay源码和书籍/ffplay/Debug/SDL.dll b/ffplay源码和书籍/ffplay/Debug/SDL.dll new file mode 100644 index 0000000..69fd61e Binary files /dev/null and b/ffplay源码和书籍/ffplay/Debug/SDL.dll differ diff --git a/ffplay源码和书籍/ffplay/Debug/allcodecs.obj b/ffplay源码和书籍/ffplay/Debug/allcodecs.obj new file mode 100644 index 0000000..8ec29c2 Binary files /dev/null and b/ffplay源码和书籍/ffplay/Debug/allcodecs.obj differ diff --git a/ffplay源码和书籍/ffplay/Debug/allformats.obj b/ffplay源码和书籍/ffplay/Debug/allformats.obj new file mode 100644 index 0000000..bfaa384 Binary files /dev/null and b/ffplay源码和书籍/ffplay/Debug/allformats.obj differ diff --git a/ffplay源码和书籍/ffplay/Debug/avidec.obj b/ffplay源码和书籍/ffplay/Debug/avidec.obj new file mode 100644 index 0000000..85828a1 Binary files /dev/null and b/ffplay源码和书籍/ffplay/Debug/avidec.obj differ diff --git a/ffplay源码和书籍/ffplay/Debug/avio.obj b/ffplay源码和书籍/ffplay/Debug/avio.obj new file mode 100644 index 0000000..e7a373d Binary files /dev/null and b/ffplay源码和书籍/ffplay/Debug/avio.obj differ diff --git a/ffplay源码和书籍/ffplay/Debug/aviobuf.obj b/ffplay源码和书籍/ffplay/Debug/aviobuf.obj new file mode 100644 index 0000000..605dc97 Binary files /dev/null and b/ffplay源码和书籍/ffplay/Debug/aviobuf.obj differ diff --git a/ffplay源码和书籍/ffplay/Debug/cutils.obj b/ffplay源码和书籍/ffplay/Debug/cutils.obj new file mode 100644 index 0000000..edb3f6e Binary files /dev/null and b/ffplay源码和书籍/ffplay/Debug/cutils.obj differ diff --git a/ffplay源码和书籍/ffplay/Debug/dsputil.obj b/ffplay源码和书籍/ffplay/Debug/dsputil.obj new file mode 100644 index 0000000..fcfe077 Binary files /dev/null and b/ffplay源码和书籍/ffplay/Debug/dsputil.obj differ diff --git a/ffplay源码和书籍/ffplay/Debug/ffplay.Build.CppClean.log b/ffplay源码和书籍/ffplay/Debug/ffplay.Build.CppClean.log new file mode 100644 index 0000000..5cd9523 --- /dev/null +++ b/ffplay源码和书籍/ffplay/Debug/ffplay.Build.CppClean.log @@ -0,0 +1,26 @@ +e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\debug\vc120.pdb +e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\debug\vc120.idb +e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\debug\allcodecs.obj +e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\debug\dsputil.obj +e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\debug\imgconvert.obj +e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\debug\msrle.obj +e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\debug\truespeech.obj +e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\debug\utils_codec.obj +e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\debug\allformats.obj +e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\debug\avidec.obj +e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\debug\avio.obj +e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\debug\aviobuf.obj +e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\debug\cutils.obj +e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\debug\file.obj +e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\debug\utils_format.obj +e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\debug\ffplay.obj +e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\debug\ffplay.ilk +e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\debug\ffplay.exe +e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\debug\ffplay.pdb +e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\.\debug\ffplay.exe +e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\debug\ffplay.tlog\cl.command.1.tlog +e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\debug\ffplay.tlog\cl.read.1.tlog +e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\debug\ffplay.tlog\cl.write.1.tlog +e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\debug\ffplay.tlog\link.command.1.tlog +e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\debug\ffplay.tlog\link.read.1.tlog +e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\debug\ffplay.tlog\link.write.1.tlog diff --git a/ffplay源码和书籍/ffplay/Debug/ffplay.exe b/ffplay源码和书籍/ffplay/Debug/ffplay.exe new file mode 100644 index 0000000..569e8ea Binary files /dev/null and b/ffplay源码和书籍/ffplay/Debug/ffplay.exe differ diff --git a/ffplay源码和书籍/ffplay/Debug/ffplay.ilk b/ffplay源码和书籍/ffplay/Debug/ffplay.ilk new file mode 100644 index 0000000..da86e82 Binary files /dev/null and b/ffplay源码和书籍/ffplay/Debug/ffplay.ilk differ diff --git a/ffplay源码和书籍/ffplay/Debug/ffplay.log b/ffplay源码和书籍/ffplay/Debug/ffplay.log new file mode 100644 index 0000000..97c53b5 --- /dev/null +++ b/ffplay源码和书籍/ffplay/Debug/ffplay.log @@ -0,0 +1,68 @@ +生成启动时间为 2016/11/18 15:28:25。 + 1>项目“E:\Work\研究生工作\COStream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\ffplay.vcxproj”在节点 2 上(Rebuild 个目标)。 + 1>ClCompile: + D:\Program Files\Microsoft Visual Studio 12.0\VC\bin\CL.exe /c /ZI /nologo /W3 /WX- /Od /Oy- /D WIN32 /D _DEBUG /D _CONSOLE /D _VC80_UPGRADE=0x0600 /D _MBCS /Gm /EHsc /RTC1 /MTd /GS /Gy- /fp:precise /Zc:wchar_t /Zc:forScope /Fo".\Debug\\" /Fd".\Debug\vc120.pdb" /Gd /TC /analyze- /errorReport:prompt ffplay.c libavcodec\allcodecs.c libavcodec\dsputil.c libavcodec\imgconvert.c libavcodec\msrle.c libavcodec\truespeech.c libavcodec\utils_codec.c libavformat\allformats.c libavformat\avidec.c libavformat\avio.c libavformat\aviobuf.c libavformat\cutils.c libavformat\file.c libavformat\utils_format.c + utils_format.c + 1>e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\libavformat\utils_format.c(5): warning C4005: “UINT_MAX”: 宏重定义 + d:\program files\microsoft visual studio 12.0\vc\include\limits.h(41) : 参见“UINT_MAX”的前一个定义 + file.c + 1>e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\libavformat\file.c(31): warning C4996: '_open': This function or variable may be unsafe. Consider using _sopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. + d:\program files\microsoft visual studio 12.0\vc\include\io.h(237) : 参见“_open”的声明 + 1>e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\libavformat\file.c(41): warning C4996: 'read': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _read. See online help for details. + d:\program files\microsoft visual studio 12.0\vc\include\io.h(337) : 参见“read”的声明 + 1>e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\libavformat\file.c(47): warning C4996: 'write': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _write. See online help for details. + d:\program files\microsoft visual studio 12.0\vc\include\io.h(342) : 参见“write”的声明 + 1>e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\libavformat\file.c(53): warning C4244: “函数”: 从“offset_t”转换到“long”,可能丢失数据 + 1>e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\libavformat\file.c(53): warning C4996: 'lseek': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _lseek. See online help for details. + d:\program files\microsoft visual studio 12.0\vc\include\io.h(334) : 参见“lseek”的声明 + 1>e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\libavformat\file.c(59): warning C4996: 'close': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _close. See online help for details. + d:\program files\microsoft visual studio 12.0\vc\include\io.h(326) : 参见“close”的声明 + cutils.c + aviobuf.c + avio.c + 1>e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\libavformat\avio.c(41): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. + d:\program files\microsoft visual studio 12.0\vc\include\string.h(112) : 参见“strcpy”的声明 + 1>e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\libavformat\avio.c(64): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. + d:\program files\microsoft visual studio 12.0\vc\include\string.h(112) : 参见“strcpy”的声明 + avidec.c + 1>e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\libavformat\avidec.c(121): warning C4244: “函数”: 从“int64_t”转换到“int”,可能丢失数据 + 1>e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\libavformat\avidec.c(325): warning C4018: “>”: 有符号/无符号不匹配 + 1>e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\libavformat\avidec.c(642): warning C4244: “+=”: 从“int64_t”转换到“unsigned int”,可能丢失数据 + 1>e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\libavformat\avidec.c(646): warning C4018: “>=”: 有符号/无符号不匹配 + allformats.c + utils_codec.c + truespeech.c + msrle.c + imgconvert.c + 1>e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\libavcodec\imgconvert.c(1091): warning C4146: 一元负运算符应用于无符号类型,结果仍为无符号类型 + 1>e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\libavcodec\imgconvert_template.h(465): warning C4146: 一元负运算符应用于无符号类型,结果仍为无符号类型 + 1>e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\libavcodec\imgconvert_template.h(859): warning C4146: 一元负运算符应用于无符号类型,结果仍为无符号类型 + dsputil.c + allcodecs.c + ffplay.c + 1>e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\ffplay.c(93): warning C4996: '_ftime64': This function or variable may be unsafe. Consider using _ftime64_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. + d:\program files\microsoft visual studio 12.0\vc\include\sys\timeb.h(131) : 参见“_ftime64”的声明 + 1>e:\work\研究生工作\costream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\ffplay.c(376): warning C4018: “>=”: 有符号/无符号不匹配 + 正在生成代码... + Link: + D:\Program Files\Microsoft Visual Studio 12.0\VC\bin\link.exe /ERRORREPORT:PROMPT /OUT:".\Debug\ffplay.exe" /INCREMENTAL /NOLOGO /LIBPATH:"E:\Work\SDL-1.2.15\lib\x86" odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /MANIFEST /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /manifest:embed /DEBUG /PDB:".\Debug\ffplay.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:".\Debug\ffplay.lib" /MACHINE:X86 /SAFESEH .\Debug\ffplay.obj + .\Debug\allcodecs.obj + .\Debug\dsputil.obj + .\Debug\imgconvert.obj + .\Debug\msrle.obj + .\Debug\truespeech.obj + .\Debug\utils_codec.obj + .\Debug\allformats.obj + .\Debug\avidec.obj + .\Debug\avio.obj + .\Debug\aviobuf.obj + .\Debug\cutils.obj + .\Debug\file.obj + .\Debug\utils_format.obj + 1>ffplay.obj : warning LNK4075: 忽略“/EDITANDCONTINUE”(由于“/SAFESEH”规范) + ffplay.vcxproj -> E:\Work\研究生工作\COStream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\.\Debug\ffplay.exe + 1>已完成生成项目“E:\Work\研究生工作\COStream以及视频编码工程\音视频编解码的书籍\ffplay源码和书籍\ffplay\ffplay.vcxproj”(Rebuild 个目标)的操作。 + +生成成功。 + +已用时间 00:00:01.76 diff --git a/ffplay源码和书籍/ffplay/Debug/ffplay.obj b/ffplay源码和书籍/ffplay/Debug/ffplay.obj new file mode 100644 index 0000000..c390c1e Binary files /dev/null and b/ffplay源码和书籍/ffplay/Debug/ffplay.obj differ diff --git a/ffplay源码和书籍/ffplay/Debug/ffplay.pdb b/ffplay源码和书籍/ffplay/Debug/ffplay.pdb new file mode 100644 index 0000000..3b9a298 Binary files /dev/null and b/ffplay源码和书籍/ffplay/Debug/ffplay.pdb differ diff --git a/ffplay源码和书籍/ffplay/Debug/ffplay.tlog/CL.read.1.tlog b/ffplay源码和书籍/ffplay/Debug/ffplay.tlog/CL.read.1.tlog new file mode 100644 index 0000000..4b4fe85 Binary files /dev/null and b/ffplay源码和书籍/ffplay/Debug/ffplay.tlog/CL.read.1.tlog differ diff --git a/ffplay源码和书籍/ffplay/Debug/ffplay.tlog/CL.write.1.tlog b/ffplay源码和书籍/ffplay/Debug/ffplay.tlog/CL.write.1.tlog new file mode 100644 index 0000000..861d0aa Binary files /dev/null and b/ffplay源码和书籍/ffplay/Debug/ffplay.tlog/CL.write.1.tlog differ diff --git a/ffplay源码和书籍/ffplay/Debug/ffplay.tlog/cl.command.1.tlog b/ffplay源码和书籍/ffplay/Debug/ffplay.tlog/cl.command.1.tlog new file mode 100644 index 0000000..546cfb4 Binary files /dev/null and b/ffplay源码和书籍/ffplay/Debug/ffplay.tlog/cl.command.1.tlog differ diff --git a/ffplay源码和书籍/ffplay/Debug/ffplay.tlog/ffplay.lastbuildstate b/ffplay源码和书籍/ffplay/Debug/ffplay.tlog/ffplay.lastbuildstate new file mode 100644 index 0000000..42ba68a --- /dev/null +++ b/ffplay源码和书籍/ffplay/Debug/ffplay.tlog/ffplay.lastbuildstate @@ -0,0 +1,2 @@ +#TargetFrameworkVersion=v4.0:PlatformToolSet=v120:EnableManagedIncrementalBuild=false:VCToolArchitecture=Native32Bit +Debug|Win32|E:\Work\研究生工作\COStream以及视频编码工程\HomerHEVC\HomerHEVC\xHEVC\| diff --git a/ffplay源码和书籍/ffplay/Debug/ffplay.tlog/link.command.1.tlog b/ffplay源码和书籍/ffplay/Debug/ffplay.tlog/link.command.1.tlog new file mode 100644 index 0000000..f0567ff Binary files /dev/null and b/ffplay源码和书籍/ffplay/Debug/ffplay.tlog/link.command.1.tlog differ diff --git a/ffplay源码和书籍/ffplay/Debug/ffplay.tlog/link.read.1.tlog b/ffplay源码和书籍/ffplay/Debug/ffplay.tlog/link.read.1.tlog new file mode 100644 index 0000000..f5d19f2 Binary files /dev/null and b/ffplay源码和书籍/ffplay/Debug/ffplay.tlog/link.read.1.tlog differ diff --git a/ffplay源码和书籍/ffplay/Debug/ffplay.tlog/link.write.1.tlog b/ffplay源码和书籍/ffplay/Debug/ffplay.tlog/link.write.1.tlog new file mode 100644 index 0000000..f24f550 Binary files /dev/null and b/ffplay源码和书籍/ffplay/Debug/ffplay.tlog/link.write.1.tlog differ diff --git a/ffplay源码和书籍/ffplay/Debug/file.obj b/ffplay源码和书籍/ffplay/Debug/file.obj new file mode 100644 index 0000000..807a28b Binary files /dev/null and b/ffplay源码和书籍/ffplay/Debug/file.obj differ diff --git a/ffplay源码和书籍/ffplay/Debug/imgconvert.obj b/ffplay源码和书籍/ffplay/Debug/imgconvert.obj new file mode 100644 index 0000000..89b5dce Binary files /dev/null and b/ffplay源码和书籍/ffplay/Debug/imgconvert.obj differ diff --git a/ffplay源码和书籍/ffplay/Debug/msrle.obj b/ffplay源码和书籍/ffplay/Debug/msrle.obj new file mode 100644 index 0000000..1caa67a Binary files /dev/null and b/ffplay源码和书籍/ffplay/Debug/msrle.obj differ diff --git a/ffplay源码和书籍/ffplay/Debug/truespeech.obj b/ffplay源码和书籍/ffplay/Debug/truespeech.obj new file mode 100644 index 0000000..a757aa3 Binary files /dev/null and b/ffplay源码和书籍/ffplay/Debug/truespeech.obj differ diff --git a/ffplay源码和书籍/ffplay/Debug/utils_codec.obj b/ffplay源码和书籍/ffplay/Debug/utils_codec.obj new file mode 100644 index 0000000..7ca6a67 Binary files /dev/null and b/ffplay源码和书籍/ffplay/Debug/utils_codec.obj differ diff --git a/ffplay源码和书籍/ffplay/Debug/utils_format.obj b/ffplay源码和书籍/ffplay/Debug/utils_format.obj new file mode 100644 index 0000000..4686245 Binary files /dev/null and b/ffplay源码和书籍/ffplay/Debug/utils_format.obj differ diff --git a/ffplay源码和书籍/ffplay/Debug/vc120.idb b/ffplay源码和书籍/ffplay/Debug/vc120.idb new file mode 100644 index 0000000..bd87b9f Binary files /dev/null and b/ffplay源码和书籍/ffplay/Debug/vc120.idb differ diff --git a/ffplay源码和书籍/ffplay/Debug/vc120.pdb b/ffplay源码和书籍/ffplay/Debug/vc120.pdb new file mode 100644 index 0000000..f90b8be Binary files /dev/null and b/ffplay源码和书籍/ffplay/Debug/vc120.pdb differ diff --git a/ffplay源码和书籍/ffplay/berrno.h b/ffplay源码和书籍/ffplay/berrno.h new file mode 100644 index 0000000..b30c538 --- /dev/null +++ b/ffplay源码和书籍/ffplay/berrno.h @@ -0,0 +1,40 @@ +#ifndef BERRNO_H +#define BERRNO_H + +/* õĴ Ҳʾжϴźŵȣ*/ +#ifdef ENOENT +#undef ENOENT +#endif +#define ENOENT 2 + +#ifdef EINTR +#undef EINTR +#endif +#define EINTR 4 + +#ifdef EIO +#undef EIO +#endif +#define EIO 5 + +#ifdef EAGAIN +#undef EAGAIN +#endif +#define EAGAIN 11 + +#ifdef ENOMEM +#undef ENOMEM +#endif +#define ENOMEM 12 + +#ifdef EINVAL +#undef EINVAL +#endif +#define EINVAL 22 + +#ifdef EPIPE +#undef EPIPE +#endif +#define EPIPE 32 + +#endif diff --git a/ffplay源码和书籍/ffplay/ffplay.c b/ffplay源码和书籍/ffplay/ffplay.c new file mode 100644 index 0000000..60a0aa9 --- /dev/null +++ b/ffplay源码和书籍/ffplay/ffplay.c @@ -0,0 +1,801 @@ +#include "./libavformat/avformat.h" + +#if defined(CONFIG_WIN32) +#include +#include +#include +#else +#include +#include +#endif + +#include + +#include +#include +#include + +#ifdef CONFIG_WIN32 +#undef main // We don't want SDL to override our main() +#endif + +#pragma comment(lib, "SDL.lib") + +/* ˳¼ */ +#define FF_QUIT_EVENT (SDL_USEREVENT + 2) + +/* Ƶе */ +#define MAX_VIDEOQ_SIZE (5 * 256 * 1024) +/* Ƶе󳤶 */ +#define MAX_AUDIOQ_SIZE (5 * 16 * 1024) + +/* ͼеij */ +#define VIDEO_PICTURE_QUEUE_SIZE 1 + +/* ݰ */ +typedef struct PacketQueue +{ + // ͷָβָ + AVPacketList *first_pkt, *last_pkt; + // г + int size; + // ж + int abort_request; + // + SDL_mutex *mutex; + // + SDL_cond *cond; +} PacketQueue; + +/* Ƶͼ */ +typedef struct VideoPicture +{ + // ʾ + SDL_Overlay *bmp; + // + int width, height; // source height & width +} VideoPicture; + +/* Ƶ״̬ */ +typedef struct VideoState +{ + // ߳ + SDL_Thread *parse_tid; + // Ƶ߳ + SDL_Thread *video_tid; + + // ж + int abort_request; + + // ʾһģ߱ʾһļģ + AVFormatContext *ic; + + int audio_stream; + int video_stream; + + // Ƶ + AVStream *audio_st; + // Ƶ + AVStream *video_st; + + // Ƶ + PacketQueue audioq; + // Ƶ + PacketQueue videoq; + + // Ŷ + VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE]; + double frame_last_delay; + + uint8_t audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE *3) / 2]; + unsigned int audio_buf_size; + int audio_buf_index; + + // Ƶݰ + AVPacket audio_pkt; + + // Ƶݺͳ + uint8_t *audio_pkt_data; + int audio_pkt_size; + + // Ƶ + SDL_mutex *video_decoder_mutex; + // Ƶ + SDL_mutex *audio_decoder_mutex; + + // Ƶļ + char filename[240]; + +} VideoState; + +static AVInputFormat *file_iformat; +static const char *input_filename; +static VideoState *cur_stream; + +static SDL_Surface *screen; +/* ȡǰʱ */ +int64_t av_gettime(void) +{ +#if defined(CONFIG_WINCE) + return timeGetTime() *int64_t_C(1000); +#elif defined(CONFIG_WIN32) + struct _timeb tb; + _ftime(&tb); + return ((int64_t)tb.time *int64_t_C(1000) + (int64_t)tb.millitm) *int64_t_C(1000); +#else + struct timeval tv; + gettimeofday(&tv, NULL); + return (int64_t)tv.tv_sec *1000000+tv.tv_usec; +#endif +} + +/* ݰгʼ */ +static void packet_queue_init(PacketQueue *q) // packet queue handling +{ + memset(q, 0, sizeof(PacketQueue)); + // + q->mutex = SDL_CreateMutex(); + // + q->cond = SDL_CreateCond(); +} + +/* ˢݰУͷݰ */ +static void packet_queue_flush(PacketQueue *q) +{ + AVPacketList *pkt, *pkt1; + + SDL_LockMutex(q->mutex); + for (pkt = q->first_pkt; pkt != NULL; pkt = pkt1) + { + pkt1 = pkt->next; + av_free_packet(&pkt->pkt); + av_freep(&pkt); + } + q->last_pkt = NULL; + q->first_pkt = NULL; + q->size = 0; + SDL_UnlockMutex(q->mutex); +} + +/* ݰ */ +static void packet_queue_end(PacketQueue *q) +{ + packet_queue_flush(q); + SDL_DestroyMutex(q->mutex); + SDL_DestroyCond(q->cond); +} + +/* ݰѹһݰ */ +static int packet_queue_put(PacketQueue *q, AVPacket *pkt) +{ + AVPacketList *pkt1; + + pkt1 = av_malloc(sizeof(AVPacketList)); + if (!pkt1) + return - 1; + pkt1->pkt = *pkt; + pkt1->next = NULL; + + SDL_LockMutex(q->mutex); + + if (!q->last_pkt) + q->first_pkt = pkt1; + else + q->last_pkt->next = pkt1; + q->last_pkt = pkt1; + q->size += pkt1->pkt.size; + + SDL_CondSignal(q->cond); + + SDL_UnlockMutex(q->mutex); + return 0; +} + +/* ˳ */ +static void packet_queue_abort(PacketQueue *q) +{ + SDL_LockMutex(q->mutex); + + q->abort_request = 1; + + SDL_CondSignal(q->cond); + + SDL_UnlockMutex(q->mutex); +} + +/* return < 0 if aborted, 0 if no packet and > 0 if packet. */ +/* Ӷȡһݰ */ +static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block) +{ + AVPacketList *pkt1; + int ret; + + SDL_LockMutex(q->mutex); + + for (;;) + { + if (q->abort_request) + { + ret = - 1; // 쳣 + break; + } + + pkt1 = q->first_pkt; + if (pkt1) + { + q->first_pkt = pkt1->next; + if (!q->first_pkt) + q->last_pkt = NULL; + q->size -= pkt1->pkt.size; + *pkt = pkt1->pkt; + av_free(pkt1); + ret = 1; + break; + } + else if (!block)// ǣ1(ģʽ)0(ģʽ) + { + ret = 0; // ģʽûֱӷ0 + break; + } + else + { + SDL_CondWait(q->cond, q->mutex); + } + } + SDL_UnlockMutex(q->mutex); + return ret; +} + +/* һVideoPicture */ +static void alloc_picture(void *opaque) +{ + VideoState *is = opaque; + VideoPicture *vp; + + vp = &is->pictq[0]; + + if (vp->bmp) + SDL_FreeYUVOverlay(vp->bmp); + + vp->bmp = SDL_CreateYUVOverlay(is->video_st->actx->width, + is->video_st->actx->height, + SDL_YV12_OVERLAY, + screen); + + vp->width = is->video_st->actx->width; + vp->height = is->video_st->actx->height; +} + +/* ʾͼ */ +static int video_display(VideoState *is, AVFrame *src_frame, double pts) +{ + VideoPicture *vp; + int dst_pix_fmt; + AVPicture pict; + + if (is->videoq.abort_request) + return - 1; + + vp = &is->pictq[0]; + + /* if the frame is not skipped, then display it */ + if (vp->bmp) + { + SDL_Rect rect; + + if (pts) + Sleep((int)(is->frame_last_delay *1000)); +#if 1 + /* get a pointer on the bitmap */ + SDL_LockYUVOverlay(vp->bmp); + + dst_pix_fmt = PIX_FMT_YUV420P; + pict.data[0] = vp->bmp->pixels[0]; + pict.data[1] = vp->bmp->pixels[2]; + pict.data[2] = vp->bmp->pixels[1]; + + pict.linesize[0] = vp->bmp->pitches[0]; + pict.linesize[1] = vp->bmp->pitches[2]; + pict.linesize[2] = vp->bmp->pitches[1]; + + img_convert(&pict, + dst_pix_fmt, + (AVPicture*)src_frame, + is->video_st->actx->pix_fmt, + is->video_st->actx->width, + is->video_st->actx->height); + + SDL_UnlockYUVOverlay(vp->bmp); /* update the bitmap content */ + + rect.x = 0; + rect.y = 0; + rect.w = is->video_st->actx->width; + rect.h = is->video_st->actx->height; + SDL_DisplayYUVOverlay(vp->bmp, &rect); +#endif + } + return 0; +} + +/* Ƶ߳ ߽*/ +static int video_thread(void *arg) +{ + VideoState *is = arg; + AVPacket pkt1, *pkt = &pkt1; + int len1, got_picture; + double pts = 0; + + // һ֡ + AVFrame *frame = av_malloc(sizeof(AVFrame)); + memset(frame, 0, sizeof(AVFrame)); + + alloc_picture(is); + + // ѭ + for (;;) + { + // ȡһݰ + if (packet_queue_get(&is->videoq, pkt, 1) < 0) + break; + + // Ȼ룬Ȼ + SDL_LockMutex(is->video_decoder_mutex); + len1 = avcodec_decode_video(is->video_st->actx, frame, &got_picture, pkt->data, pkt->size); + SDL_UnlockMutex(is->video_decoder_mutex); + + // + if (pkt->dts != AV_NOPTS_VALUE) + pts = av_q2d(is->video_st->time_base) *pkt->dts; + + // ʾ֡ + if (got_picture) + { + if (video_display(is, frame, pts) < 0) + goto the_end; + } + av_free_packet(pkt); + } + +the_end: + av_free(frame); + return 0; +} + +/* decode one audio frame and returns its uncompressed size */ +static int audio_decode_frame(VideoState *is, uint8_t *audio_buf, double *pts_ptr) +{ + AVPacket *pkt = &is->audio_pkt; + int len1, data_size; + + for (;;) + { + /* NOTE: the audio packet can contain several frames */ + while (is->audio_pkt_size > 0) + { + SDL_LockMutex(is->audio_decoder_mutex); + len1 = avcodec_decode_audio(is->audio_st->actx, (int16_t*)audio_buf, + &data_size, is->audio_pkt_data, is->audio_pkt_size); + + SDL_UnlockMutex(is->audio_decoder_mutex); + if (len1 < 0) + { + /* if error, we skip the frame */ + is->audio_pkt_size = 0; + break; + } + + is->audio_pkt_data += len1; + is->audio_pkt_size -= len1; + if (data_size <= 0) + continue; + + return data_size; + } + + /* free the current packet */ + if (pkt->data) + av_free_packet(pkt); + + /* read next packet */ + if (packet_queue_get(&is->audioq, pkt, 1) < 0) + return - 1; + + is->audio_pkt_data = pkt->data; + is->audio_pkt_size = pkt->size; + } +} + +/* prepare a new audio buffer */ +void sdl_audio_callback(void *opaque, Uint8 *stream, int len) +{ + VideoState *is = opaque; + int audio_size, len1; + double pts = 0; + + while (len > 0) + { + if (is->audio_buf_index >= is->audio_buf_size) + { + audio_size = audio_decode_frame(is, is->audio_buf, &pts); + if (audio_size < 0) + { + /* if error, just output silence */ + is->audio_buf_size = 1024; + memset(is->audio_buf, 0, is->audio_buf_size); + } + else + { +// audio_size = synchronize_audio(is, (int16_t*)is->audio_buf, audio_size, pts); + is->audio_buf_size = audio_size; + } + is->audio_buf_index = 0; + } + len1 = is->audio_buf_size - is->audio_buf_index; + if (len1 > len) + len1 = len; + memcpy(stream, (uint8_t*)is->audio_buf + is->audio_buf_index, len1); + len -= len1; + stream += len1; + is->audio_buf_index += len1; + } +} + +/* open a given stream. Return 0 if OK */ +/* һƵƵ ߳ȥ */ +static int stream_component_open(VideoState *is, int stream_index) +{ + AVFormatContext *ic = is->ic; + AVCodecContext *enc; + AVCodec *codec; + SDL_AudioSpec wanted_spec, spec; + + if (stream_index < 0 || stream_index >= ic->nb_streams) + return - 1; + + enc = ic->streams[stream_index]->actx; + + /* prepare audio output */ + /* Ƶ */ + if (enc->codec_type == CODEC_TYPE_AUDIO) + { + wanted_spec.freq = enc->sample_rate; + wanted_spec.format = AUDIO_S16SYS; + /* hack for AC3. XXX: suppress that */ + if (enc->channels > 2) + enc->channels = 2; + wanted_spec.channels = enc->channels; + wanted_spec.silence = 0; + wanted_spec.samples = 1024; //SDL_AUDIO_BUFFER_SIZE; + wanted_spec.callback = sdl_audio_callback; + wanted_spec.userdata = is; + if (SDL_OpenAudio(&wanted_spec, &spec) < 0) + { + fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError()); + return - 1; + } + } + + // һ + codec = avcodec_find_decoder(enc->codec_id); + + // 򿪱 + if (!codec || avcodec_open(enc, codec) < 0) + return - 1; + + switch (enc->codec_type) + { + case CODEC_TYPE_AUDIO: // Ƶ + is->audio_stream = stream_index; + is->audio_st = ic->streams[stream_index]; + is->audio_buf_size = 0; + is->audio_buf_index = 0; + + memset(&is->audio_pkt, 0, sizeof(is->audio_pkt)); + packet_queue_init(&is->audioq); + SDL_PauseAudio(0); + break; + case CODEC_TYPE_VIDEO: + is->video_stream = stream_index; + is->video_st = ic->streams[stream_index]; + + is->frame_last_delay = is->video_st->frame_last_delay; + + packet_queue_init(&is->videoq); // гʼ + is->video_tid = SDL_CreateThread(video_thread, is); // Ƶ߳ȥ + break; + default: + break; + } + return 0; +} + +static void stream_component_close(VideoState *is, int stream_index) +{ + AVFormatContext *ic = is->ic; + AVCodecContext *enc; + + if (stream_index < 0 || stream_index >= ic->nb_streams) + return ; + enc = ic->streams[stream_index]->actx; + + switch (enc->codec_type) + { + case CODEC_TYPE_AUDIO: + packet_queue_abort(&is->audioq); + SDL_CloseAudio(); + packet_queue_end(&is->audioq); + break; + case CODEC_TYPE_VIDEO: + packet_queue_abort(&is->videoq); + SDL_WaitThread(is->video_tid, NULL); + packet_queue_end(&is->videoq); + break; + default: + break; + } + + avcodec_close(enc); +} + +/* ߳ */ +static int decode_thread(void *arg) +{ + VideoState *is = arg; + AVFormatContext *ic; + int err, i, ret, video_index, audio_index; + AVPacket pkt1, *pkt = &pkt1; + AVFormatParameters params, *ap = ¶ms; + + int flags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL | SDL_RESIZABLE; + + video_index = - 1; + audio_index = - 1; + + is->video_stream = - 1; + is->audio_stream = - 1; + + memset(ap, 0, sizeof(*ap)); + + // ļϢ䵽IOĶ + err = av_open_input_file(&ic, is->filename, NULL, 0, ap); + if (err < 0) + { + ret = - 1; + goto fail; + } + is->ic = ic; + + // + for (i = 0; i < ic->nb_streams; i++) + { + // + AVCodecContext *enc = ic->streams[i]->actx; + + // + switch (enc->codec_type) + { + case CODEC_TYPE_AUDIO: // Ƶ + if (audio_index < 0) + audio_index = i; + break; + case CODEC_TYPE_VIDEO: // Ƶ + if (video_index < 0) + video_index = i; + + // ƵģʽõĻ + screen = SDL_SetVideoMode(enc->width, enc->height, 0, flags); + + SDL_WM_SetCaption("FFplay", "FFplay"); // ޸ΪƵС + +// schedule_refresh(is, 40); + break; + default: + break; + } + } + + // 򿪸ijɷ֣÷߳ + if (audio_index >= 0) + stream_component_open(is, audio_index); + + // ĸɷ֣÷߳ + if (video_index >= 0) + stream_component_open(is, video_index); + + if (is->video_stream < 0 && is->audio_stream < 0) + { + fprintf(stderr, "%s: could not open codecs\n", is->filename); + ret = - 1; + goto fail; + } + + // ѭ + for (;;) + { + if (is->abort_request) + break; + + // Ѿˣôӳȥ + if (is->audioq.size > MAX_AUDIOQ_SIZE || is->videoq.size > MAX_VIDEOQ_SIZE || url_feof(&ic->pb)) + { + SDL_Delay(10); // if the queue are full, no need to read more,wait 10 ms + continue; + } + + // ȡһݰʾһ֡ + ret = av_read_packet(ic, pkt); //av_read_frame(ic, pkt); + if (ret < 0) + { + if (url_ferror(&ic->pb) == 0) + { + SDL_Delay(100); // wait for user event + continue; + } + else + break; + } + + // ݰӵ + if (pkt->stream_index == is->audio_stream) + { + packet_queue_put(&is->audioq, pkt); + } + else if (pkt->stream_index == is->video_stream) + { + packet_queue_put(&is->videoq, pkt); + } + else + { + av_free_packet(pkt); + } + } + + while (!is->abort_request) // wait until the end + { + SDL_Delay(100); + } + + ret = 0; + +fail: + if (is->audio_stream >= 0) + stream_component_close(is, is->audio_stream); + + if (is->video_stream >= 0) + stream_component_close(is, is->video_stream); + + if (is->ic) + { + av_close_input_file(is->ic); + is->ic = NULL; + } + + if (ret != 0) + { + SDL_Event event; + + event.type = FF_QUIT_EVENT; + event.user.data1 = is; + SDL_PushEvent(&event); + } + return 0; +} + +/* ļ */ +static VideoState *stream_open(const char *filename, AVInputFormat *iformat) +{ + // Ƶ״̬ + VideoState *is; + + is = av_mallocz(sizeof(VideoState)); + if (!is) + return NULL; + pstrcpy(is->filename, sizeof(is->filename), filename); + + // Ƶ + is->audio_decoder_mutex = SDL_CreateMutex(); + // Ƶ + is->video_decoder_mutex = SDL_CreateMutex(); + + // ߳ + is->parse_tid = SDL_CreateThread(decode_thread, is); + if (!is->parse_tid) + { + av_free(is); + return NULL; + } + return is; +} + +static void stream_close(VideoState *is) +{ + VideoPicture *vp; + int i; + + is->abort_request = 1; + SDL_WaitThread(is->parse_tid, NULL); + + for (i = 0; i < VIDEO_PICTURE_QUEUE_SIZE; i++) + { + vp = &is->pictq[i]; + if (vp->bmp) + { + SDL_FreeYUVOverlay(vp->bmp); + vp->bmp = NULL; + } + } + + SDL_DestroyMutex(is->audio_decoder_mutex); + SDL_DestroyMutex(is->video_decoder_mutex); +} + +void do_exit(void) +{ + if (cur_stream) + { + stream_close(cur_stream); + cur_stream = NULL; + } + + SDL_Quit(); + exit(0); +} + +void event_loop(void) // handle an event sent by the GUI +{ + SDL_Event event; + + for (;;) + { + SDL_WaitEvent(&event); + switch (event.type) + { + case SDL_KEYDOWN: + switch (event.key.keysym.sym) + { + case SDLK_ESCAPE: + case SDLK_q: + do_exit(); + break; + default: + break; + } + break; + case SDL_QUIT: + case FF_QUIT_EVENT: + do_exit(); + break; + default: + break; + } + } +} + +int main(int argc, char **argv) +{ + int flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER; + + // עֵ֧ĸʽ + av_register_all(); + + // ļ + input_filename = "clocktxt_320.avi"; +// input_filename = "d:/yuv/clocktxt.avi"; + + // sdlʼsdlһƽ̨ý忪⣩ + if (SDL_Init(flags)) + exit(1); + + // ע߼¼¼¼windowsϵͳϢû¼ + SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE); + SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE); + SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE); + SDL_EventState(SDL_USEREVENT, SDL_IGNORE); + + // + cur_stream = stream_open(input_filename, file_iformat); + + event_loop(); + + return 0; +} diff --git a/ffplay源码和书籍/ffplay/ffplay.dsp b/ffplay源码和书籍/ffplay/ffplay.dsp new file mode 100644 index 0000000..9260703 --- /dev/null +++ b/ffplay源码和书籍/ffplay/ffplay.dsp @@ -0,0 +1,201 @@ +# Microsoft Developer Studio Project File - Name="ffplay" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=ffplay - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ffplay.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ffplay.mak" CFG="ffplay - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ffplay - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "ffplay - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ffplay - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x804 /d "NDEBUG" +# ADD RSC /l 0x804 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "ffplay - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x804 /d "_DEBUG" +# ADD RSC /l 0x804 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "ffplay - Win32 Release" +# Name "ffplay - Win32 Debug" +# Begin Group "libavcodec" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\libavcodec\allcodecs.c +# End Source File +# Begin Source File + +SOURCE=.\libavcodec\avcodec.h +# End Source File +# Begin Source File + +SOURCE=.\libavcodec\dsputil.c +# End Source File +# Begin Source File + +SOURCE=.\libavcodec\dsputil.h +# End Source File +# Begin Source File + +SOURCE=.\libavcodec\imgconvert.c +# End Source File +# Begin Source File + +SOURCE=.\libavcodec\imgconvert_template.h +# End Source File +# Begin Source File + +SOURCE=.\libavcodec\msrle.c +# End Source File +# Begin Source File + +SOURCE=.\libavcodec\truespeech.c +# End Source File +# Begin Source File + +SOURCE=.\libavcodec\truespeech_data.h +# End Source File +# Begin Source File + +SOURCE=.\libavcodec\utils_codec.c +# End Source File +# End Group +# Begin Group "libavformat" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\libavformat\allformats.c +# End Source File +# Begin Source File + +SOURCE=.\libavformat\avformat.h +# End Source File +# Begin Source File + +SOURCE=.\libavformat\avidec.c +# End Source File +# Begin Source File + +SOURCE=.\libavformat\avio.c +# End Source File +# Begin Source File + +SOURCE=.\libavformat\avio.h +# End Source File +# Begin Source File + +SOURCE=.\libavformat\aviobuf.c +# End Source File +# Begin Source File + +SOURCE=.\libavformat\cutils.c +# End Source File +# Begin Source File + +SOURCE=.\libavformat\file.c +# End Source File +# Begin Source File + +SOURCE=.\libavformat\utils_format.c +# End Source File +# End Group +# Begin Group "libavutil" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\libavutil\avutil.h +# End Source File +# Begin Source File + +SOURCE=.\libavutil\bswap.h +# End Source File +# Begin Source File + +SOURCE=.\libavutil\common.h +# End Source File +# Begin Source File + +SOURCE=.\libavutil\mathematics.h +# End Source File +# Begin Source File + +SOURCE=.\libavutil\rational.h +# End Source File +# End Group +# Begin Source File + +SOURCE=.\berrno.h +# End Source File +# Begin Source File + +SOURCE=.\ffplay.c +# End Source File +# End Target +# End Project diff --git a/ffplay源码和书籍/ffplay/ffplay.vcxproj b/ffplay源码和书籍/ffplay/ffplay.vcxproj new file mode 100644 index 0000000..9ce8f0f --- /dev/null +++ b/ffplay源码和书籍/ffplay/ffplay.vcxproj @@ -0,0 +1,157 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + {F914CB69-0432-4937-87FD-D02757DD4B64} + + + + Application + v120 + false + MultiByte + + + Application + v120 + false + MultiByte + + + + + + + + + + + + + + + .\Release\ + .\Release\ + false + + + .\Debug\ + .\Debug\ + true + E:\Work\SDL-1.2.15\include;$(IncludePath) + E:\Work\SDL-1.2.15\lib\x86;$(LibraryPath) + + + + MultiThreaded + Default + false + Disabled + true + Level3 + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + .\Release\ + .\Release\ffplay.pch + .\Release\ + .\Release\ + + + .\Release\ffplay.tlb + + + 0x0804 + NDEBUG;%(PreprocessorDefinitions) + + + true + .\Release\ffplay.bsc + + + true + Console + .\Release\ffplay.exe + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + MultiThreadedDebug + Default + false + Disabled + true + Level3 + true + EditAndContinue + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + .\Debug\ + .\Debug\ffplay.pch + .\Debug\ + .\Debug\ + EnableFastChecks + + + .\Debug\ffplay.tlb + + + 0x0804 + _DEBUG;%(PreprocessorDefinitions) + + + true + .\Debug\ffplay.bsc + + + true + true + Console + .\Debug\ffplay.exe + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + E:\Work\SDL-1.2.15\lib\x86;%(AdditionalLibraryDirectories) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ffplay源码和书籍/ffplay/ffplay.vcxproj.filters b/ffplay源码和书籍/ffplay/ffplay.vcxproj.filters new file mode 100644 index 0000000..6b7c1e5 --- /dev/null +++ b/ffplay源码和书籍/ffplay/ffplay.vcxproj.filters @@ -0,0 +1,92 @@ + + + + + {94bac1c7-3a5d-4c5c-9ada-d7f42de7259f} + + + {d17f4d25-f28a-4175-92be-4834f6481e36} + + + {e95c5c62-22fc-4e57-8867-b02483bd60f4} + + + + + libavcodec + + + libavcodec + + + libavcodec + + + libavcodec + + + libavcodec + + + libavcodec + + + libavformat + + + libavformat + + + libavformat + + + libavformat + + + libavformat + + + libavformat + + + libavformat + + + + + + libavcodec + + + libavcodec + + + libavcodec + + + libavcodec + + + libavformat + + + libavformat + + + libavutil + + + libavutil + + + libavutil + + + libavutil + + + libavutil + + + + \ No newline at end of file diff --git a/ffplay源码和书籍/ffplay/libavcodec/allcodecs.c b/ffplay源码和书籍/ffplay/libavcodec/allcodecs.c new file mode 100644 index 0000000..72325ca --- /dev/null +++ b/ffplay源码和书籍/ffplay/libavcodec/allcodecs.c @@ -0,0 +1,25 @@ +#include "avcodec.h" + +/************************************************************************/ +/* 򵥵ע/ʼѱӦڲʶ */ +/************************************************************************/ + +/* ȫֵı */ +extern AVCodec truespeech_decoder; +extern AVCodec msrle_decoder; + +/* עеı */ +void avcodec_register_all(void) +{ + static int inited = 0; + + if (inited != 0) + return ; + + inited = 1; + + // 򻯰ffmpegֱֻ֧뷽ʽMSRLEtruespeech + register_avcodec(&msrle_decoder); + + register_avcodec(&truespeech_decoder); +} diff --git a/ffplay源码和书籍/ffplay/libavcodec/avcodec.h b/ffplay源码和书籍/ffplay/libavcodec/avcodec.h new file mode 100644 index 0000000..8b3f64e --- /dev/null +++ b/ffplay源码和书籍/ffplay/libavcodec/avcodec.h @@ -0,0 +1,201 @@ +#ifndef AVCODEC_H +#define AVCODEC_H + +/* +** ʹõĺꡢݽṹͺͨЩꡢݽṹͺڴģȫЧ +*/ +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "../libavutil/avutil.h" + +#define FFMPEG_VERSION_INT 0x000409 +#define FFMPEG_VERSION "CVS" + +#define AV_STRINGIFY(s) AV_TOSTRING(s) +#define AV_TOSTRING(s) #s + +#define LIBAVCODEC_VERSION_INT ((51<<16)+(8<<8)+0) +#define LIBAVCODEC_VERSION 51.8.0 +#define LIBAVCODEC_BUILD LIBAVCODEC_VERSION_INT + +#define LIBAVCODEC_IDENT "Lavc" AV_STRINGIFY(LIBAVCODEC_VERSION) + +#define AV_NOPTS_VALUE int64_t_C(0x8000000000000000) +#define AV_TIME_BASE 1000000 + + /* ID 򻯰Ľֻֽ֧뷽ʽtruespeechmsrle*/ +enum CodecID +{ + CODEC_ID_TRUESPEECH, + CODEC_ID_MSRLE, + CODEC_ID_NONE +}; + +/* */ +enum CodecType +{ + CODEC_TYPE_UNKNOWN = - 1, + // Ƶ + CODEC_TYPE_VIDEO, + // Ƶ + CODEC_TYPE_AUDIO, + CODEC_TYPE_DATA +}; + +#define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audio + +#define FF_INPUT_BUFFER_PADDING_SIZE 8 + +/* +AVPicture AVFrame Ҫʾеʹû棬ͨ֡ YUV ʽʽ YUV +Ҳ RGB ʽԶ 4 data ָʾ +*/ + +/* ͼ */ +typedef struct AVPicture +{ + uint8_t *data[4]; + int linesize[4]; +} AVPicture; + +/* ֡ */ +typedef struct AVFrame +{ + uint8_t *data[4]; + int linesize[4]; + uint8_t *base[4]; +} AVFrame; + +/* +** ʱǰ Codec ʹõģ Codec е(ڳʱȷ +ֵ)codec priv_data ṹֶΣݽṹת +*/ + +/* еĵǰ Codec ʹõ */ +typedef struct AVCodecContext +{ + int bit_rate; + int frame_number; // audio or video frame number + + unsigned char *extradata; // Codec˽ݣAudioWAVEFORMATEXṹչֽڡ + int extradata_size; // VideoBITMAPINFOHEADERչֽ + + int width, height; + + enum PixelFormat pix_fmt; + + int sample_rate; // samples per sec // audio only + int channels; + int bits_per_sample; + int block_align; + + // + struct AVCodec *codec; + void *priv_data; + + enum CodecType codec_type; // see CODEC_TYPE_xxx + enum CodecID codec_id; // see CODEC_ID_xxx + + int(*get_buffer)(struct AVCodecContext *c, AVFrame *pic); + void(*release_buffer)(struct AVCodecContext *c, AVFrame *pic); + int(*reget_buffer)(struct AVCodecContext *c, AVFrame *pic); + + int internal_buffer_count; + void *internal_buffer; + + // ɫ + struct AVPaletteControl *palctrl; +}AVCodecContext; + +/* ͿԱʾ*/ +/* ʾƵ ڹܺ һýͶӦһ AVCodec +ṹڳʱжʵڲ*/ +typedef struct AVCodec +{ + const char *name; // + enum CodecType type; // ͣ VideoAudioData + enum CodecID id; // id + int priv_data_size; // ӦĵĴС + int(*init)(AVCodecContext*); // ʼ + int(*encode)(AVCodecContext *, uint8_t *buf, int buf_size, void *data); // 뺯 + int(*close)(AVCodecContext*); // ر + int(*decode)(AVCodecContext *, void *outdata, int *outdata_size, uint8_t *buf, int buf_size); // 뺯 + int capabilities; // ʾCodec + + struct AVCodec *next; // ڰ Codec һڱ +}AVCodec; + +#define AVPALETTE_SIZE 1024 +#define AVPALETTE_COUNT 256 + +/* ɫСʹС궨壬ÿɫֽ(R,G,B,)кܶƵͼɫȽ٣ +ӱʾÿصɫֵͿõɫֵʵּ򵥵ĴԼ 4:1 ѹȡ */ +/* ɫ,ɫݽṹ壬ɫݡ */ +typedef struct AVPaletteControl +{ + // demuxer sets this to 1 to indicate the palette has changed; decoder resets to 0 + int palette_changed; + + /* 4-byte ARGB palette entries, stored in native byte order; note that + * the individual palette components should be on a 8-bit scale; if + * the palette data comes from a IBM VGA native format, the component + * data is probably 6 bits in size and needs to be scaled */ + unsigned int palette[AVPALETTE_COUNT]; + +} AVPaletteControl; + +int avpicture_alloc(AVPicture *picture, int pix_fmt, int width, int height); + +void avpicture_free(AVPicture *picture); + +int avpicture_fill(AVPicture *picture, uint8_t *ptr, int pix_fmt, int width, int height); +int avpicture_get_size(int pix_fmt, int width, int height); +void avcodec_get_chroma_sub_sample(int pix_fmt, int *h_shift, int *v_shift); + +int img_convert(AVPicture *dst, int dst_pix_fmt, const AVPicture *src, int pix_fmt, + int width, int height); + +void avcodec_init(void); + +void register_avcodec(AVCodec *format); +AVCodec *avcodec_find_decoder(enum CodecID id); + +AVCodecContext *avcodec_alloc_context(void); + +int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic); +void avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic); +int avcodec_default_reget_buffer(AVCodecContext *s, AVFrame *pic); +void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height); +int avcodec_check_dimensions(void *av_log_ctx, unsigned int w, unsigned int h); + +int avcodec_open(AVCodecContext *avctx, AVCodec *codec); + +int avcodec_decode_audio(AVCodecContext *avctx, int16_t *samples, int *frame_size_ptr, + uint8_t *buf, int buf_size); +int avcodec_decode_video(AVCodecContext *avctx, AVFrame *picture, int *got_picture_ptr, + uint8_t *buf, int buf_size); + +int avcodec_close(AVCodecContext *avctx); + +void avcodec_register_all(void); + +void avcodec_default_free_buffers(AVCodecContext *s); + +void *av_malloc(unsigned int size); +void *av_mallocz(unsigned int size); +void *av_realloc(void *ptr, unsigned int size); +void av_free(void *ptr); +void av_freep(void *ptr); +void *av_fast_realloc(void *ptr, unsigned int *size, unsigned int min_size); + +void img_copy(AVPicture *dst, const AVPicture *src, int pix_fmt, int width, int height); + +#ifdef __cplusplus +} + +#endif + +#endif diff --git a/ffplay源码和书籍/ffplay/libavcodec/dsputil.c b/ffplay源码和书籍/ffplay/libavcodec/dsputil.c new file mode 100644 index 0000000..590d1bc --- /dev/null +++ b/ffplay源码和书籍/ffplay/libavcodec/dsputil.c @@ -0,0 +1,23 @@ +/************************************************************************/ +/* dsp Ż޷ʹõIJұʵʼ */ +/************************************************************************/ +#include "avcodec.h" +#include "dsputil.h" + + +uint8_t cropTbl[256+2 * MAX_NEG_CROP] = {0, }; + +/* dspľ̬ʼ ʵcropTblֵ */ +void dsputil_static_init(void) +{ + int i; + + for (i = 0; i < 256; i++) + cropTbl[i + MAX_NEG_CROP] = i; + + for (i = 0; i < MAX_NEG_CROP; i++) + { + cropTbl[i] = 0; + cropTbl[i + MAX_NEG_CROP + 256] = 255; + } +} diff --git a/ffplay源码和书籍/ffplay/libavcodec/dsputil.h b/ffplay源码和书籍/ffplay/libavcodec/dsputil.h new file mode 100644 index 0000000..3bc52f4 --- /dev/null +++ b/ffplay源码和书籍/ffplay/libavcodec/dsputil.h @@ -0,0 +1,13 @@ +#ifndef DSPUTIL_H +#define DSPUTIL_H + +/************************************************************************/ +/* dsp Ż޷ʹõIJұʼ */ +/************************************************************************/ +#define MAX_NEG_CROP 1024 + +extern uint8_t cropTbl[256+2 * MAX_NEG_CROP]; + +void dsputil_static_init(void); + +#endif diff --git a/ffplay源码和书籍/ffplay/libavcodec/imgconvert.c b/ffplay源码和书籍/ffplay/libavcodec/imgconvert.c new file mode 100644 index 0000000..642b814 --- /dev/null +++ b/ffplay源码和书籍/ffplay/libavcodec/imgconvert.c @@ -0,0 +1,1707 @@ +/************************************************************************/ +/* 岢ʵͼɫռתʹõĺͺ */ +/************************************************************************/ +#include "avcodec.h" +#include "dsputil.h" + +#define xglue(x, y) x ## y +#define glue(x, y) xglue(x, y) + +#define FF_COLOR_RGB 0 // RGB color space +#define FF_COLOR_GRAY 1 // gray color space +#define FF_COLOR_YUV 2 // YUV color space. 16 <= Y <= 235, 16 <= U, V <= 240 +#define FF_COLOR_YUV_JPEG 3 // YUV color space. 0 <= Y <= 255, 0 <= U, V <= 255 + +#define FF_PIXEL_PLANAR 0 // each channel has one component in AVPicture +#define FF_PIXEL_PACKED 1 // only one components containing all the channels +#define FF_PIXEL_PALETTE 2 // one components containing indexes for a palette + +typedef struct PixFmtInfo +{ + const char *name; + uint8_t nb_channels; // number of channels (including alpha) + uint8_t color_type; // color type (see FF_COLOR_xxx constants) + uint8_t pixel_type; // pixel storage type (see FF_PIXEL_xxx constants) + uint8_t is_alpha; // true if alpha can be specified + uint8_t x_chroma_shift; // X chroma subsampling factor is 2 ^ shift + uint8_t y_chroma_shift; // Y chroma subsampling factor is 2 ^ shift + uint8_t depth; // bit depth of the color components +} PixFmtInfo; + +// this table gives more information about formats +static PixFmtInfo pix_fmt_info[PIX_FMT_NB] = +{ + { "yuv420p", 3, FF_COLOR_YUV, FF_PIXEL_PLANAR, 0, 1, 1, 8}, + { "yuv422", 1, FF_COLOR_YUV, FF_PIXEL_PACKED, 0, 1, 0, 8}, + { "rgb24", 3, FF_COLOR_RGB, FF_PIXEL_PACKED, 0, 0, 0, 8}, + { "bgr24", 3, FF_COLOR_RGB, FF_PIXEL_PACKED, 0, 0, 0, 8}, + { "yuv422p", 3, FF_COLOR_YUV, FF_PIXEL_PLANAR, 0, 1, 0, 8}, + { "yuv444p", 3, FF_COLOR_YUV, FF_PIXEL_PLANAR, 0, 0, 0, 8}, + { "rgba32", 4, FF_COLOR_RGB, FF_PIXEL_PACKED, 1, 0, 0, 8}, + { "yuv410p", 3, FF_COLOR_YUV, FF_PIXEL_PLANAR, 0, 2, 2, 8}, + { "yuv411p", 3, FF_COLOR_YUV, FF_PIXEL_PLANAR, 0, 2, 0, 8}, + { "rgb565", 3, FF_COLOR_RGB, FF_PIXEL_PACKED, 0, 0, 0, 5}, + { "rgb555", 4, FF_COLOR_RGB, FF_PIXEL_PACKED, 1, 0, 0, 5}, + { "gray", 1, FF_COLOR_GRAY, FF_PIXEL_PLANAR, 0, 0, 0, 8}, + { "monow", 1, FF_COLOR_GRAY, FF_PIXEL_PLANAR, 0, 0, 0, 1}, + { "monob", 1, FF_COLOR_GRAY, FF_PIXEL_PLANAR, 0, 0, 0, 1}, + { "pal8", 4, FF_COLOR_RGB, FF_PIXEL_PALETTE, 1, 0, 0, 8}, + { "yuvj420p", 3, FF_COLOR_YUV_JPEG, FF_PIXEL_PLANAR, 0, 1, 1, 8}, + { "yuvj422p", 3, FF_COLOR_YUV_JPEG, FF_PIXEL_PLANAR, 0, 1, 0, 8}, + { "yuvj444p", 3, FF_COLOR_YUV_JPEG, FF_PIXEL_PLANAR, 0, 0, 0, 8}, + { "xvmcmc", }, + { "xvmcidct",}, + { "uyvy422", 1, FF_COLOR_YUV, FF_PIXEL_PACKED, 0, 1, 0, 8}, + { "uyvy411", 1, FF_COLOR_YUV, FF_PIXEL_PACKED, 0, 2, 0, 8}, +}; + +void avcodec_get_chroma_sub_sample(int pix_fmt, int *h_shift, int *v_shift) +{ + *h_shift = pix_fmt_info[pix_fmt].x_chroma_shift; + *v_shift = pix_fmt_info[pix_fmt].y_chroma_shift; +} + +// Picture field are filled with 'ptr' addresses. Also return size +int avpicture_fill(AVPicture *picture, uint8_t *ptr, int pix_fmt, int width, int height) +{ + int size, w2, h2, size2; + PixFmtInfo *pinfo; + + if (avcodec_check_dimensions(NULL, width, height)) + goto fail; + + pinfo = &pix_fmt_info[pix_fmt]; + size = width * height; + switch (pix_fmt) + { + case PIX_FMT_YUV420P: + case PIX_FMT_YUV422P: + case PIX_FMT_YUV444P: + case PIX_FMT_YUV410P: + case PIX_FMT_YUV411P: + case PIX_FMT_YUVJ420P: + case PIX_FMT_YUVJ422P: + case PIX_FMT_YUVJ444P: + w2 = (width + (1 << pinfo->x_chroma_shift) - 1) >> pinfo->x_chroma_shift; + h2 = (height + (1 << pinfo->y_chroma_shift) - 1) >> pinfo->y_chroma_shift; + size2 = w2 * h2; + picture->data[0] = ptr; + picture->data[1] = picture->data[0] + size; + picture->data[2] = picture->data[1] + size2; + picture->linesize[0] = width; + picture->linesize[1] = w2; + picture->linesize[2] = w2; + return size + 2 * size2; + case PIX_FMT_RGB24: + case PIX_FMT_BGR24: + picture->data[0] = ptr; + picture->data[1] = NULL; + picture->data[2] = NULL; + picture->linesize[0] = width * 3; + return size *3; + case PIX_FMT_RGBA32: + picture->data[0] = ptr; + picture->data[1] = NULL; + picture->data[2] = NULL; + picture->linesize[0] = width * 4; + return size *4; + case PIX_FMT_RGB555: + case PIX_FMT_RGB565: + case PIX_FMT_YUV422: + picture->data[0] = ptr; + picture->data[1] = NULL; + picture->data[2] = NULL; + picture->linesize[0] = width * 2; + return size *2; + case PIX_FMT_UYVY422: + picture->data[0] = ptr; + picture->data[1] = NULL; + picture->data[2] = NULL; + picture->linesize[0] = width * 2; + return size *2; + case PIX_FMT_UYVY411: + picture->data[0] = ptr; + picture->data[1] = NULL; + picture->data[2] = NULL; + picture->linesize[0] = width + width / 2; + return size + size / 2; + case PIX_FMT_GRAY8: + picture->data[0] = ptr; + picture->data[1] = NULL; + picture->data[2] = NULL; + picture->linesize[0] = width; + return size; + case PIX_FMT_MONOWHITE: + case PIX_FMT_MONOBLACK: + picture->data[0] = ptr; + picture->data[1] = NULL; + picture->data[2] = NULL; + picture->linesize[0] = (width + 7) >> 3; + return picture->linesize[0] *height; + case PIX_FMT_PAL8: + size2 = (size + 3) &~3; + picture->data[0] = ptr; + picture->data[1] = ptr + size2; // palette is stored here as 256 32 bit words + picture->data[2] = NULL; + picture->linesize[0] = width; + picture->linesize[1] = 4; + return size2 + 256 * 4; + default: +fail: + picture->data[0] = NULL; + picture->data[1] = NULL; + picture->data[2] = NULL; + picture->data[3] = NULL; + return - 1; + } +} + +int avpicture_get_size(int pix_fmt, int width, int height) +{ + AVPicture dummy_pict; + return avpicture_fill(&dummy_pict, NULL, pix_fmt, width, height); +} + +int avpicture_alloc(AVPicture *picture, int pix_fmt, int width, int height) +{ + unsigned int size; + void *ptr; + + size = avpicture_get_size(pix_fmt, width, height); + if (size < 0) + goto fail; + ptr = av_malloc(size); + if (!ptr) + goto fail; + avpicture_fill(picture, ptr, pix_fmt, width, height); + return 0; +fail: + memset(picture, 0, sizeof(AVPicture)); + return - 1; +} + +void avpicture_free(AVPicture *picture) +{ + av_free(picture->data[0]); +} + +static int avg_bits_per_pixel(int pix_fmt) +{ + int bits; + const PixFmtInfo *pf; + + pf = &pix_fmt_info[pix_fmt]; + switch (pf->pixel_type) + { + case FF_PIXEL_PACKED: + switch (pix_fmt) + { + case PIX_FMT_YUV422: + case PIX_FMT_UYVY422: + case PIX_FMT_RGB565: + case PIX_FMT_RGB555: + bits = 16; + break; + case PIX_FMT_UYVY411: + bits = 12; + break; + default: + bits = pf->depth *pf->nb_channels; + break; + } + break; + case FF_PIXEL_PLANAR: + if (pf->x_chroma_shift == 0 && pf->y_chroma_shift == 0) + { + bits = pf->depth *pf->nb_channels; + } + else + { + bits = pf->depth + ((2 *pf->depth) >> (pf->x_chroma_shift + pf->y_chroma_shift)); + } + break; + case FF_PIXEL_PALETTE: + bits = 8; + break; + default: + bits = - 1; + break; + } + return bits; +} + +//////////////////////////// + +void ff_img_copy_plane(uint8_t *dst, int dst_wrap, const uint8_t *src, int src_wrap, int width, int height) +{ + if ((!dst) || (!src)) + return ; + + for (; height > 0; height--) + { + memcpy(dst, src, width); + dst += dst_wrap; + src += src_wrap; + } +} + +void img_copy(AVPicture *dst, const AVPicture *src, int pix_fmt, int width, int height) +{ + int bwidth, bits, i; + PixFmtInfo *pf = &pix_fmt_info[pix_fmt]; + + pf = &pix_fmt_info[pix_fmt]; + switch (pf->pixel_type) + { + case FF_PIXEL_PACKED: + switch (pix_fmt) + { + case PIX_FMT_YUV422: + case PIX_FMT_UYVY422: + case PIX_FMT_RGB565: + case PIX_FMT_RGB555: + bits = 16; + break; + case PIX_FMT_UYVY411: + bits = 12; + break; + default: + bits = pf->depth *pf->nb_channels; + break; + } + bwidth = (width *bits + 7) >> 3; + ff_img_copy_plane(dst->data[0], dst->linesize[0], src->data[0], src->linesize[0], bwidth, height); + break; + case FF_PIXEL_PLANAR: + for (i = 0; i < pf->nb_channels; i++) + { + int w, h; + w = width; + h = height; + if (i == 1 || i == 2) + { + w >>= pf->x_chroma_shift; + h >>= pf->y_chroma_shift; + } + bwidth = (w *pf->depth + 7) >> 3; + ff_img_copy_plane(dst->data[i], dst->linesize[i], src->data[i], src->linesize[i], bwidth, h); + } + break; + case FF_PIXEL_PALETTE: + ff_img_copy_plane(dst->data[0], dst->linesize[0], src->data[0], src->linesize[0], width, height); + // copy the palette + ff_img_copy_plane(dst->data[1], dst->linesize[1], src->data[1], src->linesize[1], 4, 256); + break; + } +} + +static void yuv422_to_yuv420p(AVPicture *dst, const AVPicture *src, int width, int height) +{ + const uint8_t *p, *p1; + uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; + int w; + + p1 = src->data[0]; + lum1 = dst->data[0]; + cb1 = dst->data[1]; + cr1 = dst->data[2]; + + for (; height >= 1; height -= 2) + { + p = p1; + lum = lum1; + cb = cb1; + cr = cr1; + for (w = width; w >= 2; w -= 2) + { + lum[0] = p[0]; + cb[0] = p[1]; + lum[1] = p[2]; + cr[0] = p[3]; + p += 4; + lum += 2; + cb++; + cr++; + } + if (w) + { + lum[0] = p[0]; + cb[0] = p[1]; + cr[0] = p[3]; + cb++; + cr++; + } + p1 += src->linesize[0]; + lum1 += dst->linesize[0]; + if (height > 1) + { + p = p1; + lum = lum1; + for (w = width; w >= 2; w -= 2) + { + lum[0] = p[0]; + lum[1] = p[2]; + p += 4; + lum += 2; + } + if (w) + { + lum[0] = p[0]; + } + p1 += src->linesize[0]; + lum1 += dst->linesize[0]; + } + cb1 += dst->linesize[1]; + cr1 += dst->linesize[2]; + } +} + +static void uyvy422_to_yuv420p(AVPicture *dst, const AVPicture *src, int width, int height) +{ + const uint8_t *p, *p1; + uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; + int w; + + p1 = src->data[0]; + + lum1 = dst->data[0]; + cb1 = dst->data[1]; + cr1 = dst->data[2]; + + for (; height >= 1; height -= 2) + { + p = p1; + lum = lum1; + cb = cb1; + cr = cr1; + for (w = width; w >= 2; w -= 2) + { + lum[0] = p[1]; + cb[0] = p[0]; + lum[1] = p[3]; + cr[0] = p[2]; + p += 4; + lum += 2; + cb++; + cr++; + } + if (w) + { + lum[0] = p[1]; + cb[0] = p[0]; + cr[0] = p[2]; + cb++; + cr++; + } + p1 += src->linesize[0]; + lum1 += dst->linesize[0]; + if (height > 1) + { + p = p1; + lum = lum1; + for (w = width; w >= 2; w -= 2) + { + lum[0] = p[1]; + lum[1] = p[3]; + p += 4; + lum += 2; + } + if (w) + { + lum[0] = p[1]; + } + p1 += src->linesize[0]; + lum1 += dst->linesize[0]; + } + cb1 += dst->linesize[1]; + cr1 += dst->linesize[2]; + } +} + +static void uyvy422_to_yuv422p(AVPicture *dst, const AVPicture *src, int width, int height) +{ + const uint8_t *p, *p1; + uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; + int w; + + p1 = src->data[0]; + lum1 = dst->data[0]; + cb1 = dst->data[1]; + cr1 = dst->data[2]; + for (; height > 0; height--) + { + p = p1; + lum = lum1; + cb = cb1; + cr = cr1; + for (w = width; w >= 2; w -= 2) + { + lum[0] = p[1]; + cb[0] = p[0]; + lum[1] = p[3]; + cr[0] = p[2]; + p += 4; + lum += 2; + cb++; + cr++; + } + p1 += src->linesize[0]; + lum1 += dst->linesize[0]; + cb1 += dst->linesize[1]; + cr1 += dst->linesize[2]; + } +} + +static void yuv422_to_yuv422p(AVPicture *dst, const AVPicture *src, int width, int height) +{ + const uint8_t *p, *p1; + uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; + int w; + + p1 = src->data[0]; + lum1 = dst->data[0]; + cb1 = dst->data[1]; + cr1 = dst->data[2]; + for (; height > 0; height--) + { + p = p1; + lum = lum1; + cb = cb1; + cr = cr1; + for (w = width; w >= 2; w -= 2) + { + lum[0] = p[0]; + cb[0] = p[1]; + lum[1] = p[2]; + cr[0] = p[3]; + p += 4; + lum += 2; + cb++; + cr++; + } + p1 += src->linesize[0]; + lum1 += dst->linesize[0]; + cb1 += dst->linesize[1]; + cr1 += dst->linesize[2]; + } +} + +static void yuv422p_to_yuv422(AVPicture *dst, const AVPicture *src, int width, int height) +{ + uint8_t *p, *p1; + const uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; + int w; + + p1 = dst->data[0]; + lum1 = src->data[0]; + cb1 = src->data[1]; + cr1 = src->data[2]; + for (; height > 0; height--) + { + p = p1; + lum = lum1; + cb = cb1; + cr = cr1; + for (w = width; w >= 2; w -= 2) + { + p[0] = lum[0]; + p[1] = cb[0]; + p[2] = lum[1]; + p[3] = cr[0]; + p += 4; + lum += 2; + cb++; + cr++; + } + p1 += dst->linesize[0]; + lum1 += src->linesize[0]; + cb1 += src->linesize[1]; + cr1 += src->linesize[2]; + } +} + +static void yuv422p_to_uyvy422(AVPicture *dst, const AVPicture *src, int width, int height) +{ + uint8_t *p, *p1; + const uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; + int w; + + p1 = dst->data[0]; + lum1 = src->data[0]; + cb1 = src->data[1]; + cr1 = src->data[2]; + for (; height > 0; height--) + { + p = p1; + lum = lum1; + cb = cb1; + cr = cr1; + for (w = width; w >= 2; w -= 2) + { + p[1] = lum[0]; + p[0] = cb[0]; + p[3] = lum[1]; + p[2] = cr[0]; + p += 4; + lum += 2; + cb++; + cr++; + } + p1 += dst->linesize[0]; + lum1 += src->linesize[0]; + cb1 += src->linesize[1]; + cr1 += src->linesize[2]; + } +} + +static void uyvy411_to_yuv411p(AVPicture *dst, const AVPicture *src, int width, int height) +{ + const uint8_t *p, *p1; + uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; + int w; + + p1 = src->data[0]; + lum1 = dst->data[0]; + cb1 = dst->data[1]; + cr1 = dst->data[2]; + for (; height > 0; height--) + { + p = p1; + lum = lum1; + cb = cb1; + cr = cr1; + for (w = width; w >= 4; w -= 4) + { + cb[0] = p[0]; + lum[0] = p[1]; + lum[1] = p[2]; + cr[0] = p[3]; + lum[2] = p[4]; + lum[3] = p[5]; + p += 6; + lum += 4; + cb++; + cr++; + } + p1 += src->linesize[0]; + lum1 += dst->linesize[0]; + cb1 += dst->linesize[1]; + cr1 += dst->linesize[2]; + } +} + +static void yuv420p_to_yuv422(AVPicture *dst, const AVPicture *src, int width, int height) +{ + int w, h; + uint8_t *line1, *line2, *linesrc = dst->data[0]; + uint8_t *lum1, *lum2, *lumsrc = src->data[0]; + uint8_t *cb1, *cb2 = src->data[1]; + uint8_t *cr1, *cr2 = src->data[2]; + + for (h = height / 2; h--;) + { + line1 = linesrc; + line2 = linesrc + dst->linesize[0]; + + lum1 = lumsrc; + lum2 = lumsrc + src->linesize[0]; + + cb1 = cb2; + cr1 = cr2; + + for (w = width / 2; w--;) + { + *line1++ = *lum1++; + *line2++ = *lum2++; + *line1++ = *line2++ = *cb1++; + *line1++ = *lum1++; + *line2++ = *lum2++; + *line1++ = *line2++ = *cr1++; + } + + linesrc += dst->linesize[0] *2; + lumsrc += src->linesize[0] *2; + cb2 += src->linesize[1]; + cr2 += src->linesize[2]; + } +} + +static void yuv420p_to_uyvy422(AVPicture *dst, const AVPicture *src, int width, int height) +{ + int w, h; + uint8_t *line1, *line2, *linesrc = dst->data[0]; + uint8_t *lum1, *lum2, *lumsrc = src->data[0]; + uint8_t *cb1, *cb2 = src->data[1]; + uint8_t *cr1, *cr2 = src->data[2]; + + for (h = height / 2; h--;) + { + line1 = linesrc; + line2 = linesrc + dst->linesize[0]; + + lum1 = lumsrc; + lum2 = lumsrc + src->linesize[0]; + + cb1 = cb2; + cr1 = cr2; + + for (w = width / 2; w--;) + { + *line1++ = *line2++ = *cb1++; + *line1++ = *lum1++; + *line2++ = *lum2++; + *line1++ = *line2++ = *cr1++; + *line1++ = *lum1++; + *line2++ = *lum2++; + } + + linesrc += dst->linesize[0] *2; + lumsrc += src->linesize[0] *2; + cb2 += src->linesize[1]; + cr2 += src->linesize[2]; + } +} + +#define SCALEBITS 10 +#define ONE_HALF (1 << (SCALEBITS - 1)) +#define FIX(x) ((int) ((x) * (1<> SCALEBITS];\ + g = cm[(y + g_add) >> SCALEBITS];\ + b = cm[(y + b_add) >> SCALEBITS];\ +} + +#define YUV_TO_RGB1(cb1, cr1)\ +{\ + cb = (cb1) - 128;\ + cr = (cr1) - 128;\ + r_add = FIX(1.40200) * cr + ONE_HALF;\ + g_add = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;\ + b_add = FIX(1.77200) * cb + ONE_HALF;\ +} + +#define YUV_TO_RGB2(r, g, b, y1)\ +{\ + y = (y1) << SCALEBITS;\ + r = cm[(y + r_add) >> SCALEBITS];\ + g = cm[(y + g_add) >> SCALEBITS];\ + b = cm[(y + b_add) >> SCALEBITS];\ +} + +#define Y_CCIR_TO_JPEG(y)\ + cm[((y) * FIX(255.0/219.0) + (ONE_HALF - 16 * FIX(255.0/219.0))) >> SCALEBITS] + +#define Y_JPEG_TO_CCIR(y)\ + (((y) * FIX(219.0/255.0) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS) + +#define C_CCIR_TO_JPEG(y)\ + cm[(((y) - 128) * FIX(127.0/112.0) + (ONE_HALF + (128 << SCALEBITS))) >> SCALEBITS] + +/* NOTE: the clamp is really necessary! */ +static inline int C_JPEG_TO_CCIR(int y) +{ + y = (((y - 128) *FIX(112.0 / 127.0) + (ONE_HALF + (128 << SCALEBITS))) >> SCALEBITS); + if (y < 16) + y = 16; + return y; +} + +#define RGB_TO_Y(r, g, b) \ + ((FIX(0.29900) * (r) + FIX(0.58700) * (g) + \ + FIX(0.11400) * (b) + ONE_HALF) >> SCALEBITS) + +#define RGB_TO_U(r1, g1, b1, shift)\ + (((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + \ + FIX(0.50000) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) + +#define RGB_TO_V(r1, g1, b1, shift)\ + (((FIX(0.50000) * r1 - FIX(0.41869) * g1 - \ + FIX(0.08131) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) + +#define RGB_TO_Y_CCIR(r, g, b) \ + ((FIX(0.29900*219.0/255.0) * (r) + FIX(0.58700*219.0/255.0) * (g) + \ + FIX(0.11400*219.0/255.0) * (b) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS) + +#define RGB_TO_U_CCIR(r1, g1, b1, shift)\ + (((- FIX(0.16874*224.0/255.0) * r1 - FIX(0.33126*224.0/255.0) * g1 + \ + FIX(0.50000*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) + +#define RGB_TO_V_CCIR(r1, g1, b1, shift)\ + (((FIX(0.50000*224.0/255.0) * r1 - FIX(0.41869*224.0/255.0) * g1 - \ + FIX(0.08131*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) + +static uint8_t y_ccir_to_jpeg[256]; +static uint8_t y_jpeg_to_ccir[256]; +static uint8_t c_ccir_to_jpeg[256]; +static uint8_t c_jpeg_to_ccir[256]; + +/* apply to each pixel the given table */ +static void img_apply_table(uint8_t *dst, int dst_wrap, const uint8_t *src, int src_wrap, + int width, int height, const uint8_t *table1) +{ + int n; + const uint8_t *s; + uint8_t *d; + const uint8_t *table; + + table = table1; + for (; height > 0; height--) + { + s = src; + d = dst; + n = width; + while (n >= 4) + { + d[0] = table[s[0]]; + d[1] = table[s[1]]; + d[2] = table[s[2]]; + d[3] = table[s[3]]; + d += 4; + s += 4; + n -= 4; + } + while (n > 0) + { + d[0] = table[s[0]]; + d++; + s++; + n--; + } + dst += dst_wrap; + src += src_wrap; + } +} + +/* XXX: use generic filter ? */ +/* XXX: in most cases, the sampling position is incorrect */ + +/* 4x1 -> 1x1 */ +static void shrink41(uint8_t *dst, int dst_wrap, const uint8_t *src, int src_wrap, int width, int height) +{ + int w; + const uint8_t *s; + uint8_t *d; + + for (; height > 0; height--) + { + s = src; + d = dst; + for (w = width; w > 0; w--) + { + d[0] = (s[0] + s[1] + s[2] + s[3] + 2) >> 2; + s += 4; + d++; + } + src += src_wrap; + dst += dst_wrap; + } +} + +/* 2x1 -> 1x1 */ +static void shrink21(uint8_t *dst, int dst_wrap, const uint8_t *src, int src_wrap, int width, int height) +{ + int w; + const uint8_t *s; + uint8_t *d; + + for (; height > 0; height--) + { + s = src; + d = dst; + for (w = width; w > 0; w--) + { + d[0] = (s[0] + s[1]) >> 1; + s += 2; + d++; + } + src += src_wrap; + dst += dst_wrap; + } +} + +/* 1x2 -> 1x1 */ +static void shrink12(uint8_t *dst, int dst_wrap, const uint8_t *src, int src_wrap, int width, int height) +{ + int w; + uint8_t *d; + const uint8_t *s1, *s2; + + for (; height > 0; height--) + { + s1 = src; + s2 = s1 + src_wrap; + d = dst; + for (w = width; w >= 4; w -= 4) + { + d[0] = (s1[0] + s2[0]) >> 1; + d[1] = (s1[1] + s2[1]) >> 1; + d[2] = (s1[2] + s2[2]) >> 1; + d[3] = (s1[3] + s2[3]) >> 1; + s1 += 4; + s2 += 4; + d += 4; + } + for (; w > 0; w--) + { + d[0] = (s1[0] + s2[0]) >> 1; + s1++; + s2++; + d++; + } + src += 2 * src_wrap; + dst += dst_wrap; + } +} + +/* 2x2 -> 1x1 */ +void ff_shrink22(uint8_t *dst, int dst_wrap, const uint8_t *src, int src_wrap, int width, int height) +{ + int w; + const uint8_t *s1, *s2; + uint8_t *d; + + for (; height > 0; height--) + { + s1 = src; + s2 = s1 + src_wrap; + d = dst; + for (w = width; w >= 4; w -= 4) + { + d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2; + d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 2; + d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 2; + d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 2; + s1 += 8; + s2 += 8; + d += 4; + } + for (; w > 0; w--) + { + d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2; + s1 += 2; + s2 += 2; + d++; + } + src += 2 * src_wrap; + dst += dst_wrap; + } +} + +/* 4x4 -> 1x1 */ +void ff_shrink44(uint8_t *dst, int dst_wrap, const uint8_t *src, int src_wrap, int width, int height) +{ + int w; + const uint8_t *s1, *s2, *s3, *s4; + uint8_t *d; + + for (; height > 0; height--) + { + s1 = src; + s2 = s1 + src_wrap; + s3 = s2 + src_wrap; + s4 = s3 + src_wrap; + d = dst; + for (w = width; w > 0; w--) + { + d[0] = (s1[0] + s1[1] + s1[2] + s1[3] + s2[0] + s2[1] + s2[2] + s2[3] + + s3[0] + s3[1] + s3[2] + s3[3] + s4[0] + s4[1] + s4[2] + s4[3] + 8) >> 4; + s1 += 4; + s2 += 4; + s3 += 4; + s4 += 4; + d++; + } + src += 4 * src_wrap; + dst += dst_wrap; + } +} + +static void grow21_line(uint8_t *dst, const uint8_t *src, int width) +{ + int w; + const uint8_t *s1; + uint8_t *d; + + s1 = src; + d = dst; + for (w = width; w >= 4; w -= 4) + { + d[1] = d[0] = s1[0]; + d[3] = d[2] = s1[1]; + s1 += 2; + d += 4; + } + for (; w >= 2; w -= 2) + { + d[1] = d[0] = s1[0]; + s1++; + d += 2; + } + /* only needed if width is not a multiple of two */ + /* XXX: veryfy that */ + if (w) + { + d[0] = s1[0]; + } +} + +static void grow41_line(uint8_t *dst, const uint8_t *src, int width) +{ + int w, v; + const uint8_t *s1; + uint8_t *d; + + s1 = src; + d = dst; + for (w = width; w >= 4; w -= 4) + { + v = s1[0]; + d[0] = v; + d[1] = v; + d[2] = v; + d[3] = v; + s1++; + d += 4; + } +} + +/* 1x1 -> 2x1 */ +static void grow21(uint8_t *dst, int dst_wrap, const uint8_t *src, int src_wrap, int width, int height) +{ + for (; height > 0; height--) + { + grow21_line(dst, src, width); + src += src_wrap; + dst += dst_wrap; + } +} + +/* 1x1 -> 2x2 */ +static void grow22(uint8_t *dst, int dst_wrap, const uint8_t *src, int src_wrap, int width, int height) +{ + for (; height > 0; height--) + { + grow21_line(dst, src, width); + if (height % 2) + src += src_wrap; + dst += dst_wrap; + } +} + +/* 1x1 -> 4x1 */ +static void grow41(uint8_t *dst, int dst_wrap, const uint8_t *src, int src_wrap, int width, int height) +{ + for (; height > 0; height--) + { + grow41_line(dst, src, width); + src += src_wrap; + dst += dst_wrap; + } +} + +/* 1x1 -> 4x4 */ +static void grow44(uint8_t *dst, int dst_wrap, const uint8_t *src, int src_wrap, int width, int height) +{ + for (; height > 0; height--) + { + grow41_line(dst, src, width); + if ((height &3) == 1) + src += src_wrap; + dst += dst_wrap; + } +} + +/* 1x2 -> 2x1 */ +static void conv411(uint8_t *dst, int dst_wrap, const uint8_t *src, int src_wrap, int width, int height) +{ + int w, c; + const uint8_t *s1, *s2; + uint8_t *d; + + width >>= 1; + + for (; height > 0; height--) + { + s1 = src; + s2 = src + src_wrap; + d = dst; + for (w = width; w > 0; w--) + { + c = (s1[0] + s2[0]) >> 1; + d[0] = c; + d[1] = c; + s1++; + s2++; + d += 2; + } + src += src_wrap * 2; + dst += dst_wrap; + } +} + +/* XXX: add jpeg quantize code */ + +#define TRANSP_INDEX (6*6*6) + +/* this is maybe slow, but allows for extensions */ +static inline unsigned char gif_clut_index(uint8_t r, uint8_t g, uint8_t b) +{ + return ((((r) / 47) % 6) *6 * 6+(((g) / 47) % 6) *6+(((b) / 47) % 6)); +} + +static void build_rgb_palette(uint8_t *palette, int has_alpha) +{ + uint32_t *pal; + static const uint8_t pal_value[6] = {0x00, 0x33, 0x66, 0x99, 0xcc, 0xff }; + int i, r, g, b; + + pal = (uint32_t*)palette; + i = 0; + for (r = 0; r < 6; r++) + { + for (g = 0; g < 6; g++) + { + for (b = 0; b < 6; b++) + { + pal[i++] = (0xff << 24) | (pal_value[r] << 16) | (pal_value[g] << 8) | pal_value[b]; + } + } + } + if (has_alpha) + pal[i++] = 0; + while (i < 256) + pal[i++] = 0xff000000; +} + +/* copy bit n to bits 0 ... n - 1 */ +static inline unsigned int bitcopy_n(unsigned int a, int n) +{ + int mask; + mask = (1 << n) - 1; + return (a &(0xff &~mask)) | (( - ((a >> n) &1)) &mask); +} + +/* rgb555 handling */ + +#define RGB_NAME rgb555 + +#define RGB_IN(r, g, b, s)\ +{\ + unsigned int v = ((const uint16_t *)(s))[0];\ + r = bitcopy_n(v >> (10 - 3), 3);\ + g = bitcopy_n(v >> (5 - 3), 3);\ + b = bitcopy_n(v << 3, 3);\ +} + +#define RGBA_IN(r, g, b, a, s)\ +{\ + unsigned int v = ((const uint16_t *)(s))[0];\ + r = bitcopy_n(v >> (10 - 3), 3);\ + g = bitcopy_n(v >> (5 - 3), 3);\ + b = bitcopy_n(v << 3, 3);\ + a = (-(v >> 15)) & 0xff;\ +} + +#define RGBA_OUT(d, r, g, b, a)\ +{\ + ((uint16_t *)(d))[0] = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3) | \ + ((a << 8) & 0x8000);\ +} + +#define BPP 2 + +#include "imgconvert_template.h" + +/* rgb565 handling */ + +#define RGB_NAME rgb565 + +#define RGB_IN(r, g, b, s)\ +{\ + unsigned int v = ((const uint16_t *)(s))[0];\ + r = bitcopy_n(v >> (11 - 3), 3);\ + g = bitcopy_n(v >> (5 - 2), 2);\ + b = bitcopy_n(v << 3, 3);\ +} + +#define RGB_OUT(d, r, g, b)\ +{\ + ((uint16_t *)(d))[0] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);\ +} + +#define BPP 2 + +#include "imgconvert_template.h" + +/* bgr24 handling */ + +#define RGB_NAME bgr24 + +#define RGB_IN(r, g, b, s)\ +{\ + b = (s)[0];\ + g = (s)[1];\ + r = (s)[2];\ +} + +#define RGB_OUT(d, r, g, b)\ +{\ + (d)[0] = b;\ + (d)[1] = g;\ + (d)[2] = r;\ +} + +#define BPP 3 + +#include "imgconvert_template.h" + +#undef RGB_IN +#undef RGB_OUT +#undef BPP + +/* rgb24 handling */ + +#define RGB_NAME rgb24 +#define FMT_RGB24 + +#define RGB_IN(r, g, b, s)\ +{\ + r = (s)[0];\ + g = (s)[1];\ + b = (s)[2];\ +} + +#define RGB_OUT(d, r, g, b)\ +{\ + (d)[0] = r;\ + (d)[1] = g;\ + (d)[2] = b;\ +} + +#define BPP 3 + +#include "imgconvert_template.h" + +/* rgba32 handling */ + +#define RGB_NAME rgba32 +#define FMT_RGBA32 + +#define RGB_IN(r, g, b, s)\ +{\ + unsigned int v = ((const uint32_t *)(s))[0];\ + r = (v >> 16) & 0xff;\ + g = (v >> 8) & 0xff;\ + b = v & 0xff;\ +} + +#define RGBA_IN(r, g, b, a, s)\ +{\ + unsigned int v = ((const uint32_t *)(s))[0];\ + a = (v >> 24) & 0xff;\ + r = (v >> 16) & 0xff;\ + g = (v >> 8) & 0xff;\ + b = v & 0xff;\ +} + +#define RGBA_OUT(d, r, g, b, a)\ +{\ + ((uint32_t *)(d))[0] = (a << 24) | (r << 16) | (g << 8) | b;\ +} + +#define BPP 4 + +#include "imgconvert_template.h" + +static void mono_to_gray(AVPicture *dst, const AVPicture *src, int width, int height, int xor_mask) +{ + const unsigned char *p; + unsigned char *q; + int v, dst_wrap, src_wrap; + int y, w; + + p = src->data[0]; + src_wrap = src->linesize[0] - ((width + 7) >> 3); + + q = dst->data[0]; + dst_wrap = dst->linesize[0] - width; + for (y = 0; y < height; y++) + { + w = width; + while (w >= 8) + { + v = *p++ ^ xor_mask; + q[0] = - (v >> 7); + q[1] = - ((v >> 6) &1); + q[2] = - ((v >> 5) &1); + q[3] = - ((v >> 4) &1); + q[4] = - ((v >> 3) &1); + q[5] = - ((v >> 2) &1); + q[6] = - ((v >> 1) &1); + q[7] = - ((v >> 0) &1); + w -= 8; + q += 8; + } + if (w > 0) + { + v = *p++ ^ xor_mask; + do + { + q[0] = - ((v >> 7) &1); + q++; + v <<= 1; + } + while (--w); + } + p += src_wrap; + q += dst_wrap; + } +} + +static void monowhite_to_gray(AVPicture *dst, const AVPicture *src, int width, int height) +{ + mono_to_gray(dst, src, width, height, 0xff); +} + +static void monoblack_to_gray(AVPicture *dst, const AVPicture *src, int width, int height) +{ + mono_to_gray(dst, src, width, height, 0x00); +} + +static void gray_to_mono(AVPicture *dst, const AVPicture *src, int width, int height, int xor_mask) +{ + int n; + const uint8_t *s; + uint8_t *d; + int j, b, v, n1, src_wrap, dst_wrap, y; + + s = src->data[0]; + src_wrap = src->linesize[0] - width; + + d = dst->data[0]; + dst_wrap = dst->linesize[0] - ((width + 7) >> 3); + + for (y = 0; y < height; y++) + { + n = width; + while (n >= 8) + { + v = 0; + for (j = 0; j < 8; j++) + { + b = s[0]; + s++; + v = (v << 1) | (b >> 7); + } + d[0] = v ^ xor_mask; + d++; + n -= 8; + } + if (n > 0) + { + n1 = n; + v = 0; + while (n > 0) + { + b = s[0]; + s++; + v = (v << 1) | (b >> 7); + n--; + } + d[0] = (v << (8-(n1 &7))) ^ xor_mask; + d++; + } + s += src_wrap; + d += dst_wrap; + } +} + +static void gray_to_monowhite(AVPicture *dst, const AVPicture *src, int width, int height) +{ + gray_to_mono(dst, src, width, height, 0xff); +} + +static void gray_to_monoblack(AVPicture *dst, const AVPicture *src, int width, int height) +{ + gray_to_mono(dst, src, width, height, 0x00); +} + +typedef struct ConvertEntry +{ + void(*convert)(AVPicture *dst, const AVPicture *src, int width, int height); +} ConvertEntry; + +/* Add each new convertion function in this table. In order to be able +to convert from any format to any format, the following constraints must be satisfied: + + - all FF_COLOR_RGB formats must convert to and from PIX_FMT_RGB24 + + - all FF_COLOR_GRAY formats must convert to and from PIX_FMT_GRAY8 + + - all FF_COLOR_RGB formats with alpha must convert to and from PIX_FMT_RGBA32 + + - PIX_FMT_YUV444P and PIX_FMT_YUVJ444P must convert to and from PIX_FMT_RGB24. + + - PIX_FMT_422 must convert to and from PIX_FMT_422P. + + The other conversion functions are just optimisations for common cases. +*/ + +static ConvertEntry convert_table[PIX_FMT_NB][PIX_FMT_NB]; + +static void img_convert_init(void) +{ + int i; + uint8_t *cm = cropTbl + MAX_NEG_CROP; + + for (i = 0; i < 256; i++) + { + y_ccir_to_jpeg[i] = Y_CCIR_TO_JPEG(i); + y_jpeg_to_ccir[i] = Y_JPEG_TO_CCIR(i); + c_ccir_to_jpeg[i] = C_CCIR_TO_JPEG(i); + c_jpeg_to_ccir[i] = C_JPEG_TO_CCIR(i); + } + + convert_table[PIX_FMT_YUV420P][PIX_FMT_YUV422].convert = yuv420p_to_yuv422; + convert_table[PIX_FMT_YUV420P][PIX_FMT_YUV422].convert = yuv420p_to_yuv422; + convert_table[PIX_FMT_YUV420P][PIX_FMT_RGB555].convert = yuv420p_to_rgb555; + convert_table[PIX_FMT_YUV420P][PIX_FMT_RGB565].convert = yuv420p_to_rgb565; + convert_table[PIX_FMT_YUV420P][PIX_FMT_BGR24].convert = yuv420p_to_bgr24; + convert_table[PIX_FMT_YUV420P][PIX_FMT_RGB24].convert = yuv420p_to_rgb24; + convert_table[PIX_FMT_YUV420P][PIX_FMT_RGBA32].convert = yuv420p_to_rgba32; + convert_table[PIX_FMT_YUV420P][PIX_FMT_UYVY422].convert = yuv420p_to_uyvy422; + + convert_table[PIX_FMT_YUV422P][PIX_FMT_YUV422].convert = yuv422p_to_yuv422; + convert_table[PIX_FMT_YUV422P][PIX_FMT_UYVY422].convert = yuv422p_to_uyvy422; + + convert_table[PIX_FMT_YUV444P][PIX_FMT_RGB24].convert = yuv444p_to_rgb24; + + convert_table[PIX_FMT_YUVJ420P][PIX_FMT_RGB555].convert = yuvj420p_to_rgb555; + convert_table[PIX_FMT_YUVJ420P][PIX_FMT_RGB565].convert = yuvj420p_to_rgb565; + convert_table[PIX_FMT_YUVJ420P][PIX_FMT_BGR24].convert = yuvj420p_to_bgr24; + convert_table[PIX_FMT_YUVJ420P][PIX_FMT_RGB24].convert = yuvj420p_to_rgb24; + convert_table[PIX_FMT_YUVJ420P][PIX_FMT_RGBA32].convert = yuvj420p_to_rgba32; + + convert_table[PIX_FMT_YUVJ444P][PIX_FMT_RGB24].convert = yuvj444p_to_rgb24; + + convert_table[PIX_FMT_YUV422][PIX_FMT_YUV420P].convert = yuv422_to_yuv420p; + convert_table[PIX_FMT_YUV422][PIX_FMT_YUV422P].convert = yuv422_to_yuv422p; + + convert_table[PIX_FMT_UYVY422][PIX_FMT_YUV420P].convert = uyvy422_to_yuv420p; + convert_table[PIX_FMT_UYVY422][PIX_FMT_YUV422P].convert = uyvy422_to_yuv422p; + + convert_table[PIX_FMT_RGB24][PIX_FMT_YUV420P].convert = rgb24_to_yuv420p; + convert_table[PIX_FMT_RGB24][PIX_FMT_RGB565].convert = rgb24_to_rgb565; + convert_table[PIX_FMT_RGB24][PIX_FMT_RGB555].convert = rgb24_to_rgb555; + convert_table[PIX_FMT_RGB24][PIX_FMT_RGBA32].convert = rgb24_to_rgba32; + convert_table[PIX_FMT_RGB24][PIX_FMT_BGR24].convert = rgb24_to_bgr24; + convert_table[PIX_FMT_RGB24][PIX_FMT_GRAY8].convert = rgb24_to_gray; + convert_table[PIX_FMT_RGB24][PIX_FMT_PAL8].convert = rgb24_to_pal8; + convert_table[PIX_FMT_RGB24][PIX_FMT_YUV444P].convert = rgb24_to_yuv444p; + convert_table[PIX_FMT_RGB24][PIX_FMT_YUVJ420P].convert = rgb24_to_yuvj420p; + convert_table[PIX_FMT_RGB24][PIX_FMT_YUVJ444P].convert = rgb24_to_yuvj444p; + + convert_table[PIX_FMT_RGBA32][PIX_FMT_RGB24].convert = rgba32_to_rgb24; + convert_table[PIX_FMT_RGBA32][PIX_FMT_RGB555].convert = rgba32_to_rgb555; + convert_table[PIX_FMT_RGBA32][PIX_FMT_PAL8].convert = rgba32_to_pal8; + convert_table[PIX_FMT_RGBA32][PIX_FMT_YUV420P].convert = rgba32_to_yuv420p; + convert_table[PIX_FMT_RGBA32][PIX_FMT_GRAY8].convert = rgba32_to_gray; + + convert_table[PIX_FMT_BGR24][PIX_FMT_RGB24].convert = bgr24_to_rgb24; + convert_table[PIX_FMT_BGR24][PIX_FMT_YUV420P].convert = bgr24_to_yuv420p; + convert_table[PIX_FMT_BGR24][PIX_FMT_GRAY8].convert = bgr24_to_gray; + + convert_table[PIX_FMT_RGB555][PIX_FMT_RGB24].convert = rgb555_to_rgb24; + convert_table[PIX_FMT_RGB555][PIX_FMT_RGBA32].convert = rgb555_to_rgba32; + convert_table[PIX_FMT_RGB555][PIX_FMT_YUV420P].convert = rgb555_to_yuv420p; + convert_table[PIX_FMT_RGB555][PIX_FMT_GRAY8].convert = rgb555_to_gray; + + convert_table[PIX_FMT_RGB565][PIX_FMT_RGB24].convert = rgb565_to_rgb24; + convert_table[PIX_FMT_RGB565][PIX_FMT_YUV420P].convert = rgb565_to_yuv420p; + convert_table[PIX_FMT_RGB565][PIX_FMT_GRAY8].convert = rgb565_to_gray; + + convert_table[PIX_FMT_GRAY8][PIX_FMT_RGB555].convert = gray_to_rgb555; + convert_table[PIX_FMT_GRAY8][PIX_FMT_RGB565].convert = gray_to_rgb565; + convert_table[PIX_FMT_GRAY8][PIX_FMT_RGB24].convert = gray_to_rgb24; + convert_table[PIX_FMT_GRAY8][PIX_FMT_BGR24].convert = gray_to_bgr24; + convert_table[PIX_FMT_GRAY8][PIX_FMT_RGBA32].convert = gray_to_rgba32; + convert_table[PIX_FMT_GRAY8][PIX_FMT_MONOWHITE].convert = gray_to_monowhite; + convert_table[PIX_FMT_GRAY8][PIX_FMT_MONOBLACK].convert = gray_to_monoblack; + + convert_table[PIX_FMT_MONOWHITE][PIX_FMT_GRAY8].convert = monowhite_to_gray; + + convert_table[PIX_FMT_MONOBLACK][PIX_FMT_GRAY8].convert = monoblack_to_gray; + + convert_table[PIX_FMT_PAL8][PIX_FMT_RGB555].convert = pal8_to_rgb555; + convert_table[PIX_FMT_PAL8][PIX_FMT_RGB565].convert = pal8_to_rgb565; + convert_table[PIX_FMT_PAL8][PIX_FMT_BGR24].convert = pal8_to_bgr24; + convert_table[PIX_FMT_PAL8][PIX_FMT_RGB24].convert = pal8_to_rgb24; + convert_table[PIX_FMT_PAL8][PIX_FMT_RGBA32].convert = pal8_to_rgba32; + + convert_table[PIX_FMT_UYVY411][PIX_FMT_YUV411P].convert = uyvy411_to_yuv411p; +} + +static inline int is_yuv_planar(PixFmtInfo *ps) +{ + return (ps->color_type == FF_COLOR_YUV || ps->color_type == FF_COLOR_YUV_JPEG) + && ps->pixel_type == FF_PIXEL_PLANAR; +} + +int img_convert(AVPicture *dst, int dst_pix_fmt, const AVPicture *src, int src_pix_fmt, + int src_width, int src_height) +{ + static int inited; + int i, ret, dst_width, dst_height, int_pix_fmt; + PixFmtInfo *src_pix, *dst_pix; + ConvertEntry *ce; + AVPicture tmp1, *tmp = &tmp1; + + if (src_pix_fmt < 0 || src_pix_fmt >= PIX_FMT_NB || dst_pix_fmt < 0 || dst_pix_fmt >= PIX_FMT_NB) + return - 1; + + if (src_width <= 0 || src_height <= 0) + return 0; + + if (!inited) + { + inited = 1; + img_convert_init(); + } + + dst_width = src_width; + dst_height = src_height; + + dst_pix = &pix_fmt_info[dst_pix_fmt]; + src_pix = &pix_fmt_info[src_pix_fmt]; + + if (src_pix_fmt == dst_pix_fmt) // no conversion needed: just copy + { + img_copy(dst, src, dst_pix_fmt, dst_width, dst_height); + return 0; + } + + ce = &convert_table[src_pix_fmt][dst_pix_fmt]; + if (ce->convert) + { + ce->convert(dst, src, dst_width, dst_height); // specific conversion routine + return 0; + } + + if (is_yuv_planar(dst_pix) && src_pix_fmt == PIX_FMT_GRAY8) // gray to YUV + { + int w, h, y; + uint8_t *d; + + if (dst_pix->color_type == FF_COLOR_YUV_JPEG) + { + ff_img_copy_plane(dst->data[0], dst->linesize[0], src->data[0], src->linesize[0], + dst_width, dst_height); + } + else + { + img_apply_table(dst->data[0], dst->linesize[0], src->data[0], src->linesize[0], + dst_width, dst_height, y_jpeg_to_ccir); + } + + w = dst_width; // fill U and V with 128 + h = dst_height; + w >>= dst_pix->x_chroma_shift; + h >>= dst_pix->y_chroma_shift; + for (i = 1; i <= 2; i++) + { + d = dst->data[i]; + for (y = 0; y < h; y++) + { + memset(d, 128, w); + d += dst->linesize[i]; + } + } + return 0; + } + + if (is_yuv_planar(src_pix) && dst_pix_fmt == PIX_FMT_GRAY8) // YUV to gray + { + if (src_pix->color_type == FF_COLOR_YUV_JPEG) + { + ff_img_copy_plane(dst->data[0], dst->linesize[0], src->data[0], src->linesize[0], + dst_width, dst_height); + } + else + { + img_apply_table(dst->data[0], dst->linesize[0], src->data[0], src->linesize[0], + dst_width, dst_height, y_ccir_to_jpeg); + } + return 0; + } + + if (is_yuv_planar(dst_pix) && is_yuv_planar(src_pix)) // YUV to YUV planar + { + int x_shift, y_shift, w, h, xy_shift; + void(*resize_func)(uint8_t *dst, int dst_wrap, const uint8_t *src, int src_wrap, + int width, int height); + + // compute chroma size of the smallest dimensions + w = dst_width; + h = dst_height; + if (dst_pix->x_chroma_shift >= src_pix->x_chroma_shift) + w >>= dst_pix->x_chroma_shift; + else + w >>= src_pix->x_chroma_shift; + if (dst_pix->y_chroma_shift >= src_pix->y_chroma_shift) + h >>= dst_pix->y_chroma_shift; + else + h >>= src_pix->y_chroma_shift; + + x_shift = (dst_pix->x_chroma_shift - src_pix->x_chroma_shift); + y_shift = (dst_pix->y_chroma_shift - src_pix->y_chroma_shift); + xy_shift = ((x_shift &0xf) << 4) | (y_shift &0xf); + + // there must be filters for conversion at least from and to YUV444 format + switch (xy_shift) + { + case 0x00: + resize_func = ff_img_copy_plane; + break; + case 0x10: + resize_func = shrink21; + break; + case 0x20: + resize_func = shrink41; + break; + case 0x01: + resize_func = shrink12; + break; + case 0x11: + resize_func = ff_shrink22; + break; + case 0x22: + resize_func = ff_shrink44; + break; + case 0xf0: + resize_func = grow21; + break; + case 0xe0: + resize_func = grow41; + break; + case 0xff: + resize_func = grow22; + break; + case 0xee: + resize_func = grow44; + break; + case 0xf1: + resize_func = conv411; + break; + default: + goto no_chroma_filter; // currently not handled + } + + ff_img_copy_plane(dst->data[0], dst->linesize[0], src->data[0], src->linesize[0], + dst_width, dst_height); + + for (i = 1; i <= 2; i++) + resize_func(dst->data[i], dst->linesize[i], src->data[i], src->linesize[i], + dst_width >> dst_pix->x_chroma_shift, dst_height >> dst_pix->y_chroma_shift); + + // if yuv color space conversion is needed, we do it here on the destination image + if (dst_pix->color_type != src_pix->color_type) + { + const uint8_t *y_table, *c_table; + if (dst_pix->color_type == FF_COLOR_YUV) + { + y_table = y_jpeg_to_ccir; + c_table = c_jpeg_to_ccir; + } + else + { + y_table = y_ccir_to_jpeg; + c_table = c_ccir_to_jpeg; + } + + img_apply_table(dst->data[0], dst->linesize[0], dst->data[0], dst->linesize[0], + dst_width, dst_height, y_table); + + for (i = 1; i <= 2; i++) + img_apply_table(dst->data[i], dst->linesize[i], dst->data[i], dst->linesize[i], + dst_width >> dst_pix->x_chroma_shift, dst_height >> dst_pix->y_chroma_shift, c_table); + } + return 0; + } + +no_chroma_filter: // try to use an intermediate format + + if (src_pix_fmt == PIX_FMT_YUV422 || dst_pix_fmt == PIX_FMT_YUV422) + { + int_pix_fmt = PIX_FMT_YUV422P; // specific case: convert to YUV422P first + } + else if (src_pix_fmt == PIX_FMT_UYVY422 || dst_pix_fmt == PIX_FMT_UYVY422) + { + + int_pix_fmt = PIX_FMT_YUV422P; // specific case: convert to YUV422P first + } + else if (src_pix_fmt == PIX_FMT_UYVY411 || dst_pix_fmt == PIX_FMT_UYVY411) + { + + int_pix_fmt = PIX_FMT_YUV411P; // specific case: convert to YUV411P first + } + else if ((src_pix->color_type == FF_COLOR_GRAY && src_pix_fmt != PIX_FMT_GRAY8) + || (dst_pix->color_type == FF_COLOR_GRAY && dst_pix_fmt != PIX_FMT_GRAY8)) + { + + int_pix_fmt = PIX_FMT_GRAY8; // gray8 is the normalized format + } + else if ((is_yuv_planar(src_pix) && src_pix_fmt != PIX_FMT_YUV444P + && src_pix_fmt != PIX_FMT_YUVJ444P)) + { + if (src_pix->color_type == FF_COLOR_YUV_JPEG) // yuv444 is the normalized format + int_pix_fmt = PIX_FMT_YUVJ444P; + else + int_pix_fmt = PIX_FMT_YUV444P; + } + else if ((is_yuv_planar(dst_pix) && dst_pix_fmt != PIX_FMT_YUV444P + && dst_pix_fmt != PIX_FMT_YUVJ444P)) + { + if (dst_pix->color_type == FF_COLOR_YUV_JPEG) // yuv444 is the normalized format + int_pix_fmt = PIX_FMT_YUVJ444P; + else + int_pix_fmt = PIX_FMT_YUV444P; + } + else // the two formats are rgb or gray8 or yuv[j]444p + { + if (src_pix->is_alpha && dst_pix->is_alpha) + int_pix_fmt = PIX_FMT_RGBA32; + else + int_pix_fmt = PIX_FMT_RGB24; + } + + if (avpicture_alloc(tmp, int_pix_fmt, dst_width, dst_height) < 0) + return - 1; + + ret = - 1; + + if (img_convert(tmp, int_pix_fmt, src, src_pix_fmt, src_width, src_height) < 0) + goto fail1; + + if (img_convert(dst, dst_pix_fmt, tmp, int_pix_fmt, dst_width, dst_height) < 0) + goto fail1; + ret = 0; + +fail1: + avpicture_free(tmp); + return ret; +} + +#undef FIX diff --git a/ffplay源码和书籍/ffplay/libavcodec/imgconvert_template.h b/ffplay源码和书籍/ffplay/libavcodec/imgconvert_template.h new file mode 100644 index 0000000..3bbef9c --- /dev/null +++ b/ffplay源码和书籍/ffplay/libavcodec/imgconvert_template.h @@ -0,0 +1,887 @@ +#ifndef RGB_OUT +#define RGB_OUT(d, r, g, b) RGBA_OUT(d, r, g, b, 0xff) +#endif + +/************************************************************************/ +/* 岢ʵͼɫռתʹõĺͺ */ +/************************************************************************/ +#pragma warning (disable:4305 4244) + +static void glue(yuv420p_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src, int width, int height) +{ + const uint8_t *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr; + uint8_t *d, *d1, *d2; + int w, y, cb, cr, r_add, g_add, b_add, width2; + uint8_t *cm = cropTbl + MAX_NEG_CROP; + unsigned int r, g, b; + + d = dst->data[0]; + y1_ptr = src->data[0]; + cb_ptr = src->data[1]; + cr_ptr = src->data[2]; + width2 = (width + 1) >> 1; + + for (; height >= 2; height -= 2) + { + d1 = d; + d2 = d + dst->linesize[0]; + y2_ptr = y1_ptr + src->linesize[0]; + for (w = width; w >= 2; w -= 2) + { + YUV_TO_RGB1_CCIR(cb_ptr[0], cr_ptr[0]); + + YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[0]); /* output 4 pixels */ + RGB_OUT(d1, r, g, b); + + YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[1]); + RGB_OUT(d1 + BPP, r, g, b); + + YUV_TO_RGB2_CCIR(r, g, b, y2_ptr[0]); + RGB_OUT(d2, r, g, b); + + YUV_TO_RGB2_CCIR(r, g, b, y2_ptr[1]); + RGB_OUT(d2 + BPP, r, g, b); + + d1 += 2 * BPP; + d2 += 2 * BPP; + + y1_ptr += 2; + y2_ptr += 2; + cb_ptr++; + cr_ptr++; + } + + if (w) /* handle odd width */ + { + YUV_TO_RGB1_CCIR(cb_ptr[0], cr_ptr[0]); + YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[0]); + RGB_OUT(d1, r, g, b); + + YUV_TO_RGB2_CCIR(r, g, b, y2_ptr[0]); + RGB_OUT(d2, r, g, b); + d1 += BPP; + d2 += BPP; + y1_ptr++; + y2_ptr++; + cb_ptr++; + cr_ptr++; + } + d += 2 * dst->linesize[0]; + y1_ptr += 2 * src->linesize[0] - width; + cb_ptr += src->linesize[1] - width2; + cr_ptr += src->linesize[2] - width2; + } + + if (height) /* handle odd height */ + { + d1 = d; + for (w = width; w >= 2; w -= 2) + { + YUV_TO_RGB1_CCIR(cb_ptr[0], cr_ptr[0]); + + YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[0]); /* output 2 pixels */ + RGB_OUT(d1, r, g, b); + + YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[1]); + RGB_OUT(d1 + BPP, r, g, b); + + d1 += 2 * BPP; + + y1_ptr += 2; + cb_ptr++; + cr_ptr++; + } + + if (w) /* handle width */ + { + YUV_TO_RGB1_CCIR(cb_ptr[0], cr_ptr[0]); + + YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[0]); /* output 2 pixels */ + RGB_OUT(d1, r, g, b); + d1 += BPP; + + y1_ptr++; + cb_ptr++; + cr_ptr++; + } + } +} + +static void glue(yuvj420p_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src, int width, int height) +{ + const uint8_t *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr; + uint8_t *d, *d1, *d2; + int w, y, cb, cr, r_add, g_add, b_add, width2; + uint8_t *cm = cropTbl + MAX_NEG_CROP; + unsigned int r, g, b; + + d = dst->data[0]; + y1_ptr = src->data[0]; + cb_ptr = src->data[1]; + cr_ptr = src->data[2]; + width2 = (width + 1) >> 1; + + for (; height >= 2; height -= 2) + { + d1 = d; + d2 = d + dst->linesize[0]; + y2_ptr = y1_ptr + src->linesize[0]; + for (w = width; w >= 2; w -= 2) + { + YUV_TO_RGB1(cb_ptr[0], cr_ptr[0]); + + YUV_TO_RGB2(r, g, b, y1_ptr[0]); /* output 4 pixels */ + RGB_OUT(d1, r, g, b); + + YUV_TO_RGB2(r, g, b, y1_ptr[1]); + RGB_OUT(d1 + BPP, r, g, b); + + YUV_TO_RGB2(r, g, b, y2_ptr[0]); + RGB_OUT(d2, r, g, b); + + YUV_TO_RGB2(r, g, b, y2_ptr[1]); + RGB_OUT(d2 + BPP, r, g, b); + + d1 += 2 * BPP; + d2 += 2 * BPP; + + y1_ptr += 2; + y2_ptr += 2; + cb_ptr++; + cr_ptr++; + } + + if (w) /* handle odd width */ + { + YUV_TO_RGB1(cb_ptr[0], cr_ptr[0]); + YUV_TO_RGB2(r, g, b, y1_ptr[0]); + RGB_OUT(d1, r, g, b); + + YUV_TO_RGB2(r, g, b, y2_ptr[0]); + RGB_OUT(d2, r, g, b); + d1 += BPP; + d2 += BPP; + y1_ptr++; + y2_ptr++; + cb_ptr++; + cr_ptr++; + } + d += 2 * dst->linesize[0]; + y1_ptr += 2 * src->linesize[0] - width; + cb_ptr += src->linesize[1] - width2; + cr_ptr += src->linesize[2] - width2; + } + + if (height) /* handle odd height */ + { + d1 = d; + for (w = width; w >= 2; w -= 2) + { + YUV_TO_RGB1(cb_ptr[0], cr_ptr[0]); + + YUV_TO_RGB2(r, g, b, y1_ptr[0]); /* output 2 pixels */ + RGB_OUT(d1, r, g, b); + + YUV_TO_RGB2(r, g, b, y1_ptr[1]); + RGB_OUT(d1 + BPP, r, g, b); + + d1 += 2 * BPP; + + y1_ptr += 2; + cb_ptr++; + cr_ptr++; + } + + if (w) /* handle width */ + { + YUV_TO_RGB1(cb_ptr[0], cr_ptr[0]); + + YUV_TO_RGB2(r, g, b, y1_ptr[0]); /* output 2 pixels */ + RGB_OUT(d1, r, g, b); + d1 += BPP; + + y1_ptr++; + cb_ptr++; + cr_ptr++; + } + } +} + +static void glue(RGB_NAME, _to_yuv420p)(AVPicture *dst, const AVPicture *src, int width, int height) +{ + int wrap, wrap3, width2; + int r, g, b, r1, g1, b1, w; + uint8_t *lum, *cb, *cr; + const uint8_t *p; + + lum = dst->data[0]; + cb = dst->data[1]; + cr = dst->data[2]; + + width2 = (width + 1) >> 1; + wrap = dst->linesize[0]; + wrap3 = src->linesize[0]; + p = src->data[0]; + for (; height >= 2; height -= 2) + { + for (w = width; w >= 2; w -= 2) + { + RGB_IN(r, g, b, p); + r1 = r; + g1 = g; + b1 = b; + lum[0] = RGB_TO_Y_CCIR(r, g, b); + + RGB_IN(r, g, b, p + BPP); + r1 += r; + g1 += g; + b1 += b; + lum[1] = RGB_TO_Y_CCIR(r, g, b); + p += wrap3; + lum += wrap; + + RGB_IN(r, g, b, p); + r1 += r; + g1 += g; + b1 += b; + lum[0] = RGB_TO_Y_CCIR(r, g, b); + + RGB_IN(r, g, b, p + BPP); + r1 += r; + g1 += g; + b1 += b; + lum[1] = RGB_TO_Y_CCIR(r, g, b); + + cb[0] = RGB_TO_U_CCIR(r1, g1, b1, 2); + cr[0] = RGB_TO_V_CCIR(r1, g1, b1, 2); + + cb++; + cr++; + p += - wrap3 + 2 * BPP; + lum += - wrap + 2; + } + if (w) + { + RGB_IN(r, g, b, p); + r1 = r; + g1 = g; + b1 = b; + lum[0] = RGB_TO_Y_CCIR(r, g, b); + p += wrap3; + lum += wrap; + RGB_IN(r, g, b, p); + r1 += r; + g1 += g; + b1 += b; + lum[0] = RGB_TO_Y_CCIR(r, g, b); + cb[0] = RGB_TO_U_CCIR(r1, g1, b1, 1); + cr[0] = RGB_TO_V_CCIR(r1, g1, b1, 1); + cb++; + cr++; + p += - wrap3 + BPP; + lum += - wrap + 1; + } + p += wrap3 + (wrap3 - width * BPP); + lum += wrap + (wrap - width); + cb += dst->linesize[1] - width2; + cr += dst->linesize[2] - width2; + } + + if (height) /* handle odd height */ + { + for (w = width; w >= 2; w -= 2) + { + RGB_IN(r, g, b, p); + r1 = r; + g1 = g; + b1 = b; + lum[0] = RGB_TO_Y_CCIR(r, g, b); + + RGB_IN(r, g, b, p + BPP); + r1 += r; + g1 += g; + b1 += b; + lum[1] = RGB_TO_Y_CCIR(r, g, b); + cb[0] = RGB_TO_U_CCIR(r1, g1, b1, 1); + cr[0] = RGB_TO_V_CCIR(r1, g1, b1, 1); + cb++; + cr++; + p += 2 * BPP; + lum += 2; + } + if (w) + { + RGB_IN(r, g, b, p); + lum[0] = RGB_TO_Y_CCIR(r, g, b); + cb[0] = RGB_TO_U_CCIR(r, g, b, 0); + cr[0] = RGB_TO_V_CCIR(r, g, b, 0); + } + } +} + +static void glue(RGB_NAME, _to_gray)(AVPicture *dst, const AVPicture *src, int width, int height) +{ + const unsigned char *p; + unsigned char *q; + int r, g, b, dst_wrap, src_wrap; + int x, y; + + p = src->data[0]; + src_wrap = src->linesize[0] - BPP * width; + + q = dst->data[0]; + dst_wrap = dst->linesize[0] - width; + + for (y = 0; y < height; y++) + { + for (x = 0; x < width; x++) + { + RGB_IN(r, g, b, p); + q[0] = RGB_TO_Y(r, g, b); + q++; + p += BPP; + } + p += src_wrap; + q += dst_wrap; + } +} + +static void glue(gray_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src, int width, int height) +{ + const unsigned char *p; + unsigned char *q; + int r, dst_wrap, src_wrap; + int x, y; + + p = src->data[0]; + src_wrap = src->linesize[0] - width; + + q = dst->data[0]; + dst_wrap = dst->linesize[0] - BPP * width; + + for (y = 0; y < height; y++) + { + for (x = 0; x < width; x++) + { + r = p[0]; + RGB_OUT(q, r, r, r); + q += BPP; + p++; + } + p += src_wrap; + q += dst_wrap; + } +} + +static void glue(pal8_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src, int width, int height) +{ + const unsigned char *p; + unsigned char *q; + int r, g, b, dst_wrap, src_wrap; + int x, y; + uint32_t v; + const uint32_t *palette; + + p = src->data[0]; + src_wrap = src->linesize[0] - width; + palette = (uint32_t*)src->data[1]; + + q = dst->data[0]; + dst_wrap = dst->linesize[0] - BPP * width; + + for (y = 0; y < height; y++) + { + for (x = 0; x < width; x++) + { + v = palette[p[0]]; + r = (v >> 16) &0xff; + g = (v >> 8) &0xff; + b = (v) &0xff; +#ifdef RGBA_OUT + { + int a; + a = (v >> 24) &0xff; + RGBA_OUT(q, r, g, b, a); + } +#else + RGB_OUT(q, r, g, b); +#endif + q += BPP; + p++; + } + p += src_wrap; + q += dst_wrap; + } +} + +#if !defined(FMT_RGBA32) && defined(RGBA_OUT) +/* alpha support */ + +static void glue(rgba32_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src, int width, int height) +{ + const uint8_t *s; + uint8_t *d; + int src_wrap, dst_wrap, j, y; + unsigned int v, r, g, b, a; + + s = src->data[0]; + src_wrap = src->linesize[0] - width * 4; + + d = dst->data[0]; + dst_wrap = dst->linesize[0] - width * BPP; + + for (y = 0; y < height; y++) + { + for (j = 0; j < width; j++) + { + v = ((const uint32_t*)(s))[0]; + a = (v >> 24) &0xff; + r = (v >> 16) &0xff; + g = (v >> 8) &0xff; + b = v &0xff; + RGBA_OUT(d, r, g, b, a); + s += 4; + d += BPP; + } + s += src_wrap; + d += dst_wrap; + } +} + +static void glue(RGB_NAME, _to_rgba32)(AVPicture *dst, const AVPicture *src, int width, int height) +{ + const uint8_t *s; + uint8_t *d; + int src_wrap, dst_wrap, j, y; + unsigned int r, g, b, a; + + s = src->data[0]; + src_wrap = src->linesize[0] - width * BPP; + + d = dst->data[0]; + dst_wrap = dst->linesize[0] - width * 4; + + for (y = 0; y < height; y++) + { + for (j = 0; j < width; j++) + { + RGBA_IN(r, g, b, a, s); + ((uint32_t*)(d))[0] = (a << 24) | (r << 16) | (g << 8) | b; + d += 4; + s += BPP; + } + s += src_wrap; + d += dst_wrap; + } +} + +#endif /* !defined(FMT_RGBA32) && defined(RGBA_IN) */ + +#ifndef FMT_RGB24 + +static void glue(rgb24_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src, int width, int height) +{ + const uint8_t *s; + uint8_t *d; + int src_wrap, dst_wrap, j, y; + unsigned int r, g, b; + + s = src->data[0]; + src_wrap = src->linesize[0] - width * 3; + + d = dst->data[0]; + dst_wrap = dst->linesize[0] - width * BPP; + + for (y = 0; y < height; y++) + { + for (j = 0; j < width; j++) + { + r = s[0]; + g = s[1]; + b = s[2]; + RGB_OUT(d, r, g, b); + s += 3; + d += BPP; + } + s += src_wrap; + d += dst_wrap; + } +} + +static void glue(RGB_NAME, _to_rgb24)(AVPicture *dst, const AVPicture *src, int width, int height) +{ + const uint8_t *s; + uint8_t *d; + int src_wrap, dst_wrap, j, y; + unsigned int r, g, b; + + s = src->data[0]; + src_wrap = src->linesize[0] - width * BPP; + + d = dst->data[0]; + dst_wrap = dst->linesize[0] - width * 3; + + for (y = 0; y < height; y++) + { + for (j = 0; j < width; j++) + { + RGB_IN(r, g, b, s)d[0] = r; + d[1] = g; + d[2] = b; + d += 3; + s += BPP; + } + s += src_wrap; + d += dst_wrap; + } +} + +#endif /* !FMT_RGB24 */ + +#ifdef FMT_RGB24 + +static void yuv444p_to_rgb24(AVPicture *dst, const AVPicture *src, int width, int height) +{ + const uint8_t *y1_ptr, *cb_ptr, *cr_ptr; + uint8_t *d, *d1; + int w, y, cb, cr, r_add, g_add, b_add; + uint8_t *cm = cropTbl + MAX_NEG_CROP; + unsigned int r, g, b; + + d = dst->data[0]; + y1_ptr = src->data[0]; + cb_ptr = src->data[1]; + cr_ptr = src->data[2]; + for (; height > 0; height--) + { + d1 = d; + for (w = width; w > 0; w--) + { + YUV_TO_RGB1_CCIR(cb_ptr[0], cr_ptr[0]); + + YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[0]); + RGB_OUT(d1, r, g, b); + d1 += BPP; + + y1_ptr++; + cb_ptr++; + cr_ptr++; + } + d += dst->linesize[0]; + y1_ptr += src->linesize[0] - width; + cb_ptr += src->linesize[1] - width; + cr_ptr += src->linesize[2] - width; + } +} + +static void yuvj444p_to_rgb24(AVPicture *dst, const AVPicture *src, int width, int height) +{ + const uint8_t *y1_ptr, *cb_ptr, *cr_ptr; + uint8_t *d, *d1; + int w, y, cb, cr, r_add, g_add, b_add; + uint8_t *cm = cropTbl + MAX_NEG_CROP; + unsigned int r, g, b; + + d = dst->data[0]; + y1_ptr = src->data[0]; + cb_ptr = src->data[1]; + cr_ptr = src->data[2]; + for (; height > 0; height--) + { + d1 = d; + for (w = width; w > 0; w--) + { + YUV_TO_RGB1(cb_ptr[0], cr_ptr[0]); + + YUV_TO_RGB2(r, g, b, y1_ptr[0]); + RGB_OUT(d1, r, g, b); + d1 += BPP; + + y1_ptr++; + cb_ptr++; + cr_ptr++; + } + d += dst->linesize[0]; + y1_ptr += src->linesize[0] - width; + cb_ptr += src->linesize[1] - width; + cr_ptr += src->linesize[2] - width; + } +} + +static void rgb24_to_yuv444p(AVPicture *dst, const AVPicture *src, int width, int height) +{ + int src_wrap, x, y; + int r, g, b; + uint8_t *lum, *cb, *cr; + const uint8_t *p; + + lum = dst->data[0]; + cb = dst->data[1]; + cr = dst->data[2]; + + src_wrap = src->linesize[0] - width * BPP; + p = src->data[0]; + + for (y = 0; y < height; y++) + { + for (x = 0; x < width; x++) + { + RGB_IN(r, g, b, p); + lum[0] = RGB_TO_Y_CCIR(r, g, b); + cb[0] = RGB_TO_U_CCIR(r, g, b, 0); + cr[0] = RGB_TO_V_CCIR(r, g, b, 0); + p += BPP; + cb++; + cr++; + lum++; + } + p += src_wrap; + lum += dst->linesize[0] - width; + cb += dst->linesize[1] - width; + cr += dst->linesize[2] - width; + } +} + +static void rgb24_to_yuvj420p(AVPicture *dst, const AVPicture *src, int width, int height) +{ + int wrap, wrap3, width2; + int r, g, b, r1, g1, b1, w; + uint8_t *lum, *cb, *cr; + const uint8_t *p; + + lum = dst->data[0]; + cb = dst->data[1]; + cr = dst->data[2]; + + width2 = (width + 1) >> 1; + wrap = dst->linesize[0]; + wrap3 = src->linesize[0]; + p = src->data[0]; + for (; height >= 2; height -= 2) + { + for (w = width; w >= 2; w -= 2) + { + RGB_IN(r, g, b, p); + r1 = r; + g1 = g; + b1 = b; + lum[0] = RGB_TO_Y(r, g, b); + + RGB_IN(r, g, b, p + BPP); + r1 += r; + g1 += g; + b1 += b; + lum[1] = RGB_TO_Y(r, g, b); + p += wrap3; + lum += wrap; + + RGB_IN(r, g, b, p); + r1 += r; + g1 += g; + b1 += b; + lum[0] = RGB_TO_Y(r, g, b); + + RGB_IN(r, g, b, p + BPP); + r1 += r; + g1 += g; + b1 += b; + lum[1] = RGB_TO_Y(r, g, b); + + cb[0] = RGB_TO_U(r1, g1, b1, 2); + cr[0] = RGB_TO_V(r1, g1, b1, 2); + + cb++; + cr++; + p += - wrap3 + 2 * BPP; + lum += - wrap + 2; + } + if (w) + { + RGB_IN(r, g, b, p); + r1 = r; + g1 = g; + b1 = b; + lum[0] = RGB_TO_Y(r, g, b); + p += wrap3; + lum += wrap; + RGB_IN(r, g, b, p); + r1 += r; + g1 += g; + b1 += b; + lum[0] = RGB_TO_Y(r, g, b); + cb[0] = RGB_TO_U(r1, g1, b1, 1); + cr[0] = RGB_TO_V(r1, g1, b1, 1); + cb++; + cr++; + p += - wrap3 + BPP; + lum += - wrap + 1; + } + p += wrap3 + (wrap3 - width * BPP); + lum += wrap + (wrap - width); + cb += dst->linesize[1] - width2; + cr += dst->linesize[2] - width2; + } + + if (height) /* handle odd height */ + { + for (w = width; w >= 2; w -= 2) + { + RGB_IN(r, g, b, p); + r1 = r; + g1 = g; + b1 = b; + lum[0] = RGB_TO_Y(r, g, b); + + RGB_IN(r, g, b, p + BPP); + r1 += r; + g1 += g; + b1 += b; + lum[1] = RGB_TO_Y(r, g, b); + cb[0] = RGB_TO_U(r1, g1, b1, 1); + cr[0] = RGB_TO_V(r1, g1, b1, 1); + cb++; + cr++; + p += 2 * BPP; + lum += 2; + } + if (w) + { + RGB_IN(r, g, b, p); + lum[0] = RGB_TO_Y(r, g, b); + cb[0] = RGB_TO_U(r, g, b, 0); + cr[0] = RGB_TO_V(r, g, b, 0); + } + } +} + +static void rgb24_to_yuvj444p(AVPicture *dst, const AVPicture *src, int width, int height) +{ + int src_wrap, x, y; + int r, g, b; + uint8_t *lum, *cb, *cr; + const uint8_t *p; + + lum = dst->data[0]; + cb = dst->data[1]; + cr = dst->data[2]; + + src_wrap = src->linesize[0] - width * BPP; + p = src->data[0]; + for (y = 0; y < height; y++) + { + for (x = 0; x < width; x++) + { + RGB_IN(r, g, b, p); + lum[0] = RGB_TO_Y(r, g, b); + cb[0] = RGB_TO_U(r, g, b, 0); + cr[0] = RGB_TO_V(r, g, b, 0); + p += BPP; + cb++; + cr++; + lum++; + } + p += src_wrap; + lum += dst->linesize[0] - width; + cb += dst->linesize[1] - width; + cr += dst->linesize[2] - width; + } +} + +#endif /* FMT_RGB24 */ + +#if defined(FMT_RGB24) || defined(FMT_RGBA32) + +static void glue(RGB_NAME, _to_pal8)(AVPicture *dst, const AVPicture *src, int width, int height) +{ + const unsigned char *p; + unsigned char *q; + int dst_wrap, src_wrap; + int x, y, has_alpha; + unsigned int r, g, b; + + p = src->data[0]; + src_wrap = src->linesize[0] - BPP * width; + + q = dst->data[0]; + dst_wrap = dst->linesize[0] - width; + has_alpha = 0; + + for (y = 0; y < height; y++) + { + for (x = 0; x < width; x++) + { +#ifdef RGBA_IN + { + unsigned int a; + RGBA_IN(r, g, b, a, p); + + if (a < 0x80) /* crude approximation for alpha ! */ + { + has_alpha = 1; + q[0] = TRANSP_INDEX; + } + else + { + q[0] = gif_clut_index(r, g, b); + } + } +#else + RGB_IN(r, g, b, p); + q[0] = gif_clut_index(r, g, b); +#endif + q++; + p += BPP; + } + p += src_wrap; + q += dst_wrap; + } + + build_rgb_palette(dst->data[1], has_alpha); +} + +#endif /* defined(FMT_RGB24) || defined(FMT_RGBA32) */ + +#ifdef RGBA_IN + +#define FF_ALPHA_TRANSP 0x0001 /* image has some totally transparent pixels */ +#define FF_ALPHA_SEMI_TRANSP 0x0002 /* image has some transparent pixels */ + +static int glue(get_alpha_info_, RGB_NAME)(const AVPicture *src, int width, int height) +{ + const unsigned char *p; + int src_wrap, ret, x, y; + unsigned int r, g, b, a; + + p = src->data[0]; + src_wrap = src->linesize[0] - BPP * width; + ret = 0; + for (y = 0; y < height; y++) + { + for (x = 0; x < width; x++) + { + RGBA_IN(r, g, b, a, p); + if (a == 0x00) + { + ret |= FF_ALPHA_TRANSP; + } + else if (a != 0xff) + { + ret |= FF_ALPHA_SEMI_TRANSP; + } + p += BPP; + } + p += src_wrap; + } + return ret; +} + +#endif /* RGBA_IN */ + +#undef RGB_IN +#undef RGBA_IN +#undef RGB_OUT +#undef RGBA_OUT +#undef BPP +#undef RGB_NAME +#undef FMT_RGB24 +#undef FMT_RGBA32 diff --git a/ffplay源码和书籍/ffplay/libavcodec/msrle.c b/ffplay源码和书籍/ffplay/libavcodec/msrle.c new file mode 100644 index 0000000..e68a496 --- /dev/null +++ b/ffplay源码和书籍/ffplay/libavcodec/msrle.c @@ -0,0 +1,305 @@ +/* +** ļʵ΢г̳ѹ㷨 +*/ +#include +#include +#include + +#include "../libavutil/common.h" +#include "avcodec.h" +#include "dsputil.h" + +#define FF_BUFFER_HINTS_VALID 0x01 // Buffer hints value is meaningful (if 0 ignore) +#define FF_BUFFER_HINTS_READABLE 0x02 // Codec will read from buffer +#define FF_BUFFER_HINTS_PRESERVE 0x04 // User must not alter buffer content +#define FF_BUFFER_HINTS_REUSABLE 0x08 // Codec will reuse the buffer (update) + +/* Msrle */ +typedef struct MsrleContext +{ + // ĽģAVCodecContextһȽϳĸMsrleContextһȽϾĸ + AVCodecContext *avctx; + + // ֡ + AVFrame frame; + + unsigned char *buf; + int size; + +} MsrleContext; + +#define FETCH_NEXT_STREAM_BYTE() \ + if (stream_ptr >= s->size) \ + { \ + return; \ + } \ + stream_byte = s->buf[stream_ptr++]; + +static void msrle_decode_pal4(MsrleContext *s) +{ + int stream_ptr = 0; + unsigned char rle_code; + unsigned char extra_byte, odd_pixel; + unsigned char stream_byte; + int pixel_ptr = 0; + int row_dec = s->frame.linesize[0]; + int row_ptr = (s->avctx->height - 1) *row_dec; + int frame_size = row_dec * s->avctx->height; + int i; + + // make the palette available + memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE); + if (s->avctx->palctrl->palette_changed) + { +// s->frame.palette_has_changed = 1; + s->avctx->palctrl->palette_changed = 0; + } + + while (row_ptr >= 0) + { + FETCH_NEXT_STREAM_BYTE(); + rle_code = stream_byte; + if (rle_code == 0) + { + // fetch the next byte to see how to handle escape code + FETCH_NEXT_STREAM_BYTE(); + if (stream_byte == 0) + { + // line is done, goto the next one + row_ptr -= row_dec; + pixel_ptr = 0; + } + else if (stream_byte == 1) + { + // decode is done + return ; + } + else if (stream_byte == 2) + { + // reposition frame decode coordinates + FETCH_NEXT_STREAM_BYTE(); + pixel_ptr += stream_byte; + FETCH_NEXT_STREAM_BYTE(); + row_ptr -= stream_byte * row_dec; + } + else + { + // copy pixels from encoded stream + odd_pixel = stream_byte &1; + rle_code = (stream_byte + 1) / 2; + extra_byte = rle_code &0x01; + if ((row_ptr + pixel_ptr + stream_byte > frame_size) || (row_ptr < 0)) + { + return ; + } + + for (i = 0; i < rle_code; i++) + { + if (pixel_ptr >= s->avctx->width) + break; + FETCH_NEXT_STREAM_BYTE(); + s->frame.data[0][row_ptr + pixel_ptr] = stream_byte >> 4; + pixel_ptr++; + if (i + 1 == rle_code && odd_pixel) + break; + if (pixel_ptr >= s->avctx->width) + break; + s->frame.data[0][row_ptr + pixel_ptr] = stream_byte &0x0F; + pixel_ptr++; + } + + // if the RLE code is odd, skip a byte in the stream + if (extra_byte) + stream_ptr++; + } + } + else + { + // decode a run of data + if ((row_ptr + pixel_ptr + stream_byte > frame_size) || (row_ptr < 0)) + { + return ; + } + FETCH_NEXT_STREAM_BYTE(); + for (i = 0; i < rle_code; i++) + { + if (pixel_ptr >= s->avctx->width) + break; + if ((i &1) == 0) + s->frame.data[0][row_ptr + pixel_ptr] = stream_byte >> 4; + else + s->frame.data[0][row_ptr + pixel_ptr] = stream_byte &0x0F; + pixel_ptr++; + } + } + } + + // one last sanity check on the way out + if (stream_ptr < s->size) + { + // error + } +} + +static void msrle_decode_pal8(MsrleContext *s) +{ + int stream_ptr = 0; + unsigned char rle_code; + unsigned char extra_byte; + unsigned char stream_byte; + int pixel_ptr = 0; + int row_dec = s->frame.linesize[0]; + int row_ptr = (s->avctx->height - 1) *row_dec; + int frame_size = row_dec * s->avctx->height; + + // make the palette available + memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE); + if (s->avctx->palctrl->palette_changed) + { +// s->frame.palette_has_changed = 1; + s->avctx->palctrl->palette_changed = 0; + } + + while (row_ptr >= 0) + { + FETCH_NEXT_STREAM_BYTE(); + rle_code = stream_byte; + if (rle_code == 0) + { + // fetch the next byte to see how to handle escape code + FETCH_NEXT_STREAM_BYTE(); + if (stream_byte == 0) + { + // line is done, goto the next one + row_ptr -= row_dec; + pixel_ptr = 0; + } + else if (stream_byte == 1) + { + // decode is done + return ; + } + else if (stream_byte == 2) + { + // reposition frame decode coordinates + FETCH_NEXT_STREAM_BYTE(); + pixel_ptr += stream_byte; + FETCH_NEXT_STREAM_BYTE(); + row_ptr -= stream_byte * row_dec; + } + else + { + // copy pixels from encoded stream + if ((row_ptr + pixel_ptr + stream_byte > frame_size) || (row_ptr < 0)) + { + return ; + } + + rle_code = stream_byte; + extra_byte = stream_byte &0x01; + if (stream_ptr + rle_code + extra_byte > s->size) + { + return ; + } + + while (rle_code--) + { + FETCH_NEXT_STREAM_BYTE(); + s->frame.data[0][row_ptr + pixel_ptr] = stream_byte; + pixel_ptr++; + } + + // if the RLE code is odd, skip a byte in the stream + if (extra_byte) + stream_ptr++; + } + } + else + { + // decode a run of data + if ((row_ptr + pixel_ptr + stream_byte > frame_size) || (row_ptr < 0)) + { + return ; + } + + FETCH_NEXT_STREAM_BYTE(); + + while (rle_code--) + { + s->frame.data[0][row_ptr + pixel_ptr] = stream_byte; + pixel_ptr++; + } + } + } + + // one last sanity check on the way out + if (stream_ptr < s->size) + { + // error + } +} + +static int msrle_decode_init(AVCodecContext *avctx) +{ + MsrleContext *s = (MsrleContext*)avctx->priv_data; + + s->avctx = avctx; + + avctx->pix_fmt = PIX_FMT_PAL8; + + s->frame.data[0] = NULL; + + return 0; +} + +static int msrle_decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8_t *buf, int buf_size) +{ + MsrleContext *s = (MsrleContext*)avctx->priv_data; + + s->buf = buf; + s->size = buf_size; + + if (avctx->reget_buffer(avctx, &s->frame)) + return - 1; + + switch (avctx->bits_per_sample) + { + case 8: + msrle_decode_pal8(s); + break; + case 4: + msrle_decode_pal4(s); + break; + default: + break; + } + + *data_size = sizeof(AVFrame); + *(AVFrame*)data = s->frame; + + // report that the buffer was completely consumed + return buf_size; +} + +static int msrle_decode_end(AVCodecContext *avctx) +{ + MsrleContext *s = (MsrleContext*)avctx->priv_data; + + // release the last frame + if (s->frame.data[0]) + avctx->release_buffer(avctx, &s->frame); + + return 0; +} + +AVCodec msrle_decoder = +{ + "msrle", + CODEC_TYPE_VIDEO, + CODEC_ID_MSRLE, + sizeof(MsrleContext), + msrle_decode_init, + NULL, + msrle_decode_end, + msrle_decode_frame +}; diff --git a/ffplay源码和书籍/ffplay/libavcodec/truespeech.c b/ffplay源码和书籍/ffplay/libavcodec/truespeech.c new file mode 100644 index 0000000..446f8e0 --- /dev/null +++ b/ffplay源码和书籍/ffplay/libavcodec/truespeech.c @@ -0,0 +1,380 @@ +/************************************************************************/ +/* ļʵ truespeed Ƶ */ +/************************************************************************/ +#include "avcodec.h" + +#include "truespeech_data.h" + +// TrueSpeech decoder context + +typedef struct TSContext +{ + // input data + int16_t vector[8]; // input vector: 5/5/4/4/4/3/3/3 + int offset1[2]; // 8-bit value, used in one copying offset + int offset2[4]; // 7-bit value, encodes offsets for copying and for two-point filter + int pulseoff[4]; // 4-bit offset of pulse values block + int pulsepos[4]; // 27-bit variable, encodes 7 pulse positions + int pulseval[4]; // 7x2-bit pulse values + int flag; // 1-bit flag, shows how to choose filters + // temporary data + int filtbuf[146]; // some big vector used for storing filters + int prevfilt[8]; // filter from previous frame + int16_t tmp1[8]; // coefficients for adding to out + int16_t tmp2[8]; // coefficients for adding to out + int16_t tmp3[8]; // coefficients for adding to out + int16_t cvector[8]; // correlated input vector + int filtval; // gain value for one function + int16_t newvec[60]; // tmp vector + int16_t filters[32]; // filters for every subframe +} TSContext; + +#if !defined(LE_32) +#define LE_32(x) ((((uint8_t*)(x))[3] << 24)| (((uint8_t*)(x))[2] << 16) | \ + (((uint8_t*)(x))[1] << 8) | ((uint8_t*)(x))[0]) +#endif + +static int truespeech_decode_init(AVCodecContext *avctx) +{ + return 0; // TSContext *c = avctx->priv_data; +} + +static void truespeech_read_frame(TSContext *dec, uint8_t *input) +{ + uint32_t t; + + t = LE_32(input); // first dword + input += 4; + + dec->flag = t &1; + + dec->vector[0] = ts_codebook[0][(t >> 1) &0x1F]; + dec->vector[1] = ts_codebook[1][(t >> 6) &0x1F]; + dec->vector[2] = ts_codebook[2][(t >> 11) &0xF]; + dec->vector[3] = ts_codebook[3][(t >> 15) &0xF]; + dec->vector[4] = ts_codebook[4][(t >> 19) &0xF]; + dec->vector[5] = ts_codebook[5][(t >> 23) &0x7]; + dec->vector[6] = ts_codebook[6][(t >> 26) &0x7]; + dec->vector[7] = ts_codebook[7][(t >> 29) &0x7]; + + + t = LE_32(input); // second dword + input += 4; + + dec->offset2[0] = (t >> 0) &0x7F; + dec->offset2[1] = (t >> 7) &0x7F; + dec->offset2[2] = (t >> 14) &0x7F; + dec->offset2[3] = (t >> 21) &0x7F; + + dec->offset1[0] = ((t >> 28) &0xF) << 4; + + + t = LE_32(input); // third dword + input += 4; + + dec->pulseval[0] = (t >> 0) &0x3FFF; + dec->pulseval[1] = (t >> 14) &0x3FFF; + + dec->offset1[1] = (t >> 28) &0x0F; + + + t = LE_32(input); // fourth dword + input += 4; + + dec->pulseval[2] = (t >> 0) &0x3FFF; + dec->pulseval[3] = (t >> 14) &0x3FFF; + + dec->offset1[1] |= ((t >> 28) &0x0F) << 4; + + + t = LE_32(input); // fifth dword + input += 4; + + dec->pulsepos[0] = (t >> 4) &0x7FFFFFF; + + dec->pulseoff[0] = (t >> 0) &0xF; + + dec->offset1[0] |= (t >> 31) &1; + + + t = LE_32(input); // sixth dword + input += 4; + + dec->pulsepos[1] = (t >> 4) &0x7FFFFFF; + + dec->pulseoff[1] = (t >> 0) &0xF; + + dec->offset1[0] |= ((t >> 31) &1) << 1; + + + t = LE_32(input); // seventh dword + input += 4; + + dec->pulsepos[2] = (t >> 4) &0x7FFFFFF; + + dec->pulseoff[2] = (t >> 0) &0xF; + + dec->offset1[0] |= ((t >> 31) &1) << 2; + + + t = LE_32(input); // eighth dword + input += 4; + + dec->pulsepos[3] = (t >> 4) &0x7FFFFFF; + + dec->pulseoff[3] = (t >> 0) &0xF; + + dec->offset1[0] |= ((t >> 31) &1) << 3; +} + +static void truespeech_correlate_filter(TSContext *dec) +{ + int16_t tmp[8]; + int i, j; + + for (i = 0; i < 8; i++) + { + if (i > 0) + { + memcpy(tmp, dec->cvector, i *2); + for (j = 0; j < i; j++) + dec->cvector[j] = ((tmp[i - j - 1] *dec->vector[i]) + (dec->cvector[j] << 15) + 0x4000) >> 15; + } + dec->cvector[i] = (8-dec->vector[i]) >> 3; + } + + for (i = 0; i < 8; i++) + dec->cvector[i] = (dec->cvector[i] *ts_230[i]) >> 15; + + dec->filtval = dec->vector[0]; +} + +static void truespeech_filters_merge(TSContext *dec) +{ + int i; + + if (!dec->flag) + { + for (i = 0; i < 8; i++) + { + dec->filters[i + 0] = dec->prevfilt[i]; + dec->filters[i + 8] = dec->prevfilt[i]; + } + } + else + { + for (i = 0; i < 8; i++) + { + dec->filters[i + 0] = (dec->cvector[i] *21846+dec->prevfilt[i] *10923+16384) >> 15; + dec->filters[i + 8] = (dec->cvector[i] *10923+dec->prevfilt[i] *21846+16384) >> 15; + } + } + for (i = 0; i < 8; i++) + { + dec->filters[i + 16] = dec->cvector[i]; + dec->filters[i + 24] = dec->cvector[i]; + } +} + +static void truespeech_apply_twopoint_filter(TSContext *dec, int quart) +{ + int16_t tmp[146+60], *ptr0, *ptr1, *filter; + int i, t, off; + + t = dec->offset2[quart]; + if (t == 127) + { + memset(dec->newvec, 0, 60 *2); + return ; + } + + for (i = 0; i < 146; i++) + tmp[i] = dec->filtbuf[i]; + + off = (t / 25) + dec->offset1[quart >> 1] + 18; + ptr0 = tmp + 145-off; + ptr1 = tmp + 146; + filter = (int16_t*)ts_240 + (t % 25) *2; + for (i = 0; i < 60; i++) + { + t = (ptr0[0] *filter[0] + ptr0[1] *filter[1] + 0x2000) >> 14; + ptr0++; + dec->newvec[i] = t; + ptr1[i] = t; + } +} + +static void truespeech_place_pulses(TSContext *dec, int16_t *out, int quart) +{ + int16_t tmp[7]; + int i, j, t; + int16_t *ptr1, *ptr2; + int coef; + + memset(out, 0, 60 *2); + for (i = 0; i < 7; i++) + { + t = dec->pulseval[quart] &3; + dec->pulseval[quart] >>= 2; + tmp[6-i] = ts_562[dec->pulseoff[quart] *4+t]; + } + + coef = dec->pulsepos[quart] >> 15; + ptr1 = (int16_t*)ts_140 + 30; + ptr2 = tmp; + for (i = 0, j = 3; (i < 30) && (j > 0); i++) + { + t = *ptr1++; + if (coef >= t) + coef -= t; + else + { + out[i] = *ptr2++; + ptr1 += 30; + j--; + } + } + coef = dec->pulsepos[quart] &0x7FFF; + ptr1 = (int16_t*)ts_140; + for (i = 30, j = 4; (i < 60) && (j > 0); i++) + { + t = *ptr1++; + if (coef >= t) + coef -= t; + else + { + out[i] = *ptr2++; + ptr1 += 30; + j--; + } + } +} + +static void truespeech_update_filters(TSContext *dec, int16_t *out, int quart) +{ + int i; + + for (i = 0; i < 86; i++) + dec->filtbuf[i] = dec->filtbuf[i + 60]; + + for (i = 0; i < 60; i++) + { + dec->filtbuf[i + 86] = out[i] + dec->newvec[i] - (dec->newvec[i] >> 3); + out[i] += dec->newvec[i]; + } +} + +static void truespeech_synth(TSContext *dec, int16_t *out, int quart) +{ + int i, k; + int t[8]; + int16_t *ptr0, *ptr1; + + ptr0 = dec->tmp1; + ptr1 = dec->filters + quart * 8; + for (i = 0; i < 60; i++) + { + int sum = 0; + for (k = 0; k < 8; k++) + sum += ptr0[k] *ptr1[k]; + sum = (sum + (out[i] << 12) + 0x800) >> 12; + out[i] = clip(sum, - 0x7FFE, 0x7FFE); + for (k = 7; k > 0; k--) + ptr0[k] = ptr0[k - 1]; + ptr0[0] = out[i]; + } + + for (i = 0; i < 8; i++) + t[i] = (ts_5E2[i] *ptr1[i]) >> 15; + + ptr0 = dec->tmp2; + for (i = 0; i < 60; i++) + { + int sum = 0; + for (k = 0; k < 8; k++) + sum += ptr0[k] *t[k]; + for (k = 7; k > 0; k--) + ptr0[k] = ptr0[k - 1]; + ptr0[0] = out[i]; + out[i] = ((out[i] << 12) - sum) >> 12; + } + + for (i = 0; i < 8; i++) + t[i] = (ts_5F2[i] *ptr1[i]) >> 15; + + ptr0 = dec->tmp3; + for (i = 0; i < 60; i++) + { + int sum = out[i] << 12; + for (k = 0; k < 8; k++) + sum += ptr0[k] *t[k]; + for (k = 7; k > 0; k--) + ptr0[k] = ptr0[k - 1]; + ptr0[0] = clip((sum + 0x800) >> 12, - 0x7FFE, 0x7FFE); + + sum = ((ptr0[1]*(dec->filtval - (dec->filtval >> 2))) >> 4) + sum; + sum = sum - (sum >> 3); + out[i] = clip((sum + 0x800) >> 12, - 0x7FFE, 0x7FFE); + } +} + +static void truespeech_save_prevvec(TSContext *c) +{ + int i; + + for (i = 0; i < 8; i++) + c->prevfilt[i] = c->cvector[i]; +} + +static int truespeech_decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8_t *buf, int buf_size) +{ + TSContext *c = avctx->priv_data; + + int i; + short *samples = data; + int consumed = 0; + int16_t out_buf[240]; + + if (!buf_size) + return 0; + + while (consumed < buf_size) + { + truespeech_read_frame(c, buf + consumed); + consumed += 32; + + truespeech_correlate_filter(c); + truespeech_filters_merge(c); + + memset(out_buf, 0, 240 *2); + for (i = 0; i < 4; i++) + { + truespeech_apply_twopoint_filter(c, i); + truespeech_place_pulses(c, out_buf + i * 60, i); + truespeech_update_filters(c, out_buf + i * 60, i); + truespeech_synth(c, out_buf + i * 60, i); + } + + truespeech_save_prevvec(c); + + for (i = 0; i < 240; i++) // finally output decoded frame + *samples++ = out_buf[i]; + + } + + *data_size = consumed * 15; + + return buf_size; +} + +AVCodec truespeech_decoder = +{ + "truespeech", + CODEC_TYPE_AUDIO, + CODEC_ID_TRUESPEECH, + sizeof(TSContext), + truespeech_decode_init, + NULL, + NULL, + truespeech_decode_frame, +}; diff --git a/ffplay源码和书籍/ffplay/libavcodec/truespeech_data.h b/ffplay源码和书籍/ffplay/libavcodec/truespeech_data.h new file mode 100644 index 0000000..9510ce0 --- /dev/null +++ b/ffplay源码和书籍/ffplay/libavcodec/truespeech_data.h @@ -0,0 +1,139 @@ +#ifndef __TRUESPEECH_DATA__ +#define __TRUESPEECH_DATA__ + +/************************************************************************/ +/* ļ truespeed Ƶʹõij */ +/************************************************************************/ +#pragma warning(disable:4305 ) + +/* codebooks fo expanding input filter */ +static const int16_t ts_cb_0[32] = +{ + 0x8240, 0x8364, 0x84CE, 0x865D, 0x8805, 0x89DE, 0x8BD7, 0x8DF4, + 0x9051, 0x92E2, 0x95DE, 0x990F, 0x9C81, 0xA079, 0xA54C, 0xAAD2, + 0xB18A, 0xB90A, 0xC124, 0xC9CC, 0xD339, 0xDDD3, 0xE9D6, 0xF893, + 0x096F, 0x1ACA, 0x29EC, 0x381F, 0x45F9, 0x546A, 0x63C3, 0x73B5, +}; + +static const int16_t ts_cb_1[32] = +{ + 0x9F65, 0xB56B, 0xC583, 0xD371, 0xE018, 0xEBB4, 0xF61C, 0xFF59, + 0x085B, 0x1106, 0x1952, 0x214A, 0x28C9, 0x2FF8, 0x36E6, 0x3D92, + 0x43DF, 0x49BB, 0x4F46, 0x5467, 0x5930, 0x5DA3, 0x61EC, 0x65F9, + 0x69D4, 0x6D5A, 0x709E, 0x73AD, 0x766B, 0x78F0, 0x7B5A, 0x7DA5, +}; + +static const int16_t ts_cb_2[16] = +{ + 0x96F8, 0xA3B4, 0xAF45, 0xBA53, 0xC4B1, 0xCECC, 0xD86F, 0xE21E, + 0xEBF3, 0xF640, 0x00F7, 0x0C20, 0x1881, 0x269A, 0x376B, 0x4D60, +}; + +static const int16_t ts_cb_3[16] = +{ + 0xC654, 0xDEF2, 0xEFAA, 0xFD94, 0x096A, 0x143F, 0x1E7B, 0x282C, + 0x3176, 0x3A89, 0x439F, 0x4CA2, 0x557F, 0x5E50, 0x6718, 0x6F8D, +}; + +static const int16_t ts_cb_4[16] = +{ + 0xABE7, 0xBBA8, 0xC81C, 0xD326, 0xDD0E, 0xE5D4, 0xEE22, 0xF618, + 0xFE28, 0x064F, 0x0EB7, 0x17B8, 0x21AA, 0x2D8B, 0x3BA2, 0x4DF9, +}; + +static const int16_t ts_cb_5[8] = { 0xD51B, 0xF12E, 0x042E, 0x13C7, 0x2260, 0x311B, 0x40DE, 0x5385,}; + +static const int16_t ts_cb_6[8] = { 0xB550, 0xC825, 0xD980, 0xE997, 0xF883, 0x0752, 0x1811, 0x2E18,}; + +static const int16_t ts_cb_7[8] = { 0xCEF0, 0xE4F9, 0xF6BB, 0x0646, 0x14F5, 0x23FF, 0x356F, 0x4A8D,}; + +static const int16_t *ts_codebook[8] = {ts_cb_0, ts_cb_1, ts_cb_2, ts_cb_3, ts_cb_4, ts_cb_5, ts_cb_6, ts_cb_7}; + +/* table used for decoding pulse positions */ +static const int16_t ts_140[120] = +{ + 0x0E46, 0x0CCC, 0x0B6D, 0x0A28, 0x08FC, 0x07E8, 0x06EB, 0x0604, + 0x0532, 0x0474, 0x03C9, 0x0330, 0x02A8, 0x0230, 0x01C7, 0x016C, + 0x011E, 0x00DC, 0x00A5, 0x0078, 0x0054, 0x0038, 0x0023, 0x0014, + 0x000A, 0x0004, 0x0001, 0x0000, 0x0000, 0x0000, + + 0x0196, 0x017A, 0x015F, 0x0145, 0x012C, 0x0114, 0x00FD, 0x00E7, + 0x00D2, 0x00BE, 0x00AB, 0x0099, 0x0088, 0x0078, 0x0069, 0x005B, + 0x004E, 0x0042, 0x0037, 0x002D, 0x0024, 0x001C, 0x0015, 0x000F, + 0x000A, 0x0006, 0x0003, 0x0001, 0x0000, 0x0000, + + 0x001D, 0x001C, 0x001B, 0x001A, 0x0019, 0x0018, 0x0017, 0x0016, + 0x0015, 0x0014, 0x0013, 0x0012, 0x0011, 0x0010, 0x000F, 0x000E, + 0x000D, 0x000C, 0x000B, 0x000A, 0x0009, 0x0008, 0x0007, 0x0006, + 0x0005, 0x0004, 0x0003, 0x0002, 0x0001, 0x0000, + + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001 +}; + +/* filter for correlated input filter */ +static const int16_t ts_230[8] = { 0x7F3B, 0x7E78, 0x7DB6, 0x7CF5, 0x7C35, 0x7B76, 0x7AB8, 0x79FC }; + +/* two-point filters table */ +static const int16_t ts_240[25 * 2] = +{ + 0xED2F, 0x5239, + 0x54F1, 0xE4A9, + 0x2620, 0xEE3E, + 0x09D6, 0x2C40, + 0xEFB5, 0x2BE0, + + 0x3FE1, 0x3339, + 0x442F, 0xE6FE, + 0x4458, 0xF9DF, + 0xF231, 0x43DB, + 0x3DB0, 0xF705, + + 0x4F7B, 0xFEFB, + 0x26AD, 0x0CDC, + 0x33C2, 0x0739, + 0x12BE, 0x43A2, + 0x1BDF, 0x1F3E, + + 0x0211, 0x0796, + 0x2AEB, 0x163F, + 0x050D, 0x3A38, + 0x0D1E, 0x0D78, + 0x150F, 0x3346, + + 0x38A4, 0x0B7D, + 0x2D5D, 0x1FDF, + 0x19B7, 0x2822, + 0x0D99, 0x1F12, + 0x194C, 0x0CE6 +}; + +/* possible pulse values */ +static const int16_t ts_562[64] = +{ + 0x0002, 0x0006, 0xFFFE, 0xFFFA, + 0x0004, 0x000C, 0xFFFC, 0xFFF4, + 0x0006, 0x0012, 0xFFFA, 0xFFEE, + 0x000A, 0x001E, 0xFFF6, 0xFFE2, + 0x0010, 0x0030, 0xFFF0, 0xFFD0, + 0x0019, 0x004B, 0xFFE7, 0xFFB5, + 0x0028, 0x0078, 0xFFD8, 0xFF88, + 0x0040, 0x00C0, 0xFFC0, 0xFF40, + 0x0065, 0x012F, 0xFF9B, 0xFED1, + 0x00A1, 0x01E3, 0xFF5F, 0xFE1D, + 0x0100, 0x0300, 0xFF00, 0xFD00, + 0x0196, 0x04C2, 0xFE6A, 0xFB3E, + 0x0285, 0x078F, 0xFD7B, 0xF871, + 0x0400, 0x0C00, 0xFC00, 0xF400, + 0x0659, 0x130B, 0xF9A7, 0xECF5, + 0x0A14, 0x1E3C, 0xF5EC, 0xE1C4 +}; + +/* filters used in final output calculations */ +static const int16_t ts_5E2[8] = { 0x4666, 0x26B8, 0x154C, 0x0BB6, 0x0671, 0x038B, 0x01F3, 0x0112 }; + +static const int16_t ts_5F2[8] = { 0x6000, 0x4800, 0x3600, 0x2880, 0x1E60, 0x16C8, 0x1116, 0x0CD1 }; + +#endif diff --git a/ffplay源码和书籍/ffplay/libavcodec/utils_codec.c b/ffplay源码和书籍/ffplay/libavcodec/utils_codec.c new file mode 100644 index 0000000..d0d44c1 --- /dev/null +++ b/ffplay源码和书籍/ffplay/libavcodec/utils_codec.c @@ -0,0 +1,412 @@ +/************************************************************************/ +/* ʹõİ͹ߺ */ +/************************************************************************/ + +#include +#include "avcodec.h" +#include "dsputil.h" + +#define EDGE_WIDTH 16 +#define STRIDE_ALIGN 16 + +#define INT_MAX 2147483647 + +#define FFMAX(a,b) ((a) > (b) ? (a) : (b)) + +void *av_malloc(unsigned int size) +{ + void *ptr; + + if (size > INT_MAX) + return NULL; + ptr = malloc(size); + + return ptr; +} + +void *av_realloc(void *ptr, unsigned int size) +{ + if (size > INT_MAX) + return NULL; + + return realloc(ptr, size); +} + +void av_free(void *ptr) +{ + if (ptr) + free(ptr); +} + +void *av_mallocz(unsigned int size) +{ + void *ptr; + + ptr = av_malloc(size); + if (!ptr) + return NULL; + + memset(ptr, 0, size); + return ptr; +} + +void *av_fast_realloc(void *ptr, unsigned int *size, unsigned int min_size) +{ + if (min_size < *size) + return ptr; + + *size = FFMAX(17 *min_size / 16+32, min_size); + + return av_realloc(ptr, *size); +} + +void av_freep(void *arg) +{ + void **ptr = (void **)arg; + av_free(*ptr); + *ptr = NULL; +} + +/* Ϊֶ֧Ҫеı */ +AVCodec *first_avcodec = NULL; + +/* ע */ +void register_avcodec(AVCodec *format) +{ + /* ѱӵ */ + AVCodec **p; + p = &first_avcodec; + while (*p != NULL) + p = &(*p)->next; + *p = format; + format->next = NULL; +} + +typedef struct InternalBuffer +{ + uint8_t *base[4]; + uint8_t *data[4]; + int linesize[4]; +} InternalBuffer; + +#define INTERNAL_BUFFER_SIZE 32 + +#define ALIGN(x, a) (((x)+(a)-1)&~((a)-1)) + +void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height) +{ + int w_align = 1; + int h_align = 1; + + switch (s->pix_fmt) + { + case PIX_FMT_YUV420P: + case PIX_FMT_YUV422: + case PIX_FMT_UYVY422: + case PIX_FMT_YUV422P: + case PIX_FMT_YUV444P: + case PIX_FMT_GRAY8: + case PIX_FMT_YUVJ420P: + case PIX_FMT_YUVJ422P: + case PIX_FMT_YUVJ444P: //FIXME check for non mpeg style codecs and use less alignment + w_align = 16; + h_align = 16; + break; + case PIX_FMT_YUV411P: + case PIX_FMT_UYVY411: + w_align = 32; + h_align = 8; + break; + case PIX_FMT_YUV410P: + case PIX_FMT_RGB555: + case PIX_FMT_PAL8: + break; + case PIX_FMT_BGR24: + break; + default: + w_align = 1; + h_align = 1; + break; + } + + *width = ALIGN(*width, w_align); + *height = ALIGN(*height, h_align); +} + +int avcodec_check_dimensions(void *av_log_ctx, unsigned int w, unsigned int h) +{ + if ((int)w > 0 && (int)h > 0 && (w + 128)*(uint64_t)(h + 128) < INT_MAX / 4) + return 0; + + return - 1; +} + +int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic) +{ + int i; + int w = s->width; + int h = s->height; + int align_off; + InternalBuffer *buf; + + assert(pic->data[0] == NULL); + assert(INTERNAL_BUFFER_SIZE > s->internal_buffer_count); + + if (avcodec_check_dimensions(s, w, h)) + return - 1; + + if (s->internal_buffer == NULL) + s->internal_buffer = av_mallocz(INTERNAL_BUFFER_SIZE *sizeof(InternalBuffer)); + + buf = &((InternalBuffer*)s->internal_buffer)[s->internal_buffer_count]; + + if (buf->base[0]) + {} + else + { + int h_chroma_shift, v_chroma_shift; + int pixel_size, size[3]; + + AVPicture picture; + + avcodec_get_chroma_sub_sample(s->pix_fmt, &h_chroma_shift, &v_chroma_shift); + + avcodec_align_dimensions(s, &w, &h); + + w+= EDGE_WIDTH*2; + h+= EDGE_WIDTH*2; + + avpicture_fill(&picture, NULL, s->pix_fmt, w, h); + pixel_size = picture.linesize[0] * 8 / w; + assert(pixel_size >= 1); + + if (pixel_size == 3 *8) + w = ALIGN(w, STRIDE_ALIGN << h_chroma_shift); + else + w = ALIGN(pixel_size *w, STRIDE_ALIGN << (h_chroma_shift + 3)) / pixel_size; + + size[1] = avpicture_fill(&picture, NULL, s->pix_fmt, w, h); + size[0] = picture.linesize[0] *h; + size[1] -= size[0]; + if (picture.data[2]) + size[1] = size[2] = size[1] / 2; + else + size[2] = 0; + + memset(buf->base, 0, sizeof(buf->base)); + memset(buf->data, 0, sizeof(buf->data)); + + for (i = 0; i < 3 && size[i]; i++) + { + const int h_shift = i == 0 ? 0 : h_chroma_shift; + const int v_shift = i == 0 ? 0 : v_chroma_shift; + + buf->linesize[i] = picture.linesize[i]; + + buf->base[i] = av_malloc(size[i] + 16); //FIXME 16 + if (buf->base[i] == NULL) + return - 1; + memset(buf->base[i], 128, size[i]); + + align_off = ALIGN((buf->linesize[i] * EDGE_WIDTH >> v_shift) + ( EDGE_WIDTH >> h_shift), STRIDE_ALIGN); + + if ((s->pix_fmt == PIX_FMT_PAL8) || !size[2]) + buf->data[i] = buf->base[i]; + else + buf->data[i] = buf->base[i] + align_off; + } + } + + for (i = 0; i < 4; i++) + { + pic->base[i] = buf->base[i]; + pic->data[i] = buf->data[i]; + pic->linesize[i] = buf->linesize[i]; + } + s->internal_buffer_count++; + + return 0; +} + +void avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic) +{ + int i; + InternalBuffer *buf, *last, temp; + + assert(s->internal_buffer_count); + + buf = NULL; + for (i = 0; i < s->internal_buffer_count; i++) + { + buf = &((InternalBuffer*)s->internal_buffer)[i]; //just 3-5 checks so is not worth to optimize + if (buf->data[0] == pic->data[0]) + break; + } + assert(i < s->internal_buffer_count); + s->internal_buffer_count--; + last = &((InternalBuffer*)s->internal_buffer)[s->internal_buffer_count]; + + temp = *buf; + *buf = *last; + *last = temp; + + for (i = 0; i < 3; i++) + { + pic->data[i] = NULL; + } +} + +int avcodec_default_reget_buffer(AVCodecContext *s, AVFrame *pic) +{ + if (pic->data[0] == NULL) // If no picture return a new buffer + { + return s->get_buffer(s, pic); + } + + return 0; +} + +void avcodec_default_free_buffers(AVCodecContext *s) +{ + int i, j; + + if (s->internal_buffer == NULL) + return ; + + for (i = 0; i < INTERNAL_BUFFER_SIZE; i++) + { + InternalBuffer *buf = &((InternalBuffer*)s->internal_buffer)[i]; + for (j = 0; j < 4; j++) + { + av_freep(&buf->base[j]); + buf->data[j] = NULL; + } + } + av_freep(&s->internal_buffer); + + s->internal_buffer_count = 0; +} + +AVCodecContext *avcodec_alloc_context(void) +{ + AVCodecContext *s = av_malloc(sizeof(AVCodecContext)); + + if (s == NULL) + return NULL; + + memset(s, 0, sizeof(AVCodecContext)); + + s->get_buffer = avcodec_default_get_buffer; + s->release_buffer = avcodec_default_release_buffer; + + s->pix_fmt = PIX_FMT_NONE; + + s->palctrl = NULL; + s->reget_buffer = avcodec_default_reget_buffer; + + return s; +} + +int avcodec_open(AVCodecContext *avctx, AVCodec *codec) +{ + int ret = - 1; + + if (avctx->codec) + goto end; + + if (codec->priv_data_size > 0) + { + avctx->priv_data = av_mallocz(codec->priv_data_size); + if (!avctx->priv_data) + goto end; + } + else + { + avctx->priv_data = NULL; + } + + avctx->codec = codec; + avctx->codec_id = codec->id; + avctx->frame_number = 0; + ret = avctx->codec->init(avctx); + if (ret < 0) + { + av_freep(&avctx->priv_data); + avctx->codec = NULL; + goto end; + } + ret = 0; +end: + return ret; +} + +int avcodec_decode_video(AVCodecContext *avctx, AVFrame *picture, int *got_picture_ptr, + uint8_t *buf, int buf_size) +{ + int ret; + + *got_picture_ptr = 0; + + if (buf_size) + { + ret = avctx->codec->decode(avctx, picture, got_picture_ptr, buf, buf_size); // ʵʵıı뺯msrleȱ + + if (*got_picture_ptr) + avctx->frame_number++; + } + else + ret = 0; + + return ret; +} + +int avcodec_decode_audio(AVCodecContext *avctx, int16_t *samples, int *frame_size_ptr, + uint8_t *buf, int buf_size) +{ + int ret; + + *frame_size_ptr = 0; + if (buf_size) + { + ret = avctx->codec->decode(avctx, samples, frame_size_ptr, buf, buf_size); + avctx->frame_number++; + } + else + ret = 0; + return ret; +} + +int avcodec_close(AVCodecContext *avctx) +{ + if (avctx->codec->close) + avctx->codec->close(avctx); + avcodec_default_free_buffers(avctx); + av_freep(&avctx->priv_data); + avctx->codec = NULL; + return 0; +} + +AVCodec *avcodec_find_decoder(enum CodecID id) +{ + AVCodec *p; + p = first_avcodec; + while (p) + { + if (p->decode != NULL && p->id == id) + return p; + p = p->next; + } + return NULL; +} + +/* ʼ */ +void avcodec_init(void) +{ + static int inited = 0; + + if (inited != 0) + return ; + inited = 1; + + dsputil_static_init(); +} diff --git a/ffplay源码和书籍/ffplay/libavformat/allformats.c b/ffplay源码和书籍/ffplay/libavformat/allformats.c new file mode 100644 index 0000000..1c02e9d --- /dev/null +++ b/ffplay源码和书籍/ffplay/libavformat/allformats.c @@ -0,0 +1,31 @@ +/* +** 򵥵ע/ʼӦЭ飬ļʽӦڲ +*/ +#include "avformat.h" + +extern URLProtocol file_protocol; + +/* עֵ֧ĸʽ */ +void av_register_all(void) +{ + static int inited = 0; + + // ǷѾʼ + if (inited != 0) + return ; + inited = 1; + + // ffplay CPU һ DSPЩ CPU ԴļָŻffplay ຯ + // ŵ dsputil.h dsputil.c ļУ úָķӳ䵽 CPU ļŻʵֺ + // ˴ʼЩָ + avcodec_init(); + + // עеı + avcodec_register_all(); + + // עֵ֧ĸʽ + avidec_init(); + + // עЭ飨ļЭ顢Эȣ + register_protocol(&file_protocol); +} diff --git a/ffplay源码和书籍/ffplay/libavformat/avformat.h b/ffplay源码和书籍/ffplay/libavformat/avformat.h new file mode 100644 index 0000000..09493b2 --- /dev/null +++ b/ffplay源码和书籍/ffplay/libavformat/avformat.h @@ -0,0 +1,271 @@ +#ifndef AVFORMAT_H +#define AVFORMAT_H + +/************************************************* +** ʶļʽýͿʹõĺꡢݽṹͺ +**ͨЩꡢݽṹͺڴģȫЧ +*************************************************/ +#ifdef __cplusplus + +extern "C" +{ +#endif + + /* 汾 */ +#define LIBAVFORMAT_VERSION_INT ((50<<16)+(4<<8)+0) +#define LIBAVFORMAT_VERSION 50.4.0 +#define LIBAVFORMAT_BUILD LIBAVFORMAT_VERSION_INT + +#define LIBAVFORMAT_IDENT "Lavf" AV_STRINGIFY(LIBAVFORMAT_VERSION) + + /* ͷļ */ +#include "../libavcodec/avcodec.h" + + /* ioͷļ */ +#include "avio.h" + + /* 붨 */ +#define AVERROR_UNKNOWN (-1) // unknown error +#define AVERROR_IO (-2) // i/o error +#define AVERROR_NUMEXPECTED (-3) // number syntax expected in filename +#define AVERROR_INVALIDDATA (-4) // invalid data found +#define AVERROR_NOMEM (-5) // not enough memory +#define AVERROR_NOFMT (-6) // unknown format +#define AVERROR_NOTSUPP (-7) // operation not supported + + /* ļת */ +#define AVSEEK_FLAG_BACKWARD 1 // seek backward +#define AVSEEK_FLAG_BYTE 2 // seeking based on position in bytes +#define AVSEEK_FLAG_ANY 4 // seek to any frame, even non keyframes + +#define AVFMT_NOFILE 0x0001 // no file should be opened + +#define PKT_FLAG_KEY 0x0001 + +#define AVINDEX_KEYFRAME 0x0001 + +#define AVPROBE_SCORE_MAX 100 + +#define MAX_STREAMS 20 + + /* + ** ݰƵƵһһݰһ֡ݣ + ** δ֡ + */ +typedef struct AVPacket +{ + int64_t pts; // presentation time stamp in time_base units ʾʱ䣬Ƶʾʱ + int64_t dts; // decompression time stamp in time_base units ʱ䣬ǺҪ + int64_t pos; // byte position in stream, -1 if unknown + uint8_t *data; // ʵʱƵݻ׵ַ + int size; // ʵʱƵݻĴС + int stream_index; // ǰƵݰӦڱƵƵ + int flags; //ݰһЩǣǷǹؼ֡ȡ + void(*destruct)(struct AVPacket*); // ٺ +} AVPacket; + +/* Ƶб */ +typedef struct AVPacketList +{ + AVPacket pkt; + struct AVPacketList *next; +} AVPacketList; + +/* ͷݰڵ */ +static inline void av_destruct_packet(AVPacket *pkt) +{ + av_free(pkt->data); + pkt->data = NULL; + pkt->size = 0; +} + +/* ͷһƵ */ +static inline void av_free_packet(AVPacket *pkt) +{ + if (pkt && pkt->destruct) + pkt->destruct(pkt); +} + +/* +** ȡһƵ +** ļݰݣ +** עܵʱļƫȷҪݵĴСҲȷ +** ݰĻûз䡣ڴҪʼһЩ +*/ +static inline int av_get_packet(ByteIOContext *s, AVPacket *pkt, int size) +{ + int ret; + unsigned char *data; + if ((unsigned)size > (unsigned)size + FF_INPUT_BUFFER_PADDING_SIZE) + return AVERROR_NOMEM; + + // ڴ + data = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE); + if (!data) + return AVERROR_NOMEM; + + memset(data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE); + + pkt->pts = AV_NOPTS_VALUE; + pkt->dts = AV_NOPTS_VALUE; + pkt->pos = - 1; + pkt->flags = 0; + pkt->stream_index = 0; + pkt->data = data; + pkt->size = size; + pkt->destruct = av_destruct_packet; + + pkt->pos = url_ftell(s); + + // ȡʵʵ + ret = url_fread(s, pkt->data, size); + if (ret <= 0) + av_free_packet(pkt); + else + pkt->size = ret; + + return ret; +} + +/* +** ̽ +** ΪʶļʽҪһļͷƥ ffplay ֵ֧ļʽļ +** ýṹļ׵ַʹС˴Ķļ +*/ +typedef struct AVProbeData +{ + // ļ + const char *filename; + // ̽⵽ + unsigned char *buf; + // ݳ + int buf_size; +} AVProbeData; + +/* +** ļṹflags size λΪ˽ʡڴ +*/ +typedef struct AVIndexEntry +{ + int64_t pos; + int64_t timestamp; + int flags: 2; + int size: 30; //yeah trying to keep the size of this small to reduce memory requirements (its 24 vs 32 byte due to possible 8byte align) +} AVIndexEntry; + +/* +** ƵƵ +** AVStream ıʾһýýһЩͨõ +** ϸΪƵƵƵֿԷֳAVIͣmp4 +*/ +typedef struct AVStream +{ + // + AVCodecContext *actx; // codec context, change from AVCodecContext *codec; + + // + void *priv_data; // AVIStream ڱУ AVIStream + + // ʱ׼ + AVRational time_base; // av_set_pts_info()ʼ + + // 󣬼粻֧IJҵʱʹ + AVIndexEntry *index_entries; // only used if the format does not support seeking natively + int nb_index_entries; + int index_entries_allocated_size; + + double frame_last_delay; // ֡ӳ +} AVStream; + +/* ʽ */ +typedef struct AVFormatParameters +{ + int dbg; //only for debug ֻһԱ־ +} AVFormatParameters; + +/* +** ʽļĽṹָ룩 +** AVInputFormat ļʽעⲻAVIAV Inputڹܺ +** ڳʱжʵ +*/ +typedef struct AVInputFormat +{ + // ļ + const char *name; + + int priv_data_size; + + // ̽⺯ + int(*read_probe)(AVProbeData*); + + // ȡͷ + int(*read_header)(struct AVFormatContext *, AVFormatParameters *ap); + + // ȡһ֡ݣһݰ + int(*read_packet)(struct AVFormatContext *, AVPacket *pkt); + + // رļ + int(*read_close)(struct AVFormatContext*); + + const char *extensions; // ļչ + + // һļĸʽ + struct AVInputFormat *next; + +} AVInputFormat; + +/* +** AVFormatContext ṹʾеĵǰļʽʹõģ +** ļеԣкһʵ +*/ +typedef struct AVFormatContext // format I/O context +{ + // ļĸʽAVFormatContextһĸAVInputFormatһĸ + struct AVInputFormat *iformat; + + void *priv_data; + + // ļ + ByteIOContext pb; + + // + int nb_streams; + + // ƵƵ + AVStream *streams[MAX_STREAMS]; + +} AVFormatContext; + +int avidec_init(void); + +void av_register_input_format(AVInputFormat *format); + +void av_register_all(void); + +AVInputFormat *av_probe_input_format(AVProbeData *pd, int is_opened); +int match_ext(const char *filename, const char *extensions); + +int av_open_input_stream(AVFormatContext **ic_ptr, ByteIOContext *pb, const char *filename, + AVInputFormat *fmt, AVFormatParameters *ap); + +int av_open_input_file(AVFormatContext **ic_ptr, const char *filename, AVInputFormat *fmt, + int buf_size, AVFormatParameters *ap); + +int av_read_frame(AVFormatContext *s, AVPacket *pkt); +int av_read_packet(AVFormatContext *s, AVPacket *pkt); +void av_close_input_file(AVFormatContext *s); +AVStream *av_new_stream(AVFormatContext *s, int id); +void av_set_pts_info(AVStream *s, int pts_wrap_bits, int pts_num, int pts_den); + +int av_index_search_timestamp(AVStream *st, int64_t timestamp, int flags); +int av_add_index_entry(AVStream *st, int64_t pos, int64_t timestamp, int size, int distance, int flags); + +int strstart(const char *str, const char *val, const char **ptr); +void pstrcpy(char *buf, int buf_size, const char *str); + +#ifdef __cplusplus +} + +#endif + +#endif diff --git a/ffplay源码和书籍/ffplay/libavformat/avidec.c b/ffplay源码和书籍/ffplay/libavformat/avidec.c new file mode 100644 index 0000000..edff9f6 --- /dev/null +++ b/ffplay源码和书籍/ffplay/libavformat/avidec.c @@ -0,0 +1,792 @@ +/* +** AVI ļغעЩطЩԴ롣 +ע 1AVI ļýִŷʽǽ֯źͽ֯š֯žƵ֡Ϊ +Сλ໥ţƵཻ֡֯һ𣬲Ҵŵļûر涨ǽ֯žǰ +һý֡һ𣬷ǽ֯ŵ avi ļ١ +ע 2AVI ļṹ AVIINDEXENTRY е dwChunkOffset ֶָʾƫеļʼֽڵƫ +ƣеļݿ chunk ƫơ +ע 3 avi ļǽ֯ŵġ +*/ + +#include "avformat.h" + +#include + +#define AVIIF_INDEX 0x10 + +#define AVIF_HASINDEX 0x00000010 // Index at end of file? +#define AVIF_MUSTUSEINDEX 0x00000020 + +#define INT_MAX 2147483647 + +#define MKTAG(a,b,c,d) (a | (b << 8) | (c << 16) | (d << 24)) + +#define FFMIN(a,b) ((a) > (b) ? (b) : (a)) +#define FFMAX(a,b) ((a) > (b) ? (a) : (b)) + +static int avi_load_index(AVFormatContext *s); +static int guess_ni_flag(AVFormatContext *s); + +/* AVIʽƵ */ +typedef struct +{ + int64_t frame_offset; // current frame(video) or byte(audio) counter(used to compute the pts) + int remaining; + int packet_size; + + int scale; + int rate; + int sample_size; // size of one sample (or packet) (in the rate/scale sense) in bytes + + int64_t cum_len; // temporary storage (used during seek) + + int prefix; // normally 'd'<<8 + 'c' or 'w'<<8 + 'b' + int prefix_count; +} AVIStream; + +/* AVIļ*/ +typedef struct +{ + int64_t riff_end; // RIFFС + int64_t movi_list; + int64_t movi_end; + int non_interleaved; + int stream_index_2; // Ϊ˺AVPacketеstream_index +} AVIContext; + +typedef struct +{ + int id; + unsigned int tag; +} CodecTag; + +const CodecTag codec_bmp_tags[] = +{ + {CODEC_ID_MSRLE, MKTAG('m', 'r', 'l', 'e')}, + {CODEC_ID_MSRLE, MKTAG(0x1, 0x0, 0x0, 0x0)}, + {CODEC_ID_NONE, 0}, +}; + +const CodecTag codec_wav_tags[] = +{ + {CODEC_ID_TRUESPEECH, 0x22}, + {0, 0}, +}; + +enum CodecID codec_get_id(const CodecTag *tags, unsigned int tag) +{ + while (tags->id != CODEC_ID_NONE) + { + if (toupper((tag >> 0) &0xFF) == toupper((tags->tag >> 0) &0xFF) + && toupper((tag >> 8) &0xFF) == toupper((tags->tag >> 8) &0xFF) + && toupper((tag >> 16)&0xFF) == toupper((tags->tag >> 16)&0xFF) + && toupper((tag >> 24)&0xFF) == toupper((tags->tag >> 24)&0xFF)) + return tags->id; + + tags++; + } + return CODEC_ID_NONE; +} + +static int get_riff(AVIContext *avi, ByteIOContext *pb) +{ + uint32_t tag; + tag = get_le32(pb); + + if (tag != MKTAG('R', 'I', 'F', 'F')) + return - 1; + + avi->riff_end = get_le32(pb); // RIFF chunk size + avi->riff_end += url_ftell(pb); // RIFF chunk end + tag = get_le32(pb); + + if (tag != MKTAG('A', 'V', 'I', ' ') && tag != MKTAG('A', 'V', 'I', 'X')) + return - 1; + + return 0; +} + +static void clean_index(AVFormatContext *s) +{ + int i, j; + + for (i = 0; i < s->nb_streams; i++) + { + AVStream *st = s->streams[i]; + AVIStream *ast = st->priv_data; + int n = st->nb_index_entries; + int max = ast->sample_size; + int64_t pos, size, ts; + + if (n != 1 || ast->sample_size == 0) + continue; + + while (max < 1024) + max += max; + + pos = st->index_entries[0].pos; + size = st->index_entries[0].size; + ts = st->index_entries[0].timestamp; + + for (j = 0; j < size; j += max) + { + av_add_index_entry(st, pos + j, ts + j / ast->sample_size, FFMIN(max, size - j), 0, AVINDEX_KEYFRAME); + } + } +} + +static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap) +{ + AVIContext *avi = s->priv_data; + ByteIOContext *pb = &s->pb; + uint32_t tag, tag1, handler; + int codec_type, stream_index, frame_period, bit_rate; + unsigned int size, nb_frames; + int i, n; + AVStream *st; + AVIStream *ast; + + avi->stream_index_2 = - 1; + + if (get_riff(avi, pb) < 0) + return - 1; + + stream_index = - 1; // first list tag + codec_type = - 1; + frame_period = 0; + + for (;;) + { + if (url_feof(pb)) + goto fail; + + tag = get_le32(pb); + size = get_le32(pb); + + switch (tag) + { + case MKTAG('L', 'I', 'S', 'T'): // ignored, except when start of video packets + tag1 = get_le32(pb); + if (tag1 == MKTAG('m', 'o', 'v', 'i')) + { + avi->movi_list = url_ftell(pb) - 4; + if (size) + avi->movi_end = avi->movi_list + size; + else + avi->movi_end = url_fsize(pb); + + goto end_of_header; // ݶξΪļͷˣgoto + } + break; + case MKTAG('a', 'v', 'i', 'h'): // avi header, using frame_period is bad idea + frame_period = get_le32(pb); + bit_rate = get_le32(pb) *8; + get_le32(pb); + avi->non_interleaved |= get_le32(pb) &AVIF_MUSTUSEINDEX; + + url_fskip(pb, 2 *4); + n = get_le32(pb); + for (i = 0; i < n; i++) + { + AVIStream *ast; + st = av_new_stream(s, i); + if (!st) + goto fail; + + ast = av_mallocz(sizeof(AVIStream)); + if (!ast) + goto fail; + st->priv_data = ast; + + st->actx->bit_rate = bit_rate; + } + url_fskip(pb, size - 7 * 4); + break; + case MKTAG('s', 't', 'r', 'h'): // stream header + stream_index++; + tag1 = get_le32(pb); + handler = get_le32(pb); + + if (stream_index >= s->nb_streams) + { + url_fskip(pb, size - 8); + break; + } + st = s->streams[stream_index]; + ast = st->priv_data; + + get_le32(pb); // flags + get_le16(pb); // priority + get_le16(pb); // language + get_le32(pb); // initial frame + ast->scale = get_le32(pb); + ast->rate = get_le32(pb); + if (ast->scale && ast->rate) + {} + else if (frame_period) + { + ast->rate = 1000000; + ast->scale = frame_period; + } + else + { + ast->rate = 25; + ast->scale = 1; + } + av_set_pts_info(st, 64, ast->scale, ast->rate); + + ast->cum_len = get_le32(pb); // start + nb_frames = get_le32(pb); + + get_le32(pb); // buffer size + get_le32(pb); // quality + ast->sample_size = get_le32(pb); // sample ssize + + switch (tag1) + { + case MKTAG('v', 'i', 'd', 's'): codec_type = CODEC_TYPE_VIDEO; + ast->sample_size = 0; + break; + case MKTAG('a', 'u', 'd', 's'): codec_type = CODEC_TYPE_AUDIO; + break; + case MKTAG('t', 'x', 't', 's'): //FIXME + codec_type = CODEC_TYPE_DATA; //CODEC_TYPE_SUB ? FIXME + break; + case MKTAG('p', 'a', 'd', 's'): codec_type = CODEC_TYPE_UNKNOWN; + stream_index--; + break; + default: + goto fail; + } + ast->frame_offset = ast->cum_len *FFMAX(ast->sample_size, 1); + url_fskip(pb, size - 12 * 4); + break; + case MKTAG('s', 't', 'r', 'f'): // stream header + if (stream_index >= s->nb_streams) + { + url_fskip(pb, size); + } + else + { + st = s->streams[stream_index]; + switch (codec_type) + { + case CODEC_TYPE_VIDEO: // BITMAPINFOHEADER + get_le32(pb); // size + st->actx->width = get_le32(pb); + st->actx->height = get_le32(pb); + get_le16(pb); // panes + st->actx->bits_per_sample = get_le16(pb); // depth + tag1 = get_le32(pb); + get_le32(pb); // ImageSize + get_le32(pb); // XPelsPerMeter + get_le32(pb); // YPelsPerMeter + get_le32(pb); // ClrUsed + get_le32(pb); // ClrImportant + + if (size > 10 *4 && size < (1 << 30)) + { + st->actx->extradata_size = size - 10 * 4; + st->actx->extradata = av_malloc(st->actx->extradata_size + + FF_INPUT_BUFFER_PADDING_SIZE); + url_fread(pb, st->actx->extradata, st->actx->extradata_size); + } + + if (st->actx->extradata_size &1) + get_byte(pb); + + /* Extract palette from extradata if bpp <= 8 */ + /* This code assumes that extradata contains only palette */ + /* This is true for all paletted codecs implemented in ffmpeg */ + if (st->actx->extradata_size && (st->actx->bits_per_sample <= 8)) + { + int min = FFMIN(st->actx->extradata_size, AVPALETTE_SIZE); + + st->actx->palctrl = av_mallocz(sizeof(AVPaletteControl)); + memcpy(st->actx->palctrl->palette, st->actx->extradata, min); + st->actx->palctrl->palette_changed = 1; + } + + st->actx->codec_type = CODEC_TYPE_VIDEO; + st->actx->codec_id = codec_get_id(codec_bmp_tags, tag1); + + st->frame_last_delay = 1.0 * ast->scale / ast->rate; + + break; + case CODEC_TYPE_AUDIO: + { + AVCodecContext *actx = st->actx; + + int id = get_le16(pb); + actx->codec_type = CODEC_TYPE_AUDIO; + actx->channels = get_le16(pb); + actx->sample_rate = get_le32(pb); + actx->bit_rate = get_le32(pb) *8; + actx->block_align = get_le16(pb); + if (size == 14) // We're dealing with plain vanilla WAVEFORMAT + actx->bits_per_sample = 8; + else + actx->bits_per_sample = get_le16(pb); + actx->codec_id = codec_get_id(codec_wav_tags, id); // wav_codec_get_id(id, codec->bits_per_sample); + + if (size > 16) + { + actx->extradata_size = get_le16(pb); // We're obviously dealing with WAVEFORMATEX + if (actx->extradata_size > 0) + { + if (actx->extradata_size > size - 18) + actx->extradata_size = size - 18; + actx->extradata = av_mallocz(actx->extradata_size + + FF_INPUT_BUFFER_PADDING_SIZE); + url_fread(pb, actx->extradata, actx->extradata_size); + } + else + { + actx->extradata_size = 0; + } + + // It is possible for the chunk to contain garbage at the end + if (size - actx->extradata_size - 18 > 0) + url_fskip(pb, size - actx->extradata_size - 18); + } + } + + if (size % 2) // 2-aligned (fix for Stargate SG-1 - 3x18 - Shades of Grey.avi) + url_fskip(pb, 1); + + break; + default: + st->actx->codec_type = CODEC_TYPE_DATA; + st->actx->codec_id = CODEC_ID_NONE; + url_fskip(pb, size); + break; + } + } + break; + default: // skip tag + size += (size &1); + url_fskip(pb, size); + break; + } + } + +end_of_header: + if (stream_index != s->nb_streams - 1) // check stream number + { +fail: + for (i = 0; i < s->nb_streams; i++) + { + av_freep(&s->streams[i]->actx->extradata); + av_freep(&s->streams[i]); + } + return - 1; + } + + avi_load_index(s); + + avi->non_interleaved |= guess_ni_flag(s); + if (avi->non_interleaved) + clean_index(s); + + return 0; +} + +int avi_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + AVIContext *avi = s->priv_data; + ByteIOContext *pb = &s->pb; + int n, d[8], size; + offset_t i, sync; + + if (avi->non_interleaved) + { + int best_stream_index = 0; + AVStream *best_st = NULL; + AVIStream *best_ast; + int64_t best_ts = INT64_MAX; + int i; + + for (i = 0; i < s->nb_streams; i++) + { + AVStream *st = s->streams[i]; + AVIStream *ast = st->priv_data; + int64_t ts = ast->frame_offset; + + if (ast->sample_size) + ts /= ast->sample_size; + + ts = av_rescale(ts, AV_TIME_BASE *(int64_t)st->time_base.num, st->time_base.den); + + if (ts < best_ts) + { + best_ts = ts; + best_st = st; + best_stream_index = i; + } + } + best_ast = best_st->priv_data; + best_ts = av_rescale(best_ts, best_st->time_base.den, AV_TIME_BASE *(int64_t)best_st->time_base.num); + if (best_ast->remaining) + i = av_index_search_timestamp(best_st, best_ts, AVSEEK_FLAG_ANY | AVSEEK_FLAG_BACKWARD); + else + i = av_index_search_timestamp(best_st, best_ts, AVSEEK_FLAG_ANY); + + if (i >= 0) + { + int64_t pos = best_st->index_entries[i].pos; + pos += best_ast->packet_size - best_ast->remaining; + url_fseek(&s->pb, pos + 8, SEEK_SET); + + assert(best_ast->remaining <= best_ast->packet_size); + + avi->stream_index_2 = best_stream_index; + if (!best_ast->remaining) + best_ast->packet_size = best_ast->remaining = best_st->index_entries[i].size; + } + } + +resync: + + if (avi->stream_index_2 >= 0) + { + AVStream *st = s->streams[avi->stream_index_2]; + AVIStream *ast = st->priv_data; + int size; + + if (ast->sample_size <= 1) // minorityreport.AVI block_align=1024 sample_size=1 IMA-ADPCM + size = INT_MAX; + else if (ast->sample_size < 32) + size = 64 * ast->sample_size; + else + size = ast->sample_size; + + if (size > ast->remaining) + size = ast->remaining; + + av_get_packet(pb, pkt, size); + + pkt->dts = ast->frame_offset; + + if (ast->sample_size) + pkt->dts /= ast->sample_size; + + pkt->stream_index = avi->stream_index_2; + + if (st->actx->codec_type == CODEC_TYPE_VIDEO) + { + if (st->index_entries) + { + AVIndexEntry *e; + int index; + + index = av_index_search_timestamp(st, pkt->dts, 0); + e = &st->index_entries[index]; + + if (index >= 0 && e->timestamp == ast->frame_offset) + { + if (e->flags &AVINDEX_KEYFRAME) + pkt->flags |= PKT_FLAG_KEY; + } + } + else + { + pkt->flags |= PKT_FLAG_KEY; // if no index, better to say that all frames are key frames + } + } + else + { + pkt->flags |= PKT_FLAG_KEY; + } + + if (ast->sample_size) + ast->frame_offset += pkt->size; + else + ast->frame_offset++; + + ast->remaining -= size; + if (!ast->remaining) + { + avi->stream_index_2 = - 1; + ast->packet_size = 0; + if (size &1) + { + get_byte(pb); + size++; + } + } + + return size; + } + + memset(d, - 1, sizeof(int) *8); + for (i = sync = url_ftell(pb); !url_feof(pb); i++) + { + int j; + + if (i >= avi->movi_end) + break; + + for (j = 0; j < 7; j++) + d[j] = d[j + 1]; + + d[7] = get_byte(pb); + + size = d[4] + (d[5] << 8) + (d[6] << 16) + (d[7] << 24); + + if (d[2] >= '0' && d[2] <= '9' && d[3] >= '0' && d[3] <= '9') + { + n = (d[2] - '0') *10+(d[3] - '0'); + } + else + { + n = 100; //invalid stream id + } + + if (i + size > avi->movi_end || d[0] < 0) + continue; + + if ((d[0] == 'i' && d[1] == 'x' && n < s->nb_streams) + || (d[0] == 'J' && d[1] == 'U' && d[2] == 'N' && d[3] == 'K')) + { + url_fskip(pb, size); + goto resync; + } + + if (d[0] >= '0' && d[0] <= '9' && d[1] >= '0' && d[1] <= '9') + { + n = (d[0] - '0') *10+(d[1] - '0'); + } + else + { + n = 100; //invalid stream id + } + + //parse ##dc/##wb + if (n < s->nb_streams) + { + AVStream *st; + AVIStream *ast; + st = s->streams[n]; + ast = st->priv_data; + + if(sync + 9 <= i) + { + int dbg=0; + } + else + { + int dbg1=0; + } + + if (((ast->prefix_count < 5 || sync + 9 > i) && d[2] < 128 && d[3] < 128) + || d[2] * 256 + d[3] == ast->prefix) + { + if (d[2] * 256 + d[3] == ast->prefix) + ast->prefix_count++; + else + { + ast->prefix = d[2] *256+d[3]; + ast->prefix_count = 0; + } + + avi->stream_index_2 = n; + ast->packet_size = size + 8; + ast->remaining = size; + goto resync; + } + } + // palette changed chunk + if (d[0] >= '0' && d[0] <= '9' && d[1] >= '0' && d[1] <= '9' + && (d[2] == 'p' && d[3] == 'c') && n < s->nb_streams && i + size <= avi->movi_end) + { + AVStream *st; + int first, clr, flags, k, p; + + st = s->streams[n]; + + first = get_byte(pb); + clr = get_byte(pb); + if (!clr) // all 256 colors used + clr = 256; + flags = get_le16(pb); + p = 4; + for (k = first; k < clr + first; k++) + { + int r, g, b; + r = get_byte(pb); + g = get_byte(pb); + b = get_byte(pb); + get_byte(pb); + st->actx->palctrl->palette[k] = b + (g << 8) + (r << 16); + } + st->actx->palctrl->palette_changed = 1; + goto resync; + } + } + + return - 1; +} + +static int avi_read_idx1(AVFormatContext *s, int size) +{ + AVIContext *avi = s->priv_data; + ByteIOContext *pb = &s->pb; + int nb_index_entries, i; + AVStream *st; + AVIStream *ast; + unsigned int index, tag, flags, pos, len; + unsigned last_pos = - 1; + + nb_index_entries = size / 16; + if (nb_index_entries <= 0) + return - 1; + + for (i = 0; i < nb_index_entries; i++)// read the entries and sort them in each stream component + { + tag = get_le32(pb); + flags = get_le32(pb); + pos = get_le32(pb); + len = get_le32(pb); + + if (i == 0 && pos > avi->movi_list) + avi->movi_list = 0; + + pos += avi->movi_list; + + index = ((tag &0xff) - '0') *10; + index += ((tag >> 8) &0xff) - '0'; + if (index >= s->nb_streams) + continue; + + st = s->streams[index]; + ast = st->priv_data; + + if (last_pos == pos) + avi->non_interleaved = 1; + else + av_add_index_entry(st, pos, ast->cum_len, len, 0, (flags &AVIIF_INDEX) ? AVINDEX_KEYFRAME : 0); + + if (ast->sample_size) + ast->cum_len += len / ast->sample_size; + else + ast->cum_len++; + last_pos = pos; + } + return 0; +} + +static int guess_ni_flag(AVFormatContext *s) +{ + int i; + int64_t last_start = 0; + int64_t first_end = INT64_MAX; + + for (i = 0; i < s->nb_streams; i++) + { + AVStream *st = s->streams[i]; + int n = st->nb_index_entries; + + if (n <= 0) + continue; + + if (st->index_entries[0].pos > last_start) + last_start = st->index_entries[0].pos; + + if (st->index_entries[n - 1].pos < first_end) + first_end = st->index_entries[n - 1].pos; + } + return last_start > first_end; +} + +static int avi_load_index(AVFormatContext *s) +{ + AVIContext *avi = s->priv_data; + ByteIOContext *pb = &s->pb; + uint32_t tag, size; + offset_t pos = url_ftell(pb); + + url_fseek(pb, avi->movi_end, SEEK_SET); + + for (;;) + { + if (url_feof(pb)) + break; + tag = get_le32(pb); + size = get_le32(pb); + + switch (tag) + { + case MKTAG('i', 'd', 'x', '1'): + if (avi_read_idx1(s, size) < 0) + goto skip; + else + goto the_end; + break; + default: +skip: + size += (size &1); + url_fskip(pb, size); + break; + } + } +the_end: + url_fseek(pb, pos, SEEK_SET); + return 0; +} + +static int avi_read_close(AVFormatContext *s) +{ + int i; + AVIContext *avi = s->priv_data; + + for (i = 0; i < s->nb_streams; i++) + { + AVStream *st = s->streams[i]; + AVIStream *ast = st->priv_data; + av_free(ast); + av_free(st->actx->extradata); + av_free(st->actx->palctrl); + } + + return 0; +} + +static int avi_probe(AVProbeData *p) +{ + if (p->buf_size <= 32) // check file header + return 0; + if (p->buf[0] == 'R' && p->buf[1] == 'I' && p->buf[2] == 'F' && p->buf[3] == 'F' + && p->buf[8] == 'A' && p->buf[9] == 'V' && p->buf[10] == 'I'&& p->buf[11] == ' ') + return AVPROBE_SCORE_MAX; + else + return 0; +} + +AVInputFormat avi_iformat = +{ + "avi", + sizeof(AVIContext), + avi_probe, + avi_read_header, + avi_read_packet, + avi_read_close, +}; + +/* ֵ֧ĸʽijʼ */ +int avidec_init(void) +{ + // עʽ + av_register_input_format(&avi_iformat); + return 0; +} + +/* + AVIF_HASINDEXAVIļ"idx1" + AVIF_MUSTUSEINDEXָ˳ + AVIF_ISINTERLEAVEDAVIļinterleavedʽ + AVIF_WASCAPTUREFILEAVIļò׽ʵʱƵרŷļ + AVIF_COPYRIGHTEDAVIļаȨϢ + + AVIF_MUSTUSEINDEX : ӦóҪʹindexϵ˳ݵչ˳ + 磬ñ־ڴһ༭õ֡б +// */ \ No newline at end of file diff --git a/ffplay源码和书籍/ffplay/libavformat/avio.c b/ffplay源码和书籍/ffplay/libavformat/avio.c new file mode 100644 index 0000000..1fedd2e --- /dev/null +++ b/ffplay源码和书籍/ffplay/libavformat/avio.c @@ -0,0 +1,134 @@ +/************************************************************************ +** ļʵ URLProtocol ļ +** URLProtocol ǵײļ(file,pipe )ļ򵥷װ +** һֻһתվ󲿷ֺǼתײľʵֺ +/************************************************************************/ + +#include "../berrno.h" +#include "avformat.h" + +/* ffmpegֶ֧Э飬ֵ֧Э鴮 */ +URLProtocol *first_protocol = NULL; + +/* עЭ飨νЭݵ壺ļ׽ֵʽ */ +int register_protocol(URLProtocol *protocol) +{ + URLProtocol **p; + p = &first_protocol; + while (*p != NULL) + p = &(*p)->next; + *p = protocol; + protocol->next = NULL; + return 0; +} + +/* URL */ +int url_open(URLContext **puc, const char *filename, int flags) +{ + // + URLContext *uc; + // Э鼰 + URLProtocol *up; + const char *p; + // Эַ + char proto_str[128], *q; + int err; + + p = filename; + q = proto_str; + + // ȷЭ + while (*p != '\0' && *p != ':') + { + if (!isalpha(*p)) // protocols can only contain alphabetic chars + goto file_proto; + if ((q - proto_str) < sizeof(proto_str) - 1) + *q++ = *p; + p++; + } + // if the protocol has length 1, we consider it is a dos drive + if (*p == '\0' || (q - proto_str) <= 1) + { +file_proto: + strcpy(proto_str, "file"); + } + else + { + *q = '\0'; + } + + up = first_protocol; + + // ѰҺЭ + while (up != NULL) + { + if (!strcmp(proto_str, up->name)) + goto found; + up = up->next; + } + err = - ENOENT; + goto fail; +found: + + // URL + uc = av_malloc(sizeof(URLContext) + strlen(filename)); + if (!uc) + { + err = - ENOMEM; + goto fail; + } + strcpy(uc->filename, filename); + uc->prot = up; + uc->flags = flags; + uc->max_packet_size = 0; // default: stream file + + // URL + err = up->url_open(uc, filename, flags); + if (err < 0) + { + av_free(uc); + *puc = NULL; + return err; + } + *puc = uc; + return 0; +fail: + *puc = NULL; + return err; +} + +/* ȡ */ +int url_read(URLContext *h, unsigned char *buf, int size) +{ + int ret; + if (h->flags &URL_WRONLY) + return AVERROR_IO; + ret = h->prot->url_read(h, buf, size); + return ret; +} + +/* ڹļת */ +offset_t url_seek(URLContext *h, offset_t pos, int whence) +{ + offset_t ret; + + if (!h->prot->url_seek) + return - EPIPE; + ret = h->prot->url_seek(h, pos, whence); + return ret; +} + +/* رURL */ +int url_close(URLContext *h) +{ + int ret; + + ret = h->prot->url_close(h); + av_free(h); + return ret; +} + +int url_get_max_packet_size(URLContext *h) +{ + return h->max_packet_size; +} diff --git a/ffplay源码和书籍/ffplay/libavformat/avio.h b/ffplay源码和书籍/ffplay/libavformat/avio.h new file mode 100644 index 0000000..f427d59 --- /dev/null +++ b/ffplay源码和书籍/ffplay/libavformat/avio.h @@ -0,0 +1,119 @@ +#ifndef AVIO_H +#define AVIO_H + +/* +** ļдģ鶨ݽṹͺ +*/ + +#define URL_EOF (-1) + +typedef int64_t offset_t; + +/* ļʵȨ޵Ķ */ +#define URL_RDONLY 0 +#define URL_WRONLY 1 +#define URL_RDWR 2 + +/* +** URLģʾһ루ļ׽ +** URLContext ṹʾеĵǰļЭʹõģйļЭ鹲е +** (ڳʱȷֵ)͹ṹֶ +*/ +typedef struct URLContext +{ + // Э + struct URLProtocol *prot; + int flags; + int max_packet_size; // if non zero, the stream is packetized with this max packet size + void *priv_data; // fileһļЭ飬Ϳ + char filename[1]; // specified filename +} URLContext; + +/* +** URLЭ飨ļ׽IJ +** URLProtocol ļЭ飬ڹܺ +** һֹļЭӦһ URLProtocol ṹ +** ɾ pipeudptcpЭ飬һ file Э +*/ +typedef struct URLProtocol +{ + const char *name; + int(*url_open)(URLContext *h, const char *filename, int flags); + int(*url_read)(URLContext *h, unsigned char *buf, int size); + int(*url_write)(URLContext *h, unsigned char *buf, int size); + offset_t(*url_seek)(URLContext *h, offset_t pos, int whence); + int(*url_close)(URLContext *h); + struct URLProtocol *next; +} URLProtocol; + +/* +** ϵģļ +*/ +typedef struct ByteIOContext +{ + // ݻ + unsigned char *buffer; + // С + int buffer_size; + // ЧֽڷΧ + unsigned char *buf_ptr, *buf_end; + // + void *opaque; + // ȡ + int (*read_buf)(void *opaque, uint8_t *buf, int buf_size); + // д + int (*write_buf)(void *opaque, uint8_t *buf, int buf_size); + // bufferָ + offset_t(*seek)(void *opaque, offset_t offset, int whence); + // λ + offset_t pos; // position in the file of the current buffer + // DzDZҪˢ + int must_flush; // true if the next seek should flush + // Ƿ񵽴ļβ + int eof_reached; // true if eof reached + // Ƿд + int write_flag; // true if open for writing + // ݰĴС + int max_packet_size; + // + int error; // contains the error code or 0 if no error happened +} ByteIOContext; + +int url_open(URLContext **h, const char *filename, int flags); +int url_read(URLContext *h, unsigned char *buf, int size); +int url_write(URLContext *h, unsigned char *buf, int size); +offset_t url_seek(URLContext *h, offset_t pos, int whence); +int url_close(URLContext *h); +int url_get_max_packet_size(URLContext *h); + +int register_protocol(URLProtocol *protocol); + +int init_put_byte(ByteIOContext *s, + unsigned char *buffer, + int buffer_size, + int write_flag, + void *opaque, + int(*read_buf)(void *opaque, uint8_t *buf, int buf_size), + int(*write_buf)(void *opaque, uint8_t *buf, int buf_size), + offset_t(*seek)(void *opaque, offset_t offset, int whence)); + +offset_t url_fseek(ByteIOContext *s, offset_t offset, int whence); +void url_fskip(ByteIOContext *s, offset_t offset); +offset_t url_ftell(ByteIOContext *s); +offset_t url_fsize(ByteIOContext *s); +int url_feof(ByteIOContext *s); +int url_ferror(ByteIOContext *s); + +int url_fread(ByteIOContext *s, unsigned char *buf, int size); // get_buffer +int get_byte(ByteIOContext *s); +unsigned int get_le32(ByteIOContext *s); +unsigned int get_le16(ByteIOContext *s); + +int url_setbufsize(ByteIOContext *s, int buf_size); +int url_fopen(ByteIOContext *s, const char *filename, int flags); +int url_fclose(ByteIOContext *s); + +int url_open_buf(ByteIOContext *s, uint8_t *buf, int buf_size, int flags); +int url_close_buf(ByteIOContext *s); + +#endif diff --git a/ffplay源码和书籍/ffplay/libavformat/aviobuf.c b/ffplay源码和书籍/ffplay/libavformat/aviobuf.c new file mode 100644 index 0000000..7bdebc7 --- /dev/null +++ b/ffplay源码和书籍/ffplay/libavformat/aviobuf.c @@ -0,0 +1,324 @@ +/* +** лĹļ ByteIOContext صļ +** ByteIOContextURLContextIJͬڣByteIOContextǴģByteIOContextIJǻڻĶǻļ +** URLContextȡݽByteIOContextURLContextByteIOContext棬ByteIOContextĵײ +*/ + +#include "../berrno.h" +#include "avformat.h" +#include "avio.h" +#include + +/* Ļ泤 */ +#define IO_BUFFER_SIZE 32768 + +/* +** ʼ ByteIOContext ṹ +*/ +int init_put_byte(ByteIOContext *s, + unsigned char *buffer, + int buffer_size, + int write_flag, + void *opaque, + int(*read_buf)(void *opaque, uint8_t *buf, int buf_size), + int(*write_buf)(void *opaque, uint8_t *buf, int buf_size), + offset_t(*seek)(void *opaque, offset_t offset, int whence)) +{ + s->buffer = buffer; + s->buffer_size = buffer_size; + s->buf_ptr = buffer; + s->write_flag = write_flag; + if (!s->write_flag) + s->buf_end = buffer; + else + s->buf_end = buffer + buffer_size; + s->opaque = opaque; + s->write_buf = write_buf; + s->read_buf = read_buf; + s->seek = seek; + s->pos = 0; + s->must_flush = 0; + s->eof_reached = 0; + s->error = 0; + s->max_packet_size = 0; + + return 0; +} + +/* +** ļ ByteIOContext seek +*/ +offset_t url_fseek(ByteIOContext *s, offset_t offset, int whence) +{ + offset_t offset1; + + if (whence != SEEK_CUR && whence != SEEK_SET) + return - EINVAL; + + if (whence == SEEK_CUR) + { + offset1 = s->pos - (s->buf_end - s->buffer) + (s->buf_ptr - s->buffer); + if (offset == 0) + return offset1; + offset += offset1; + } + offset1 = offset - (s->pos - (s->buf_end - s->buffer)); + if (offset1 >= 0 && offset1 <= (s->buf_end - s->buffer)) + { + s->buf_ptr = s->buffer + offset1; // can do the seek inside the buffer + } + else + { + if (!s->seek) + return - EPIPE; + s->buf_ptr = s->buffer; + s->buf_end = s->buffer; + if (s->seek(s->opaque, offset, SEEK_SET) == (offset_t) - EPIPE) + return - EPIPE; + s->pos = offset; + } + s->eof_reached = 0; + + return offset; +} + +/* ת */ +void url_fskip(ByteIOContext *s, offset_t offset) +{ + url_fseek(s, offset, SEEK_CUR); +} + +/* ȡ */ +offset_t url_ftell(ByteIOContext *s) +{ + return url_fseek(s, 0, SEEK_CUR); +} + +/* ļС */ +offset_t url_fsize(ByteIOContext *s) +{ + offset_t size; + + if (!s->seek) + return - EPIPE; + size = s->seek(s->opaque, - 1, SEEK_END) + 1; + s->seek(s->opaque, s->pos, SEEK_SET); + return size; +} + +/* Ƿ񵽴ļβ */ +int url_feof(ByteIOContext *s) +{ + return s->eof_reached; +} + +/* */ +int url_ferror(ByteIOContext *s) +{ + return s->error; +} + +// Input stream +/* bufferҲһȡļIJ */ +static void fill_buffer(ByteIOContext *s) +{ + int len; + + if (s->eof_reached) + return ; + + len = s->read_buf(s->opaque, s->buffer, s->buffer_size); + if (len <= 0) + { // do not modify buffer if EOF reached so that a seek back can be done without rereading data + s->eof_reached = 1; + + if (len < 0) + s->error = len; + } + else + { + s->pos += len; + s->buf_ptr = s->buffer; + s->buf_end = s->buffer + len; + } +} + +/* ȡһֽ */ +int get_byte(ByteIOContext *s) // NOTE: return 0 if EOF, so you cannot use it if EOF handling is necessary +{ + if (s->buf_ptr < s->buf_end) + { + return *s->buf_ptr++; + } + else + { + // ȡ + fill_buffer(s); + if (s->buf_ptr < s->buf_end) + return *s->buf_ptr++; + else + return 0; + } +} + +/* ӹļ ByteIOContext С˷ʽȡֽ,ʵִָ get_byte() */ +unsigned int get_le16(ByteIOContext *s) +{ + unsigned int val; + val = get_byte(s); + val |= get_byte(s) << 8; + return val; +} + +/* ӹļ ByteIOContext С˷ʽȡĸֽ,ʵִָ get_le16() */ +unsigned int get_le32(ByteIOContext *s) +{ + unsigned int val; + val = get_le16(s); + val |= get_le16(s) << 16; + return val; +} + +#define url_write_buf NULL + +/* ת */ +static int url_read_buf(void *opaque, uint8_t *buf, int buf_size) +{ + URLContext *h = opaque; + return url_read(h, buf, buf_size); +} + +/* ת seek */ +static offset_t url_seek_buf(void *opaque, offset_t offset, int whence) +{ + URLContext *h = opaque; + return url_seek(h, offset, whence); +} + +/* òļ ByteIOContext ڲĴСӦ޸ڲС */ +int url_setbufsize(ByteIOContext *s, int buf_size) // must be called before any I/O +{ + uint8_t *buffer; + buffer = av_malloc(buf_size); + if (!buffer) + return - ENOMEM; + + av_free(s->buffer); + s->buffer = buffer; + s->buffer_size = buf_size; + s->buf_ptr = buffer; + if (!s->write_flag) + s->buf_end = buffer; + else + s->buf_end = buffer + buf_size; + return 0; +} + +/* 򿪹ļ ByteIOContext */ +int url_fopen(ByteIOContext *s, const char *filename, int flags) +{ + URLContext *h; + uint8_t *buffer; + int buffer_size, max_packet_size; + int err; + + err = url_open(&h, filename, flags); + if (err < 0) + return err; + + max_packet_size = url_get_max_packet_size(h); + if (max_packet_size) + { + buffer_size = max_packet_size; // no need to bufferize more than one packet + } + else + { + buffer_size = IO_BUFFER_SIZE; + } + + buffer = av_malloc(buffer_size); + if (!buffer) + { + url_close(h); + return - ENOMEM; + } + + if (init_put_byte(s, + buffer, + buffer_size, + (h->flags & URL_WRONLY || h->flags & URL_RDWR), + h, + url_read_buf, + url_write_buf, + url_seek_buf) < 0) + { + url_close(h); + av_free(buffer); + return AVERROR_IO; + } + + s->max_packet_size = max_packet_size; + + return 0; +} + +/* رչļ ByteIOContext */ +int url_fclose(ByteIOContext *s) +{ + URLContext *h = s->opaque; + + av_free(s->buffer); + memset(s, 0, sizeof(ByteIOContext)); + return url_close(h); +} + +/* ļ ByteIOContext */ +int url_fread(ByteIOContext *s, unsigned char *buf, int size) // get_buffer +{ + int len, size1; + + size1 = size; + while (size > 0) + { + len = s->buf_end - s->buf_ptr; + if (len > size) + len = size; + if (len == 0) + { + if (size > s->buffer_size) + { + len = s->read_buf(s->opaque, buf, size); + if (len <= 0) + { + s->eof_reached = 1; + if (len < 0) + s->error = len; + break; + } + else + { + s->pos += len; + size -= len; + buf += len; + s->buf_ptr = s->buffer; + s->buf_end = s->buffer /* + len*/; + } + } + else + { + fill_buffer(s); + len = s->buf_end - s->buf_ptr; + if (len == 0) + break; + } + } + else + { + memcpy(buf, s->buf_ptr, len); + buf += len; + s->buf_ptr += len; + size -= len; + } + } + return size1 - size; +} diff --git a/ffplay源码和书籍/ffplay/libavformat/cutils.c b/ffplay源码和书籍/ffplay/libavformat/cutils.c new file mode 100644 index 0000000..a5b7ddf --- /dev/null +++ b/ffplay源码和书籍/ffplay/libavformat/cutils.c @@ -0,0 +1,46 @@ +/* +** ַIJ +*/ + +#include "avformat.h" + +/* +** str ַ val ַָʾͷȥͷ*ptr +*/ +int strstart(const char *str, const char *val, const char **ptr) +{ + const char *p, *q; + p = str; + q = val; + while (*q != '\0') + { + if (*p != *q) + return 0; + p++; + q++; + } + if (ptr) + *ptr = p; + return 1; +} + +/* +** ַ +*/ +void pstrcpy(char *buf, int buf_size, const char *str) +{ + int c; + char *q = buf; + + if (buf_size <= 0) + return ; + + for (;;) + { + c = *str++; + if (c == 0 || q >= buf + buf_size - 1) + break; + *q++ = c; + } + *q = '\0'; +} diff --git a/ffplay源码和书籍/ffplay/libavformat/file.c b/ffplay源码和书籍/ffplay/libavformat/file.c new file mode 100644 index 0000000..af7bcfc --- /dev/null +++ b/ffplay源码和书籍/ffplay/libavformat/file.c @@ -0,0 +1,89 @@ +/* +** ffplay file rtsprtptcp ЭһЭ飬 file:ǰ׺ʾ file Э顣 +** URLContext ṹͳһʾЩϵЭ飬ṩͳһijӿڡ +** ĹЭʵļʵ URLContext ӿڡļʵ file Э URLContext ӿ +*/ + +#include "../berrno.h" + +#include "avformat.h" +#include + +#ifndef CONFIG_WIN32 +#include +#include +#include +#else +#include +#define open(fname,oflag,pmode) _open(fname,oflag,pmode) +#endif + +/* +** ļ +*/ +static int file_open(URLContext *h, const char *filename, int flags) +{ + int access; + int fd; + + // fileЭ + strstart(filename, "file:", &filename); + + // ʱ־ + if (flags &URL_RDWR) + access = O_CREAT | O_TRUNC | O_RDWR; + else if (flags &URL_WRONLY) + access = O_CREAT | O_TRUNC | O_WRONLY; + else + access = O_RDONLY; +#if defined(CONFIG_WIN32) || defined(CONFIG_OS2) || defined(__CYGWIN__) + access |= O_BINARY; +#endif + // ļ + fd = open(filename, access, 0666); + if (fd < 0) + return - ENOENT; + + // ļURLContextpriv_data + h->priv_data = (void*)(size_t)fd; + return 0; +} + +/* ȡ */ +static int file_read(URLContext *h, unsigned char *buf, int size) +{ + int fd = (size_t)h->priv_data; + return read(fd, buf, size); +} + +/* д */ +static int file_write(URLContext *h, unsigned char *buf, int size) +{ + int fd = (size_t)h->priv_data; + return write(fd, buf, size); +} + +/* ת */ +static offset_t file_seek(URLContext *h, offset_t pos, int whence) +{ + int fd = (size_t)h->priv_data; + return lseek(fd, pos, whence); +} + +/* رļ */ +static int file_close(URLContext *h) +{ + int fd = (size_t)h->priv_data; + return close(fd); +} + +/* FILE͵protocol */ +URLProtocol file_protocol = +{ + "file", + file_open, + file_read, + file_write, + file_seek, + file_close, +}; diff --git a/ffplay源码和书籍/ffplay/libavformat/utils_format.c b/ffplay源码和书籍/ffplay/libavformat/utils_format.c new file mode 100644 index 0000000..8e9a4d6 --- /dev/null +++ b/ffplay源码和书籍/ffplay/libavformat/utils_format.c @@ -0,0 +1,345 @@ +/* +** ʶļʽýʽʹõһЩຯ +*/ +#include "../berrno.h" +#include "avformat.h" +#include + +#define UINT_MAX (0xffffffff) + +#define PROBE_BUF_MIN 2048 +#define PROBE_BUF_MAX 131072 + +/* Ϊֵ֧ĸʽкܶ࣬Ҫֵ֧ĸʽ */ +AVInputFormat *first_iformat = NULL; + +/* עĸʽ*/ +void av_register_input_format(AVInputFormat *format) +{ + AVInputFormat **p; + p = &first_iformat; + while (*p != NULL) + p = &(*p)->next; + *p = format; + format->next = NULL; +} + +/* Ƚļչʶļ */ +int match_ext(const char *filename, const char *extensions) +{ + const char *ext, *p; + char ext1[32], *q; + + if (!filename) + return 0; + + ext = strrchr(filename, '.'); + if (ext) + { + ext++; + p = extensions; + for (;;) + { + q = ext1; + while (*p != '\0' && *p != ',' && q - ext1 < sizeof(ext1) - 1) + *q++ = *p++; + *q = '\0'; + if (!strcasecmp(ext1, ext)) + return 1; + if (*p == '\0') + break; + p++; + } + } + return 0; +} + +/* ̽ļʽʶļʽ */ +AVInputFormat *av_probe_input_format(AVProbeData *pd, int is_opened) +{ + AVInputFormat *fmt1, *fmt; + int score, score_max; + + fmt = NULL; + score_max = 0; + for (fmt1 = first_iformat; fmt1 != NULL; fmt1 = fmt1->next) + { + if (!is_opened) + continue; + + score = 0; + if (fmt1->read_probe) + { + score = fmt1->read_probe(pd); + } + else if (fmt1->extensions) + { + if (match_ext(pd->filename, fmt1->extensions)) + score = 50; + } + if (score > score_max) + { + score_max = score; + fmt = fmt1; + } + } + return fmt; +} + +/* */ +int av_open_input_stream(AVFormatContext **ic_ptr, ByteIOContext *pb, const char *filename, + AVInputFormat *fmt, AVFormatParameters *ap) +{ + int err; + AVFormatContext *ic; + AVFormatParameters default_ap; + + if (!ap) + { + ap = &default_ap; + memset(ap, 0, sizeof(default_ap)); + } + + ic = av_mallocz(sizeof(AVFormatContext)); + if (!ic) + { + err = AVERROR_NOMEM; + goto fail; + } + ic->iformat = fmt; + if (pb) + ic->pb = *pb; + + if (fmt->priv_data_size > 0) + { + ic->priv_data = av_mallocz(fmt->priv_data_size); + if (!ic->priv_data) + { + err = AVERROR_NOMEM; + goto fail; + } + } + else + { + ic->priv_data = NULL; + } + + err = ic->iformat->read_header(ic, ap); + if (err < 0) + goto fail; + + *ic_ptr = ic; + return 0; + +fail: + if (ic) + av_freep(&ic->priv_data); + + av_free(ic); + *ic_ptr = NULL; + return err; +} + +/* ļʶļʽȻúʶýʽ */ +int av_open_input_file(AVFormatContext **ic_ptr, const char *filename, AVInputFormat *fmt, + int buf_size, AVFormatParameters *ap) +{ + int err, must_open_file, file_opened, probe_size; + AVProbeData probe_data, *pd = &probe_data; + ByteIOContext pb1, *pb = &pb1; + + file_opened = 0; + pd->filename = ""; + if (filename) + pd->filename = filename; + pd->buf = NULL; + pd->buf_size = 0; + + must_open_file = 1; + + if (!fmt || must_open_file) + { + if (url_fopen(pb, filename, URL_RDONLY) < 0) + { + err = AVERROR_IO; + goto fail; + } + file_opened = 1; + if (buf_size > 0) + url_setbufsize(pb, buf_size); + + for (probe_size = PROBE_BUF_MIN; probe_size <= PROBE_BUF_MAX && !fmt; probe_size <<= 1) + { + pd->buf = av_realloc(pd->buf, probe_size); + pd->buf_size = url_fread(pb, pd->buf, probe_size); + if (url_fseek(pb, 0, SEEK_SET) == (offset_t) - EPIPE) + { + url_fclose(pb); + if (url_fopen(pb, filename, URL_RDONLY) < 0) + { + file_opened = 0; + err = AVERROR_IO; + goto fail; + } + } + + fmt = av_probe_input_format(pd, 1); + } + av_freep(&pd->buf); + } + + if (!fmt) + { + err = AVERROR_NOFMT; + goto fail; + } + + err = av_open_input_stream(ic_ptr, pb, filename, fmt, ap); + if (err) + goto fail; + return 0; + +fail: + av_freep(&pd->buf); + if (file_opened) + url_fclose(pb); + *ic_ptr = NULL; + return err; +} + +/* һζȡһݰ */ +int av_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + return s->iformat->read_packet(s, pkt); +} + +/* +** ЩýļΪ seekƵ֡ffplay Щʱ +** ŵһСֵ +*/ +int av_add_index_entry(AVStream *st, int64_t pos, int64_t timestamp, int size, int distance, int flags) +{ + AVIndexEntry *entries, *ie; + int index; + + if ((unsigned)st->nb_index_entries + 1 >= UINT_MAX / sizeof(AVIndexEntry)) // Խж + return - 1; + + entries = av_fast_realloc(st->index_entries, &st->index_entries_allocated_size, + (st->nb_index_entries + 1) * sizeof(AVIndexEntry)); + if (!entries) + return - 1; + + st->index_entries = entries; + + index = av_index_search_timestamp(st, timestamp, AVSEEK_FLAG_ANY); + + if (index < 0) // + { + index = st->nb_index_entries++; + ie = &entries[index]; + assert(index == 0 || ie[ - 1].timestamp < timestamp); + } + else // в + { + ie = &entries[index]; + if (ie->timestamp != timestamp) + { + if (ie->timestamp <= timestamp) + return - 1; + + memmove(entries + index + 1, entries + index, + sizeof(AVIndexEntry)*(st->nb_index_entries - index)); + + st->nb_index_entries++; + } + } + + ie->pos = pos; + ie->timestamp = timestamp; + ie->size = size; + ie->flags = flags; + + return index; +} + +int av_index_search_timestamp(AVStream *st, int64_t wanted_timestamp, int flags) +{ + AVIndexEntry *entries = st->index_entries; + int nb_entries = st->nb_index_entries; + int a, b, m; + int64_t timestamp; + + a = - 1; + b = nb_entries; + + while (b - a > 1) //ûм¼idxֵõ۰ + { + m = (a + b) >> 1; + timestamp = entries[m].timestamp; + if (timestamp >= wanted_timestamp) + b = m; + if (timestamp <= wanted_timestamp) + a = m; + } + + m = (flags &AVSEEK_FLAG_BACKWARD) ? a : b; + + if (!(flags &AVSEEK_FLAG_ANY)) + { + while (m >= 0 && m < nb_entries && !(entries[m].flags &AVINDEX_KEYFRAME)) + { + m += (flags &AVSEEK_FLAG_BACKWARD) ? - 1: 1; + } + } + + if (m == nb_entries) + return - 1; + + return m; +} + +void av_close_input_file(AVFormatContext *s) +{ + int i; + AVStream *st; + + if (s->iformat->read_close) + s->iformat->read_close(s); + + for (i = 0; i < s->nb_streams; i++) + { + st = s->streams[i]; + av_free(st->index_entries); + av_free(st->actx); + av_free(st); + } + + url_fclose(&s->pb); + + av_freep(&s->priv_data); + av_free(s); +} + +AVStream *av_new_stream(AVFormatContext *s, int id) +{ + AVStream *st; + + if (s->nb_streams >= MAX_STREAMS) + return NULL; + + st = av_mallocz(sizeof(AVStream)); + if (!st) + return NULL; + + st->actx = avcodec_alloc_context(); + + s->streams[s->nb_streams++] = st; + return st; +} + +void av_set_pts_info(AVStream *s, int pts_wrap_bits, int pts_num, int pts_den) +{ + s->time_base.num = pts_num; + s->time_base.den = pts_den; +} diff --git a/ffplay源码和书籍/ffplay/libavutil/avutil.h b/ffplay源码和书籍/ffplay/libavutil/avutil.h new file mode 100644 index 0000000..4d61644 --- /dev/null +++ b/ffplay源码和书籍/ffplay/libavutil/avutil.h @@ -0,0 +1,57 @@ +#ifndef AVUTIL_H +#define AVUTIL_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "common.h" +#include "bswap.h" +#include "mathematics.h" +#include "rational.h" + +#define AV_STRINGIFY(s) AV_TOSTRING(s) +#define AV_TOSTRING(s) #s + +#define LIBAVUTIL_VERSION_INT ((49<<16)+(0<<8)+0) +#define LIBAVUTIL_VERSION 49.0.0 +#define LIBAVUTIL_BUILD LIBAVUTIL_VERSION_INT + +#define LIBAVUTIL_IDENT "Lavu" AV_STRINGIFY(LIBAVUTIL_VERSION) + + /* ظʽ */ +enum PixelFormat +{ + PIX_FMT_NONE = - 1, + PIX_FMT_YUV420P, // Planar YUV 4:2:0 (1 Cr & Cb sample per 2x2 Y samples) + PIX_FMT_YUV422, // Packed pixel, Y0 Cb Y1 Cr + PIX_FMT_RGB24, // Packed pixel, 3 bytes per pixel, RGBRGB... + PIX_FMT_BGR24, // Packed pixel, 3 bytes per pixel, BGRBGR... + PIX_FMT_YUV422P, // Planar YUV 4:2:2 (1 Cr & Cb sample per 2x1 Y samples) + PIX_FMT_YUV444P, // Planar YUV 4:4:4 (1 Cr & Cb sample per 1x1 Y samples) + PIX_FMT_RGBA32, // Packed pixel, 4 bytes per pixel, BGRABGRA..., stored in cpu endianness + PIX_FMT_YUV410P, // Planar YUV 4:1:0 (1 Cr & Cb sample per 4x4 Y samples) + PIX_FMT_YUV411P, // Planar YUV 4:1:1 (1 Cr & Cb sample per 4x1 Y samples) + PIX_FMT_RGB565, // always stored in cpu endianness + PIX_FMT_RGB555, // always stored in cpu endianness, most significant bit to 1 + PIX_FMT_GRAY8, + PIX_FMT_MONOWHITE, // 0 is white + PIX_FMT_MONOBLACK, // 0 is black + PIX_FMT_PAL8, // 8 bit with RGBA palette + PIX_FMT_YUVJ420P, // Planar YUV 4:2:0 full scale (jpeg) + PIX_FMT_YUVJ422P, // Planar YUV 4:2:2 full scale (jpeg) + PIX_FMT_YUVJ444P, // Planar YUV 4:4:4 full scale (jpeg) + PIX_FMT_XVMC_MPEG2_MC, // XVideo Motion Acceleration via common packet passing(xvmc_render.h) + PIX_FMT_XVMC_MPEG2_IDCT, + PIX_FMT_UYVY422, // Packed pixel, Cb Y0 Cr Y1 + PIX_FMT_UYVY411, // Packed pixel, Cb Y0 Y1 Cr Y2 Y3 + PIX_FMT_NB, +}; + +#ifdef __cplusplus +} + +#endif + +#endif diff --git a/ffplay源码和书籍/ffplay/libavutil/bswap.h b/ffplay源码和书籍/ffplay/libavutil/bswap.h new file mode 100644 index 0000000..2bcc089 --- /dev/null +++ b/ffplay源码和书籍/ffplay/libavutil/bswap.h @@ -0,0 +1,29 @@ +/************************************************************************/ +/* ֽ˳򽻻 */ +/************************************************************************/ + +#ifndef __BSWAP_H__ +#define __BSWAP_H__ + +/* 16bitֽ˳򽻻 */ +static inline uint16_t bswap_16(uint16_t x) +{ + return (x >> 8) | (x << 8); +} + +/* 32bitֽ˳򽻻 */ +static inline uint32_t bswap_32(uint32_t x) +{ + x = ((x << 8) &0xFF00FF00) | ((x >> 8) &0x00FF00FF); + return (x >> 16) | (x << 16); +} + +// be2me ... BigEndian to MachineEndian +// le2me ... LittleEndian to MachineEndian + +#define be2me_16(x) bswap_16(x) +#define be2me_32(x) bswap_32(x) +#define le2me_16(x) (x) +#define le2me_32(x) (x) + +#endif diff --git a/ffplay源码和书籍/ffplay/libavutil/common.h b/ffplay源码和书籍/ffplay/libavutil/common.h new file mode 100644 index 0000000..765a8bf --- /dev/null +++ b/ffplay源码和书籍/ffplay/libavutil/common.h @@ -0,0 +1,69 @@ + +/************************************************************************/ +/* õͺͺ */ +/************************************************************************/ +#ifndef COMMON_H +#define COMMON_H + +#include +#include +#include +#include + +#if defined(WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__) +#define CONFIG_WIN32 +#endif + +#ifdef CONFIG_WIN32 +#define inline __inline +#endif + +typedef signed char int8_t; +typedef signed short int16_t; +typedef signed int int32_t; +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; + +#ifdef CONFIG_WIN32 +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; +#else +typedef signed long long int64_t; +typedef unsigned long long uint64_t; +#endif + +#ifdef CONFIG_WIN32 +#define int64_t_C(c) (c ## i64) +#define uint64_t_C(c) (c ## i64) +#else +#define int64_t_C(c) (c ## LL) +#define uint64_t_C(c) (c ## ULL) +#endif + +#ifndef INT64_MAX +#define INT64_MAX int64_t_C(9223372036854775807) +#endif + +/* Сд޹ַıȽ */ +static int strcasecmp(char *s1, const char *s2) +{ + while (toupper((unsigned char) *s1) == toupper((unsigned char) *s2++)) + if (*s1++ == '\0') + return 0; + + return (toupper((unsigned char) *s1) - toupper((unsigned char) *--s2)); +} + +/* ޷ */ +static inline int clip(int a, int amin, int amax) +{ + if (a < amin) + return amin; + else if (a > amax) + return amax; + else + return a; +} + +#endif diff --git a/ffplay源码和书籍/ffplay/libavutil/mathematics.h b/ffplay源码和书籍/ffplay/libavutil/mathematics.h new file mode 100644 index 0000000..aa986bd --- /dev/null +++ b/ffplay源码和书籍/ffplay/libavutil/mathematics.h @@ -0,0 +1,10 @@ +#ifndef MATHEMATICS_H +#define MATHEMATICS_H + +/* */ +static inline int64_t av_rescale(int64_t a, int64_t b, int64_t c) +{ + return a *b / c; +} + +#endif diff --git a/ffplay源码和书籍/ffplay/libavutil/rational.h b/ffplay源码和书籍/ffplay/libavutil/rational.h new file mode 100644 index 0000000..17459be --- /dev/null +++ b/ffplay源码和书籍/ffplay/libavutil/rational.h @@ -0,0 +1,20 @@ +/************************************************************************/ +/* */ +/************************************************************************/ +#ifndef RATIONAL_H +#define RATIONAL_H + +/* ṹ */ +typedef struct AVRational +{ + int num; // numerator // + int den; // denominator // ĸ +} AVRational; + +/* */ +static inline double av_q2d(AVRational a) +{ + return a.num / (double)a.den; +} + +#endif diff --git a/ffplay源码和书籍/ffplay/update.txt b/ffplay源码和书籍/ffplay/update.txt new file mode 100644 index 0000000..5a3d6d0 --- /dev/null +++ b/ffplay源码和书籍/ffplay/update.txt @@ -0,0 +1,2 @@ +ӭ mcodec.cnblogs.com +ϵ tslking@tom.com \ No newline at end of file