From 4f4d98911a40a7683106c644fec459c9dd115df2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Colin=20G=C3=BCnther?= Date: Sun, 3 Aug 2014 13:43:55 +0200 Subject: [PATCH] FFMPEG Plugin: Extract video aspect ratio calculation code. - Also make use of the extracted code in the AVCodecDecoder class. - Enhance some documentation and fix some coding style violations. - No functional change intended. --- .../media/plugins/ffmpeg/AVCodecDecoder.cpp | 16 +++- .../media/plugins/ffmpeg/AVFormatReader.cpp | 28 +------ src/add-ons/media/plugins/ffmpeg/Utilities.h | 74 +++++++++++++++++++ 3 files changed, 92 insertions(+), 26 deletions(-) create mode 100644 src/add-ons/media/plugins/ffmpeg/Utilities.h diff --git a/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp b/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp index e3055002b2..b427a49d40 100644 --- a/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp +++ b/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp @@ -21,6 +21,8 @@ #include #include +#include "Utilities.h" + #undef TRACE //#define TRACE_AV_CODEC @@ -879,8 +881,8 @@ AVCodecDecoder::_DecodeNextVideoFrame() } -/*! \brief Updates relevant fields of the class member fHeader with the properties of - the most recently decoded video frame. +/*! \brief Updates relevant fields of the class member fHeader with the + properties of the most recently decoded video frame. It is assumed that this function is called in _DecodeNextVideoFrame() only when the following asserts hold true: @@ -893,6 +895,9 @@ AVCodecDecoder::_DecodeNextVideoFrame() 4. There will be at maximumn only one decoded video frame in our cache at any single point in time. Otherwise you couldn't tell to which cached decoded video frame the properties in fHeader relate to. + 5. AVCodecContext is still valid for this video frame (This is the case + when this function is called immediately after + avcodec_decode_video2(). */ void AVCodecDecoder::_UpdateMediaHeaderForVideoFrame() @@ -901,6 +906,9 @@ AVCodecDecoder::_UpdateMediaHeaderForVideoFrame() fHeader.file_pos = 0; fHeader.orig_size = 0; fHeader.start_time = fRawDecodedPicture->reordered_opaque; + fHeader.u.raw_video.display_line_width = fRawDecodedPicture->width; + fHeader.u.raw_video.display_line_count = fRawDecodedPicture->height; + fHeader.u.raw_video.bytes_per_row = 0; // TODO: Implement calculation fHeader.u.raw_video.field_gamma = 1.0; fHeader.u.raw_video.field_sequence = fFrame; fHeader.u.raw_video.field_number = 0; @@ -908,6 +916,10 @@ AVCodecDecoder::_UpdateMediaHeaderForVideoFrame() fHeader.u.raw_video.first_active_line = 1; fHeader.u.raw_video.line_count = fRawDecodedPicture->height; + ConvertAVCodecContextToVideoAspectWidthAndHeight(*fContext, + fHeader.u.raw_video.pixel_width_aspect, + fHeader.u.raw_video.pixel_height_aspect); + TRACE("[v] start_time=%02d:%02d.%02d field_sequence=%lu\n", int((fHeader.start_time / 60000000) % 60), int((fHeader.start_time / 1000000) % 60), diff --git a/src/add-ons/media/plugins/ffmpeg/AVFormatReader.cpp b/src/add-ons/media/plugins/ffmpeg/AVFormatReader.cpp index aeed534f12..3cb21311f5 100644 --- a/src/add-ons/media/plugins/ffmpeg/AVFormatReader.cpp +++ b/src/add-ons/media/plugins/ffmpeg/AVFormatReader.cpp @@ -25,6 +25,7 @@ extern "C" { #include "DemuxerTable.h" #include "gfx_util.h" +#include "Utilities.h" //#define TRACE_AVFORMAT_READER @@ -1151,30 +1152,9 @@ AVFormatReader::Stream::Init(int32 virtualIndex) format->u.encoded_video.output.orientation = B_VIDEO_TOP_LEFT_RIGHT; - // Calculate the display aspect ratio - AVRational displayAspectRatio; - if (codecContext->sample_aspect_ratio.num != 0) { - av_reduce(&displayAspectRatio.num, &displayAspectRatio.den, - codecContext->width - * codecContext->sample_aspect_ratio.num, - codecContext->height - * codecContext->sample_aspect_ratio.den, - 1024 * 1024); - TRACE(" pixel aspect ratio: %d/%d, " - "display aspect ratio: %d/%d\n", - codecContext->sample_aspect_ratio.num, - codecContext->sample_aspect_ratio.den, - displayAspectRatio.num, displayAspectRatio.den); - } else { - av_reduce(&displayAspectRatio.num, &displayAspectRatio.den, - codecContext->width, codecContext->height, 1024 * 1024); - TRACE(" no display aspect ratio (%d/%d)\n", - displayAspectRatio.num, displayAspectRatio.den); - } - format->u.encoded_video.output.pixel_width_aspect - = displayAspectRatio.num; - format->u.encoded_video.output.pixel_height_aspect - = displayAspectRatio.den; + ConvertAVCodecContextToVideoAspectWidthAndHeight(*codecContext, + format->u.encoded_video.output.pixel_width_aspect, + format->u.encoded_video.output.pixel_height_aspect); format->u.encoded_video.output.display.format = pixfmt_to_colorspace(codecContext->pix_fmt); diff --git a/src/add-ons/media/plugins/ffmpeg/Utilities.h b/src/add-ons/media/plugins/ffmpeg/Utilities.h new file mode 100644 index 0000000000..c82e85d10c --- /dev/null +++ b/src/add-ons/media/plugins/ffmpeg/Utilities.h @@ -0,0 +1,74 @@ +/* + * Copyright 2009, Stephan Aßmus + * Copyright 2014, Colin Günther + * All rights reserved. Distributed under the terms of the GNU L-GPL license. + */ +#ifndef UTILITIES_H +#define UTILITIES_H + + +/*! \brief This file contains functions to convert values from FFmpeg to Media + Kit and vice versa. +*/ + + +#include + +extern "C" { + #include "avcodec.h" +} + + +/*! \brief Converts FFmpeg notation of video aspect ratio into the Media Kits + notation. + + \param pixelWidthAspectOut On return contains the Media Kits notation of + the video aspect ratio width. E.g. 16:9 -> 16 is returned here + \param pixelHeightAspectOut On return contains the Media Kits notation of + the video aspect ratio height. E.g. 16:9 -> 9 is returned here + \param contextIn An AVCodeContext structure of FFmpeg containing the values + needed to calculate the Media Kit video aspect ratio. + The following fields are used for the calculation: + - AVCodecContext.sample_aspect_ratio.num (optional) + - AVCodecContext.sample_aspect_ratio.den (optional) + - AVCodecContext.width (must) + - AVCodecContext.height (must) +*/ +inline void +ConvertAVCodecContextToVideoAspectWidthAndHeight(AVCodecContext& contextIn, + uint16& pixelWidthAspectOut, uint16& pixelHeightAspectOut) +{ + assert(contextIn.sample_aspect_ratio.num >= 0); + assert(contextIn.sample_aspect_ratio.den > 0); + assert(contextIn.width > 0); + assert(contextIn.height > 0); + + // The following code is based on code originally located in + // AVFormatReader::Stream::Init() and thus should be copyrighted to Stephan + // Aßmus + AVRational pixelAspectRatio; + + if (contextIn.sample_aspect_ratio.num == 0) { + // AVCodecContext doesn't contain a video aspect ratio, so calculate it + // ourselve based solely on the video dimensions + av_reduce(&pixelAspectRatio.num, &pixelAspectRatio.den, contextIn.width, + contextIn.height, 1024 * 1024); + + pixelWidthAspectOut = static_cast(pixelAspectRatio.num); + pixelHeightAspectOut = static_cast(pixelAspectRatio.den); + return; + } + + // AVCodecContext contains a video aspect ratio, so use it + av_reduce(&pixelAspectRatio.num, &pixelAspectRatio.den, + contextIn.width * contextIn.sample_aspect_ratio.num, + contextIn.height * contextIn.sample_aspect_ratio.den, + 1024 * 1024); + + pixelWidthAspectOut = static_cast(pixelAspectRatio.num); + pixelHeightAspectOut = static_cast(pixelAspectRatio.den); +} + + + +#endif // UTILITIES_H