ffmpeg: implement deinterlace feature for ffmpeg 3.x.
* Use the yadif filter. * Fixes #12731.
This commit is contained in:
parent
037ea84ba5
commit
0b6c89fb16
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include <Bitmap.h>
|
#include <Bitmap.h>
|
||||||
#include <Debug.h>
|
#include <Debug.h>
|
||||||
|
#include <String.h>
|
||||||
|
|
||||||
#include "Utilities.h"
|
#include "Utilities.h"
|
||||||
|
|
||||||
@ -126,6 +127,13 @@ AVCodecDecoder::AVCodecDecoder()
|
|||||||
fDecodedDataBuffer(av_frame_alloc()),
|
fDecodedDataBuffer(av_frame_alloc()),
|
||||||
fDecodedDataBufferOffset(0),
|
fDecodedDataBufferOffset(0),
|
||||||
fDecodedDataBufferSize(0)
|
fDecodedDataBufferSize(0)
|
||||||
|
#if LIBAVCODEC_VERSION_INT >= ((57 << 16) | (0 << 8))
|
||||||
|
,
|
||||||
|
fBufferSinkContext(NULL),
|
||||||
|
fBufferSourceContext(NULL),
|
||||||
|
fFilterGraph(NULL),
|
||||||
|
fFilterFrame(NULL)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
TRACE("AVCodecDecoder::AVCodecDecoder()\n");
|
TRACE("AVCodecDecoder::AVCodecDecoder()\n");
|
||||||
|
|
||||||
@ -164,6 +172,11 @@ AVCodecDecoder::~AVCodecDecoder()
|
|||||||
av_free(fContext);
|
av_free(fContext);
|
||||||
av_free(fDecodedDataBuffer);
|
av_free(fDecodedDataBuffer);
|
||||||
|
|
||||||
|
#if LIBAVCODEC_VERSION_INT >= ((57 << 16) | (0 << 8))
|
||||||
|
av_frame_free(&fFilterFrame);
|
||||||
|
avfilter_graph_free(&fFilterGraph);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if USE_SWS_FOR_COLOR_SPACE_CONVERSION
|
#if USE_SWS_FOR_COLOR_SPACE_CONVERSION
|
||||||
if (fSwsContext != NULL)
|
if (fSwsContext != NULL)
|
||||||
sws_freeContext(fSwsContext);
|
sws_freeContext(fSwsContext);
|
||||||
@ -1641,9 +1654,10 @@ AVCodecDecoder::_DeinterlaceAndColorConvertVideoFrame()
|
|||||||
} else
|
} else
|
||||||
useDeinterlacedPicture = true;
|
useDeinterlacedPicture = true;
|
||||||
#else
|
#else
|
||||||
// avpicture_deinterlace is gone
|
// deinterlace implemented using avfilter
|
||||||
// TODO: implement alternate deinterlace using avfilter
|
_ProcessFilterGraph(&deinterlacedPicture, &rawPicture,
|
||||||
TRACE("[v] avpicture_deinterlace() - not implemented\n");
|
fContext->pix_fmt, displayWidth, displayHeight);
|
||||||
|
useDeinterlacedPicture = true;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1723,3 +1737,101 @@ AVCodecDecoder::_DeinterlaceAndColorConvertVideoFrame()
|
|||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if LIBAVCODEC_VERSION_INT >= ((57 << 16) | (0 << 8))
|
||||||
|
|
||||||
|
/*! \brief Init the deinterlace filter graph.
|
||||||
|
|
||||||
|
\returns B_OK the filter graph could be built.
|
||||||
|
\returns B_BAD_VALUE something was wrong with building the graph.
|
||||||
|
*/
|
||||||
|
status_t
|
||||||
|
AVCodecDecoder::_InitFilterGraph(enum AVPixelFormat pixfmt, int32 width,
|
||||||
|
int32 height)
|
||||||
|
{
|
||||||
|
if (fFilterGraph != NULL) {
|
||||||
|
av_frame_free(&fFilterFrame);
|
||||||
|
avfilter_graph_free(&fFilterGraph);
|
||||||
|
}
|
||||||
|
|
||||||
|
fFilterGraph = avfilter_graph_alloc();
|
||||||
|
|
||||||
|
BString arguments;
|
||||||
|
arguments.SetToFormat("buffer=video_size=%dx%d:pix_fmt=%d:time_base=1/1:"
|
||||||
|
"pixel_aspect=0/1[in];[in]yadif[out];[out]buffersink", width, height,
|
||||||
|
pixfmt);
|
||||||
|
AVFilterInOut* inputs = NULL;
|
||||||
|
AVFilterInOut* outputs = NULL;
|
||||||
|
TRACE("[v] _InitFilterGraph(): %s\n", arguments.String());
|
||||||
|
int ret = avfilter_graph_parse2(fFilterGraph, arguments.String(), &inputs,
|
||||||
|
&outputs);
|
||||||
|
if (ret < 0) {
|
||||||
|
fprintf(stderr, "avfilter_graph_parse2() failed\n");
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = avfilter_graph_config(fFilterGraph, NULL);
|
||||||
|
if (ret < 0) {
|
||||||
|
fprintf(stderr, "avfilter_graph_config() failed\n");
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
fBufferSourceContext = avfilter_graph_get_filter(fFilterGraph,
|
||||||
|
"Parsed_buffer_0");
|
||||||
|
fBufferSinkContext = avfilter_graph_get_filter(fFilterGraph,
|
||||||
|
"Parsed_buffersink_2");
|
||||||
|
if (fBufferSourceContext == NULL || fBufferSinkContext == NULL) {
|
||||||
|
fprintf(stderr, "avfilter_graph_get_filter() failed\n");
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
fFilterFrame = av_frame_alloc();
|
||||||
|
fLastWidth = width;
|
||||||
|
fLastHeight = height;
|
||||||
|
fLastPixfmt = pixfmt;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! \brief Process an AVPicture with the deinterlace filter graph.
|
||||||
|
|
||||||
|
We decode exactly one video frame into dst.
|
||||||
|
Equivalent function for avpicture_deinterlace() from version 2.x.
|
||||||
|
|
||||||
|
\returns B_OK video frame successfully deinterlaced.
|
||||||
|
\returns B_BAD_DATA No frame could be output.
|
||||||
|
\returns B_NO_MEMORY Not enough memory available for correct operation.
|
||||||
|
*/
|
||||||
|
status_t
|
||||||
|
AVCodecDecoder::_ProcessFilterGraph(AVPicture *dst, const AVPicture *src,
|
||||||
|
enum AVPixelFormat pixfmt, int32 width, int32 height)
|
||||||
|
{
|
||||||
|
if (fFilterGraph == NULL || width != fLastWidth
|
||||||
|
|| height != fLastHeight || pixfmt != fLastPixfmt) {
|
||||||
|
|
||||||
|
status_t err = _InitFilterGraph(pixfmt, width, height);
|
||||||
|
if (err != B_OK)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(fFilterFrame->data, src->data, sizeof(src->data));
|
||||||
|
memcpy(fFilterFrame->linesize, src->linesize, sizeof(src->linesize));
|
||||||
|
fFilterFrame->width = width;
|
||||||
|
fFilterFrame->height = height;
|
||||||
|
fFilterFrame->format = pixfmt;
|
||||||
|
|
||||||
|
int ret = av_buffersrc_add_frame(fBufferSourceContext, fFilterFrame);
|
||||||
|
if (ret < 0)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
ret = av_buffersink_get_frame(fBufferSinkContext, fFilterFrame);
|
||||||
|
if (ret < 0)
|
||||||
|
return B_BAD_DATA;
|
||||||
|
|
||||||
|
av_picture_copy(dst, (const AVPicture *)fFilterFrame, pixfmt, width,
|
||||||
|
height);
|
||||||
|
av_frame_unref(fFilterFrame);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
@ -19,6 +19,11 @@
|
|||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "avcodec.h"
|
#include "avcodec.h"
|
||||||
|
#if LIBAVCODEC_VERSION_INT >= ((57 << 16) | (0 << 8))
|
||||||
|
#include "avfilter.h"
|
||||||
|
#include "buffersink.h"
|
||||||
|
#include "buffersrc.h"
|
||||||
|
#endif
|
||||||
#include "swresample.h"
|
#include "swresample.h"
|
||||||
#include "swscale.h"
|
#include "swscale.h"
|
||||||
}
|
}
|
||||||
@ -95,6 +100,14 @@ private:
|
|||||||
void _UpdateMediaHeaderForVideoFrame();
|
void _UpdateMediaHeaderForVideoFrame();
|
||||||
status_t _DeinterlaceAndColorConvertVideoFrame();
|
status_t _DeinterlaceAndColorConvertVideoFrame();
|
||||||
|
|
||||||
|
#if LIBAVCODEC_VERSION_INT >= ((57 << 16) | (0 << 8))
|
||||||
|
// video deinterlace filter graph
|
||||||
|
status_t _InitFilterGraph(enum AVPixelFormat pixfmt,
|
||||||
|
int32 width, int32 height);
|
||||||
|
status_t _ProcessFilterGraph(AVPicture *dst,
|
||||||
|
const AVPicture *src, enum AVPixelFormat pixfmt,
|
||||||
|
int32 width, int32 height);
|
||||||
|
#endif
|
||||||
|
|
||||||
media_header fHeader;
|
media_header fHeader;
|
||||||
// Contains the properties of the current
|
// Contains the properties of the current
|
||||||
@ -144,6 +157,17 @@ private:
|
|||||||
int32 fDecodedDataBufferSize;
|
int32 fDecodedDataBufferSize;
|
||||||
|
|
||||||
AVPacket fTempPacket;
|
AVPacket fTempPacket;
|
||||||
|
|
||||||
|
#if LIBAVCODEC_VERSION_INT >= ((57 << 16) | (0 << 8))
|
||||||
|
// video deinterlace feature
|
||||||
|
AVFilterContext* fBufferSinkContext;
|
||||||
|
AVFilterContext* fBufferSourceContext;
|
||||||
|
AVFilterGraph* fFilterGraph;
|
||||||
|
AVFrame* fFilterFrame;
|
||||||
|
int32 fLastWidth;
|
||||||
|
int32 fLastHeight;
|
||||||
|
enum AVPixelFormat fLastPixfmt;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // AVCODEC_DECODER_H
|
#endif // AVCODEC_DECODER_H
|
||||||
|
@ -87,6 +87,9 @@ FFmpegPlugin::GlobalInitilizer::GlobalInitilizer()
|
|||||||
|
|
||||||
av_register_all();
|
av_register_all();
|
||||||
// This will also call av_codec_init() by registering codecs.
|
// This will also call av_codec_init() by registering codecs.
|
||||||
|
#if LIBAVCODEC_VERSION_INT >= ((57 << 16) | (0 << 8))
|
||||||
|
avfilter_register_all();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user