ffmpegthumbs-ffmpeg3.patch 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. From:
  2. Date:
  3. Subject:
  4. X-Git-Url: http://quickgit.kde.org/?p=ffmpegthumbs.git&a=commitdiff&h=3978c762072b7bc16b2096819b7cfa2052deaf5e
  5. ---
  6. ---
  7. --- a/CMakeLists.txt
  8. +++ b/CMakeLists.txt
  9. @@ -36,7 +36,7 @@
  10. add_library(ffmpegthumbs MODULE ${ffmpegthumbs_PART_SRCS})
  11. -target_link_libraries(ffmpegthumbs Qt5::Gui KF5::KIOWidgets ${AVUTIL_LIBRARIES} ${AVFORMAT_LIBRARIES} ${AVCODEC_LIBRARIES} ${SWSCALE_LIBRARIES} )
  12. +target_link_libraries(ffmpegthumbs Qt5::Gui KF5::KIOWidgets ${AVUTIL_LIBRARIES} ${AVFILTER_LIBRARIES} ${AVFORMAT_LIBRARIES} ${AVCODEC_LIBRARIES} ${SWSCALE_LIBRARIES} )
  13. install(TARGETS ffmpegthumbs DESTINATION ${PLUGIN_INSTALL_DIR})
  14. --- a/cmake/FindFFmpeg.cmake
  15. +++ b/cmake/FindFFmpeg.cmake
  16. @@ -99,6 +99,7 @@
  17. # Check for all possible component.
  18. find_component(AVCODEC libavcodec avcodec libavcodec/avcodec.h)
  19. + find_component(AVFILTER libavfilter avfilter libavfilter/avfilter.h)
  20. find_component(AVFORMAT libavformat avformat libavformat/avformat.h)
  21. find_component(AVDEVICE libavdevice avdevice libavdevice/avdevice.h)
  22. find_component(AVUTIL libavutil avutil libavutil/avutil.h)
  23. --- a/ffmpegthumbnailer/moviedecoder.cpp
  24. +++ b/ffmpegthumbnailer/moviedecoder.cpp
  25. @@ -40,6 +40,10 @@
  26. , m_FormatContextWasGiven(pavContext != NULL)
  27. , m_AllowSeek(true)
  28. , m_initialized(false)
  29. + , m_bufferSinkContext(nullptr)
  30. + , m_bufferSourceContext(nullptr)
  31. + , m_filterGraph(nullptr)
  32. + , m_filterFrame(nullptr)
  33. {
  34. initialize(filename);
  35. }
  36. @@ -51,6 +55,9 @@
  37. void MovieDecoder::initialize(const QString& filename)
  38. {
  39. + m_lastWidth = -1;
  40. + m_lastHeight = -1;
  41. + m_lastPixfmt = AV_PIX_FMT_NONE;
  42. av_register_all();
  43. avcodec_register_all();
  44. @@ -67,7 +74,7 @@
  45. }
  46. initializeVideo();
  47. - m_pFrame = avcodec_alloc_frame();
  48. + m_pFrame = av_frame_alloc();
  49. if (m_pFrame) {
  50. m_initialized=true;
  51. @@ -82,6 +89,7 @@
  52. void MovieDecoder::destroy()
  53. {
  54. + deleteFilterGraph();
  55. if (m_pVideoCodecContext) {
  56. avcodec_close(m_pVideoCodecContext);
  57. m_pVideoCodecContext = NULL;
  58. @@ -93,13 +101,13 @@
  59. }
  60. if (m_pPacket) {
  61. - av_free_packet(m_pPacket);
  62. + av_packet_unref(m_pPacket);
  63. delete m_pPacket;
  64. m_pPacket = NULL;
  65. }
  66. if (m_pFrame) {
  67. - av_free(m_pFrame);
  68. + av_frame_free(&m_pFrame);
  69. m_pFrame = NULL;
  70. }
  71. @@ -239,7 +247,7 @@
  72. return false;
  73. }
  74. - avcodec_get_frame_defaults(m_pFrame);
  75. + av_frame_unref(m_pFrame);
  76. int frameFinished = 0;
  77. @@ -264,7 +272,7 @@
  78. int attempts = 0;
  79. if (m_pPacket) {
  80. - av_free_packet(m_pPacket);
  81. + av_packet_unref(m_pPacket);
  82. delete m_pPacket;
  83. }
  84. @@ -275,7 +283,7 @@
  85. if (framesAvailable) {
  86. frameDecoded = m_pPacket->stream_index == m_VideoStream;
  87. if (!frameDecoded) {
  88. - av_free_packet(m_pPacket);
  89. + av_packet_unref(m_pPacket);
  90. }
  91. }
  92. }
  93. @@ -283,15 +291,100 @@
  94. return frameDecoded;
  95. }
  96. +void MovieDecoder::deleteFilterGraph()
  97. +{
  98. + if (m_filterGraph) {
  99. + av_frame_free(&m_filterFrame);
  100. + avfilter_graph_free(&m_filterGraph);
  101. + m_filterGraph = nullptr;
  102. + }
  103. +}
  104. +
  105. +bool MovieDecoder::initFilterGraph(enum AVPixelFormat pixfmt, int width, int height)
  106. +{
  107. + AVFilterInOut *inputs = nullptr, *outputs = nullptr;
  108. +
  109. + deleteFilterGraph();
  110. + m_filterGraph = avfilter_graph_alloc();
  111. +
  112. + QByteArray arguments("buffer=");
  113. + arguments += "video_size=" + QByteArray::number(width) + "x" + QByteArray::number(height) + ":";
  114. + arguments += "pix_fmt=" + QByteArray::number(pixfmt) + ":";
  115. + arguments += "time_base=1/1:pixel_aspect=0/1[in];";
  116. + arguments += "[in]yadif[out];";
  117. + arguments += "[out]buffersink";
  118. +
  119. + int ret = avfilter_graph_parse2(m_filterGraph, arguments.constData(), &inputs, &outputs);
  120. + if (ret < 0) {
  121. + qWarning() << "Unable to parse filter graph";
  122. + return false;
  123. + }
  124. +
  125. + if(inputs || outputs)
  126. + return -1;
  127. +
  128. + ret = avfilter_graph_config(m_filterGraph, nullptr);
  129. + if (ret < 0) {
  130. + qWarning() << "Unable to validate filter graph";
  131. + return false;
  132. + }
  133. +
  134. + m_bufferSourceContext = avfilter_graph_get_filter(m_filterGraph, "Parsed_buffer_0");
  135. + m_bufferSinkContext = avfilter_graph_get_filter(m_filterGraph, "Parsed_buffersink_2");
  136. + if (!m_bufferSourceContext || !m_bufferSinkContext) {
  137. + qWarning() << "Unable to get source or sink";
  138. + return false;
  139. + }
  140. + m_filterFrame = av_frame_alloc();
  141. + m_lastWidth = width;
  142. + m_lastHeight = height;
  143. + m_lastPixfmt = pixfmt;
  144. +
  145. + return true;
  146. +}
  147. +
  148. +bool MovieDecoder::processFilterGraph(AVPicture *dst, const AVPicture *src,
  149. + enum AVPixelFormat pixfmt, int width, int height)
  150. +{
  151. + if (!m_filterGraph || width != m_lastWidth ||
  152. + height != m_lastHeight || pixfmt != m_lastPixfmt) {
  153. +
  154. + if (!initFilterGraph(pixfmt, width, height)) {
  155. + return false;
  156. + }
  157. + }
  158. +
  159. + memcpy(m_filterFrame->data, src->data, sizeof(src->data));
  160. + memcpy(m_filterFrame->linesize, src->linesize, sizeof(src->linesize));
  161. + m_filterFrame->width = width;
  162. + m_filterFrame->height = height;
  163. + m_filterFrame->format = pixfmt;
  164. +
  165. + int ret = av_buffersrc_add_frame(m_bufferSourceContext, m_filterFrame);
  166. + if (ret < 0) {
  167. + return false;
  168. + }
  169. +
  170. + ret = av_buffersink_get_frame(m_bufferSinkContext, m_filterFrame);
  171. + if (ret < 0) {
  172. + return false;
  173. + }
  174. +
  175. + av_picture_copy(dst, (const AVPicture *) m_filterFrame, pixfmt, width, height);
  176. + av_frame_unref(m_filterFrame);
  177. +
  178. + return true;
  179. +}
  180. +
  181. void MovieDecoder::getScaledVideoFrame(int scaledSize, bool maintainAspectRatio, VideoFrame& videoFrame)
  182. {
  183. if (m_pFrame->interlaced_frame) {
  184. - avpicture_deinterlace((AVPicture*) m_pFrame, (AVPicture*) m_pFrame, m_pVideoCodecContext->pix_fmt,
  185. + processFilterGraph((AVPicture*) m_pFrame, (AVPicture*) m_pFrame, m_pVideoCodecContext->pix_fmt,
  186. m_pVideoCodecContext->width, m_pVideoCodecContext->height);
  187. }
  188. int scaledWidth, scaledHeight;
  189. - convertAndScaleFrame(PIX_FMT_RGB24, scaledSize, maintainAspectRatio, scaledWidth, scaledHeight);
  190. + convertAndScaleFrame(AV_PIX_FMT_RGB24, scaledSize, maintainAspectRatio, scaledWidth, scaledHeight);
  191. videoFrame.width = scaledWidth;
  192. videoFrame.height = scaledHeight;
  193. @@ -302,7 +395,7 @@
  194. memcpy((&(videoFrame.frameData.front())), m_pFrame->data[0], videoFrame.lineSize * videoFrame.height);
  195. }
  196. -void MovieDecoder::convertAndScaleFrame(PixelFormat format, int scaledSize, bool maintainAspectRatio, int& scaledWidth, int& scaledHeight)
  197. +void MovieDecoder::convertAndScaleFrame(AVPixelFormat format, int scaledSize, bool maintainAspectRatio, int& scaledWidth, int& scaledHeight)
  198. {
  199. calculateDimensions(scaledSize, maintainAspectRatio, scaledWidth, scaledHeight);
  200. SwsContext* scaleContext = sws_getContext(m_pVideoCodecContext->width, m_pVideoCodecContext->height,
  201. @@ -323,7 +416,7 @@
  202. convertedFrame->data, convertedFrame->linesize);
  203. sws_freeContext(scaleContext);
  204. - av_free(m_pFrame);
  205. + av_frame_free(&m_pFrame);
  206. av_free(m_pFrameBuffer);
  207. m_pFrame = convertedFrame;
  208. @@ -355,9 +448,9 @@
  209. }
  210. }
  211. -void MovieDecoder::createAVFrame(AVFrame** avFrame, quint8** frameBuffer, int width, int height, PixelFormat format)
  212. -{
  213. - *avFrame = avcodec_alloc_frame();
  214. +void MovieDecoder::createAVFrame(AVFrame** avFrame, quint8** frameBuffer, int width, int height, AVPixelFormat format)
  215. +{
  216. + *avFrame = av_frame_alloc();
  217. int numBytes = avpicture_get_size(format, width, height);
  218. *frameBuffer = reinterpret_cast<quint8*>(av_malloc(numBytes));
  219. --- a/ffmpegthumbnailer/moviedecoder.h
  220. +++ b/ffmpegthumbnailer/moviedecoder.h
  221. @@ -23,6 +23,9 @@
  222. extern "C" {
  223. #include <libavcodec/avcodec.h>
  224. #include <libavformat/avformat.h>
  225. +#include <libavfilter/avfilter.h>
  226. +#include <libavfilter/buffersrc.h>
  227. +#include <libavfilter/buffersink.h>
  228. }
  229. namespace ffmpegthumbnailer
  230. @@ -52,9 +55,13 @@
  231. bool decodeVideoPacket();
  232. bool getVideoPacket();
  233. - void convertAndScaleFrame(PixelFormat format, int scaledSize, bool maintainAspectRatio, int& scaledWidth, int& scaledHeight);
  234. - void createAVFrame(AVFrame** avFrame, quint8** frameBuffer, int width, int height, PixelFormat format);
  235. + void convertAndScaleFrame(AVPixelFormat format, int scaledSize, bool maintainAspectRatio, int& scaledWidth, int& scaledHeight);
  236. + void createAVFrame(AVFrame** avFrame, quint8** frameBuffer, int width, int height, AVPixelFormat format);
  237. void calculateDimensions(int squareSize, bool maintainAspectRatio, int& destWidth, int& destHeight);
  238. +
  239. + void deleteFilterGraph();
  240. + bool initFilterGraph(enum AVPixelFormat pixfmt, int width, int height);
  241. + bool processFilterGraph(AVPicture *dst, const AVPicture *src, enum AVPixelFormat pixfmt, int width, int height);
  242. private:
  243. int m_VideoStream;
  244. @@ -68,6 +75,13 @@
  245. bool m_FormatContextWasGiven;
  246. bool m_AllowSeek;
  247. bool m_initialized;
  248. + AVFilterContext* m_bufferSinkContext;
  249. + AVFilterContext* m_bufferSourceContext;
  250. + AVFilterGraph* m_filterGraph;
  251. + AVFrame* m_filterFrame;
  252. + int m_lastWidth;
  253. + int m_lastHeight;
  254. + enum AVPixelFormat m_lastPixfmt;
  255. };
  256. }
  257. --- a/tests/CMakeLists.txt
  258. +++ b/tests/CMakeLists.txt
  259. @@ -19,7 +19,7 @@
  260. add_executable(ffmpegthumbtest ${ffmpegthumbtest_SRCS} )
  261. -target_link_libraries(ffmpegthumbtest Qt5::Gui KF5::KIOWidgets ${AVUTIL_LIBRARIES} ${AVFORMAT_LIBRARIES} ${AVCODEC_LIBRARIES} ${SWSCALE_LIBRARIES})
  262. +target_link_libraries(ffmpegthumbtest Qt5::Gui KF5::KIOWidgets ${AVUTIL_LIBRARIES} ${AVFILTER_LIBRARIES} ${AVFORMAT_LIBRARIES} ${AVCODEC_LIBRARIES} ${SWSCALE_LIBRARIES})