[haiku-commits] haiku: hrev47618 - in src: add-ons/media/plugins/ffmpeg tests/kits/media/mpeg2_decoder_test

  • From: coling@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Mon, 4 Aug 2014 12:27:20 +0200 (CEST)

hrev47618 adds 5 changesets to branch 'master'
old head: 05f06a9065d9caae87bdc5ad2a99446d4ed83499
new head: 6a18ef8358523873c8536722e009a4ab85b1049b
overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=6a18ef8+%5E05f06a9

----------------------------------------------------------------------------

4f4d989: 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.

60909c1: FFMPEG Plugin: Implement and use calculation of bytes per row.

160f00b: FFMPEG Plugin: Implement video frame rate calculation for decoder.
  
  - The frame rate calculation is purely based on AVCodecContext fields. This 
way
    the frame rate can be calculated by the FFMPEG decoder based on the actual
    video data. This is useful for automatically detection of the correct
    decoding parameters (not implemented yet but scheduled for a later commit).
  - Not used anywhere yet (scheduled for a later commit).
  - Also some minor documentation updates.

62320bd: FFMPEG Plugin: Automatic detection of video decoding parameters.
  
  - Kudos to Marcus Overhagen for laying out the general idea of automatic
    detection by sharing some of his dvb code examples with me.
  - Simplify pixel format search code by removing the loop and let FFMPEG
    decide what pixel format to use based on the actual video data.
  - Automatically detect the video frame rate based on the actual video data.
  - Remove fOutputVideoFormat to avoid synchronizing values in two distinct
    places. The member variable fHeader is the main place for important decoder
    parameters now.
  - Introduce fOutputColorSpace containing the color space that was previously
    tracked in the fOutputVideoFormat member variable.
  - Update the documentation accordingly.

6a18ef8: MediaKit: Remove superflous code in mpeg2_decoder_test.
  
  - Thanks to automatic video decoding parameter detection, we no longer need to
    manually hack the correct parameters for this test to succeed, jiha!

                                           [ Colin Günther <coling@xxxxxx> ]

----------------------------------------------------------------------------

5 files changed, 229 insertions(+), 120 deletions(-)
.../media/plugins/ffmpeg/AVCodecDecoder.cpp      | 172 ++++++++++---------
.../media/plugins/ffmpeg/AVCodecDecoder.h        |   2 +-
.../media/plugins/ffmpeg/AVFormatReader.cpp      |  28 +--
src/add-ons/media/plugins/ffmpeg/Utilities.h     | 137 +++++++++++++++
.../mpeg2_decoder_test/mpeg2_decoder_test.cpp    |  10 --

############################################################################

Commit:      4f4d98911a40a7683106c644fec459c9dd115df2
URL:         http://cgit.haiku-os.org/haiku/commit/?id=4f4d989
Author:      Colin Günther <coling@xxxxxx>
Date:        Sun Aug  3 11:43:55 2014 UTC

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.

----------------------------------------------------------------------------

diff --git a/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp 
b/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp
index e305500..b427a49 100644
--- a/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp
+++ b/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp
@@ -21,6 +21,8 @@
 #include <Bitmap.h>
 #include <Debug.h>
 
+#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 aeed534..3cb2131 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 0000000..c82e85d
--- /dev/null
+++ b/src/add-ons/media/plugins/ffmpeg/Utilities.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2009, Stephan Aßmus <superstippi@xxxxxx>
+ * Copyright 2014, Colin Günther <coling@xxxxxx>
+ * 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 <assert.h>
+
+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<int16>(pixelAspectRatio.num);
+               pixelHeightAspectOut = static_cast<int16>(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<int16>(pixelAspectRatio.num);
+       pixelHeightAspectOut = static_cast<int16>(pixelAspectRatio.den);
+}
+
+
+
+#endif // UTILITIES_H

############################################################################

Commit:      60909c1e194c097674aa80ce0da5e50cb4fab427
URL:         http://cgit.haiku-os.org/haiku/commit/?id=60909c1
Author:      Colin Günther <coling@xxxxxx>
Date:        Sun Aug  3 12:50:37 2014 UTC

FFMPEG Plugin: Implement and use calculation of bytes per row.

----------------------------------------------------------------------------

diff --git a/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp 
b/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp
index b427a49..845fe67 100644
--- a/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp
+++ b/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp
@@ -908,7 +908,9 @@ AVCodecDecoder::_UpdateMediaHeaderForVideoFrame()
        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.bytes_per_row
+               = CalculateBytesPerRowWithColorSpaceAndVideoWidth(
+                       fOutputVideoFormat.display.format, 
fRawDecodedPicture->width);
        fHeader.u.raw_video.field_gamma = 1.0;
        fHeader.u.raw_video.field_sequence = fFrame;
        fHeader.u.raw_video.field_number = 0;
diff --git a/src/add-ons/media/plugins/ffmpeg/Utilities.h 
b/src/add-ons/media/plugins/ffmpeg/Utilities.h
index c82e85d..e02f076 100644
--- a/src/add-ons/media/plugins/ffmpeg/Utilities.h
+++ b/src/add-ons/media/plugins/ffmpeg/Utilities.h
@@ -7,13 +7,15 @@
 #define UTILITIES_H
 
 
-/*! \brief This file contains functions to convert values from FFmpeg to Media
-               Kit and vice versa.
+/*! \brief This file contains functions to convert and calculate values from
+               FFmpeg to Media Kit and vice versa.
 */
 
 
 #include <assert.h>
 
+#include <GraphicsDefs.h>
+
 extern "C" {
        #include "avcodec.h"
 }
@@ -70,5 +72,37 @@ 
ConvertAVCodecContextToVideoAspectWidthAndHeight(AVCodecContext& contextIn,
 }
 
 
+/*! \brief Calculates bytes per row for a video frame.
+
+       \param colorSpace The Media Kit color space the video frame uses.
+       \param videoWidth The width of the video frame.
+
+       \returns bytes per video frame row
+       \returns Zero, when bytes per video frame cannot be calculated.
+*/
+inline uint32
+CalculateBytesPerRowWithColorSpaceAndVideoWidth(color_space colorSpace, int 
videoWidth)
+{
+       assert(videoWidth >= 0);
+
+       const uint32 kBytesPerRowUnknown = 0;
+       size_t bytesPerPixel;
+       size_t rowAlignment;
+
+       if (get_pixel_size_for(colorSpace, &bytesPerPixel, &rowAlignment, NULL) 
!= B_OK)
+               return kBytesPerRowUnknown;
+
+       uint32 bytesPerRow = bytesPerPixel * videoWidth;
+       uint32 numberOfUnalignedBytes = bytesPerRow % rowAlignment;
+
+       if (numberOfUnalignedBytes == 0)
+               return bytesPerRow;
+
+       uint32 numberOfBytesNeededForAlignment = rowAlignment - 
numberOfUnalignedBytes;
+       bytesPerRow += numberOfBytesNeededForAlignment;
+
+       return bytesPerRow;
+}
+
 
 #endif // UTILITIES_H

############################################################################

Commit:      160f00bca87e954515145a25889e7ba89bfb97a2
URL:         http://cgit.haiku-os.org/haiku/commit/?id=160f00b
Author:      Colin Günther <coling@xxxxxx>
Date:        Sun Aug  3 22:28:52 2014 UTC

FFMPEG Plugin: Implement video frame rate calculation for decoder.

- The frame rate calculation is purely based on AVCodecContext fields. This way
  the frame rate can be calculated by the FFMPEG decoder based on the actual
  video data. This is useful for automatically detection of the correct
  decoding parameters (not implemented yet but scheduled for a later commit).
- Not used anywhere yet (scheduled for a later commit).
- Also some minor documentation updates.

----------------------------------------------------------------------------

diff --git a/src/add-ons/media/plugins/ffmpeg/Utilities.h 
b/src/add-ons/media/plugins/ffmpeg/Utilities.h
index e02f076..f51f6b2 100644
--- a/src/add-ons/media/plugins/ffmpeg/Utilities.h
+++ b/src/add-ons/media/plugins/ffmpeg/Utilities.h
@@ -24,10 +24,6 @@ extern "C" {
 /*! \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:
@@ -35,6 +31,10 @@ extern "C" {
                        - AVCodecContext.sample_aspect_ratio.den (optional)
                        - AVCodecContext.width (must)
                        - AVCodecContext.height (must)
+       \param pixelWidthAspectOut On return contains Media Kits notation of the
+               video aspect ratio width. E.g. 16:9 -> 16 is returned here
+       \param pixelHeightAspectOut On return contains Media Kits notation of 
the
+               video aspect ratio height. E.g. 16:9 -> 9 is returned here
 */
 inline void
 ConvertAVCodecContextToVideoAspectWidthAndHeight(AVCodecContext& contextIn,
@@ -105,4 +105,33 @@ 
CalculateBytesPerRowWithColorSpaceAndVideoWidth(color_space colorSpace, int vide
 }
 
 
+/*! \brief Converts FFmpeg notation of video frame rate into the Media Kits
+               notation.
+
+       \param contextIn An AVCodeContext structure of FFmpeg containing the 
values
+               needed to calculate the Media Kit video frame rate.
+               The following fields are used for the calculation:
+                       - AVCodecContext.time_base.num (must)
+                       - AVCodecContext.time_base.den (must)
+                       - AVCodecContext.ticks_per_frame (must)
+       \param frameRateOut On return contains Media Kits notation of the video
+               frame rate.
+*/
+inline void
+ConvertAVCodecContextToVideoFrameRate(AVCodecContext& contextIn, float& 
frameRateOut)
+{
+       // assert that av_q2d(contextIn.time_base) > 0 and computable
+       assert(contextIn.time_base.num > 0);
+       assert(contextIn.time_base.den > 0);
+
+       // The following code is based on private get_fps() function of FFmpeg's
+       // ratecontrol.c:
+       // 
https://lists.ffmpeg.org/pipermail/ffmpeg-cvslog/2012-April/049280.html
+       double possiblyInterlacedFrameRate = 1.0 / av_q2d(contextIn.time_base);
+       double numberOfInterlacedFramesPerFullFrame = 
FFMAX(contextIn.ticks_per_frame, 1);
+
+       frameRateOut
+               = possiblyInterlacedFrameRate / 
numberOfInterlacedFramesPerFullFrame;
+}
+
 #endif // UTILITIES_H

############################################################################

Commit:      62320bdea233d6f3d321ea20b922dde8a0c711d9
URL:         http://cgit.haiku-os.org/haiku/commit/?id=62320bd
Author:      Colin Günther <coling@xxxxxx>
Date:        Sun Aug  3 22:33:33 2014 UTC

FFMPEG Plugin: Automatic detection of video decoding parameters.

- Kudos to Marcus Overhagen for laying out the general idea of automatic
  detection by sharing some of his dvb code examples with me.
- Simplify pixel format search code by removing the loop and let FFMPEG
  decide what pixel format to use based on the actual video data.
- Automatically detect the video frame rate based on the actual video data.
- Remove fOutputVideoFormat to avoid synchronizing values in two distinct
  places. The member variable fHeader is the main place for important decoder
  parameters now.
- Introduce fOutputColorSpace containing the color space that was previously
  tracked in the fOutputVideoFormat member variable.
- Update the documentation accordingly.

----------------------------------------------------------------------------

diff --git a/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp 
b/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp
index 845fe67..437c79f 100644
--- a/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp
+++ b/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp
@@ -78,7 +78,6 @@ AVCodecDecoder::AVCodecDecoder()
        :
        fHeader(),
        fInputFormat(),
-       fOutputVideoFormat(),
        fFrame(0),
        fIsAudio(false),
        fCodec(NULL),
@@ -101,6 +100,7 @@ AVCodecDecoder::AVCodecDecoder()
        fBlockAlign(0),
 
        fStartTime(0),
+       fOutputColorSpace(B_NO_COLOR_SPACE),
        fOutputFrameCount(0),
        fOutputFrameRate(1.0),
        fOutputFrameSize(0),
@@ -432,26 +432,6 @@ AVCodecDecoder::_NegotiateVideoOutputFormat(media_format* 
inOutFormat)
 {
        TRACE("AVCodecDecoder::_NegotiateVideoOutputFormat()\n");
 
-       fOutputVideoFormat = fInputFormat.u.encoded_video.output;
-
-       fContext->width = fOutputVideoFormat.display.line_width;
-       fContext->height = fOutputVideoFormat.display.line_count;
-//     fContext->frame_rate = (int)(fOutputVideoFormat.field_rate
-//             * fContext->frame_rate_base);
-
-       fOutputFrameRate = fOutputVideoFormat.field_rate;
-
-       fContext->extradata = (uint8_t*)fExtraData;
-       fContext->extradata_size = fExtraDataSize;
-
-       bool codecCanHandleIncompleteFrames
-               = (fCodec->capabilities & CODEC_CAP_TRUNCATED) != 0;
-       if (codecCanHandleIncompleteFrames) {
-               // Expect and handle video frames to be splitted across 
consecutive
-               // data chunks.
-               fContext->flags |= CODEC_FLAG_TRUNCATED;
-       }
-
        TRACE("  requested video format 0x%x\n",
                inOutFormat->u.raw_video.display.format);
 
@@ -459,15 +439,10 @@ AVCodecDecoder::_NegotiateVideoOutputFormat(media_format* 
inOutFormat)
        // it will only ask for YCbCr, which DrawBitmap doesn't handle, so the
        // default colordepth is RGB32).
        if (inOutFormat->u.raw_video.display.format == B_YCbCr422)
-               fOutputVideoFormat.display.format = B_YCbCr422;
+               fOutputColorSpace = B_YCbCr422;
        else
-               fOutputVideoFormat.display.format = B_RGB32;
+               fOutputColorSpace = B_RGB32;
 
-       // Search for a pixel-format the codec handles
-       // TODO: We should try this a couple of times until it succeeds, each
-       // time using another pixel-format that is supported by the decoder.
-       // But libavcodec doesn't seem to offer any way to tell the decoder
-       // which format it should use.
 #if USE_SWS_FOR_COLOR_SPACE_CONVERSION
        if (fSwsContext != NULL)
                sws_freeContext(fSwsContext);
@@ -475,38 +450,41 @@ AVCodecDecoder::_NegotiateVideoOutputFormat(media_format* 
inOutFormat)
 #else
        fFormatConversionFunc = 0;
 #endif
-       // Iterate over supported codec formats
-       for (int i = 0; i < 1; i++) {
-               // close any previous instance
-               if (fCodecInitDone) {
-                       fCodecInitDone = false;
-                       avcodec_close(fContext);
-               }
-               // TODO: Set n-th fContext->pix_fmt here
-               if (avcodec_open2(fContext, fCodec, NULL) >= 0) {
-                       fCodecInitDone = true;
 
-#if USE_SWS_FOR_COLOR_SPACE_CONVERSION
-                       fSwsContext = sws_getContext(fContext->width, 
fContext->height,
-                               fContext->pix_fmt, fContext->width, 
fContext->height,
-                               
colorspace_to_pixfmt(fOutputVideoFormat.display.format),
-                               SWS_FAST_BILINEAR, NULL, NULL, NULL);
-               }
-#else
-                       fFormatConversionFunc = resolve_colorspace(
-                               fOutputVideoFormat.display.format, 
fContext->pix_fmt,
-                               fContext->width, fContext->height);
-               }
-               if (fFormatConversionFunc != NULL)
-                       break;
-#endif
+       fContext->extradata = (uint8_t*)fExtraData;
+       fContext->extradata_size = fExtraDataSize;
+
+       bool codecCanHandleIncompleteFrames
+               = (fCodec->capabilities & CODEC_CAP_TRUNCATED) != 0;
+       if (codecCanHandleIncompleteFrames) {
+               // Expect and handle video frames to be splitted across 
consecutive
+               // data chunks.
+               fContext->flags |= CODEC_FLAG_TRUNCATED;
        }
 
-       if (!fCodecInitDone) {
+       // close any previous instance
+       if (fCodecInitDone) {
+               fCodecInitDone = false;
+               avcodec_close(fContext);
+       }
+
+       if (avcodec_open2(fContext, fCodec, NULL) >= 0)
+               fCodecInitDone = true;
+       else {
                TRACE("avcodec_open() failed to init codec!\n");
                return B_ERROR;
        }
 
+       _ResetTempPacket();
+
+       status_t statusOfDecodingFirstFrame = _DecodeNextVideoFrame();
+       if (statusOfDecodingFirstFrame != B_OK) {
+               TRACE("[v] decoding first video frame failed\n");
+               return B_ERROR;
+       }
+
+       // Note: fSwsContext / fFormatConversionFunc should have been 
initialized
+       // by first call to _DecodeNextVideoFrame() above.
 #if USE_SWS_FOR_COLOR_SPACE_CONVERSION
        if (fSwsContext == NULL) {
                TRACE("No SWS Scale context or decoder has not set the pixel 
format "
@@ -519,21 +497,25 @@ AVCodecDecoder::_NegotiateVideoOutputFormat(media_format* 
inOutFormat)
        }
 #endif
 
-       if (fOutputVideoFormat.display.format == B_YCbCr422) {
-               fOutputVideoFormat.display.bytes_per_row
-                       = 2 * fOutputVideoFormat.display.line_width;
-       } else {
-               fOutputVideoFormat.display.bytes_per_row
-                       = 4 * fOutputVideoFormat.display.line_width;
-       }
-
        inOutFormat->type = B_MEDIA_RAW_VIDEO;
-       inOutFormat->u.raw_video = fOutputVideoFormat;
-
        inOutFormat->require_flags = 0;
        inOutFormat->deny_flags = B_MEDIA_MAUI_UNDEFINED_FLAGS;
 
-       _ResetTempPacket();
+       inOutFormat->u.raw_video = fInputFormat.u.encoded_video.output;
+
+       inOutFormat->u.raw_video.interlace = 1;
+               // Progressive (non-interlaced) video frames are delivered
+       inOutFormat->u.raw_video.first_active = 
fHeader.u.raw_video.first_active_line;
+       inOutFormat->u.raw_video.last_active = fHeader.u.raw_video.line_count;
+       inOutFormat->u.raw_video.pixel_width_aspect = 
fHeader.u.raw_video.pixel_width_aspect;
+       inOutFormat->u.raw_video.pixel_height_aspect = 
fHeader.u.raw_video.pixel_height_aspect;
+       inOutFormat->u.raw_video.field_rate = fOutputFrameRate;
+               // Was calculated by first call to _DecodeNextVideoFrame()
+
+       inOutFormat->u.raw_video.display.format = fOutputColorSpace;
+       inOutFormat->u.raw_video.display.line_width = 
fHeader.u.raw_video.display_line_width;
+       inOutFormat->u.raw_video.display.line_count = 
fHeader.u.raw_video.display_line_count;
+       inOutFormat->u.raw_video.display.bytes_per_row = 
fHeader.u.raw_video.bytes_per_row;
 
 #ifdef TRACE_AV_CODEC
        char buffer[1024];
@@ -713,7 +695,7 @@ AVCodecDecoder::_DecodeVideo(void* outBuffer, int64* 
outFrameCount,
 
     To every decoded video frame there is a media_header populated in
     fHeader, containing the corresponding video frame properties.
-
+    
        Normally every decoded video frame has a start_time field populated in 
the
        associated fHeader, that determines the presentation time of the frame.
        This relationship will only hold true, when each data chunk that is
@@ -733,6 +715,12 @@ AVCodecDecoder::_DecodeVideo(void* outBuffer, int64* 
outFrameCount,
        and the start time it should be presented isn't established at the 
moment.
        Though this     might change in the future.
 
+    More over the fOutputFrameRate variable is updated for every decoded video
+    frame.
+
+       On first call, the member variables     fSwsContext / 
fFormatConversionFunc
+       are initialized.
+
        \return B_OK, when we successfully decoded one video frame
  */
 status_t
@@ -842,6 +830,8 @@ AVCodecDecoder::_DecodeNextVideoFrame()
                        _UpdateMediaHeaderForVideoFrame();
                        _DeinterlaceAndColorConvertVideoFrame();
 
+                       ConvertAVCodecContextToVideoFrameRate(*fContext, 
fOutputFrameRate);
+
 #ifdef DEBUG
                        dump_ffframe(fRawDecodedPicture, "ffpict");
 //                     dump_ffframe(fPostProcessedDecodedPicture, "opict");
@@ -909,8 +899,8 @@ AVCodecDecoder::_UpdateMediaHeaderForVideoFrame()
        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
-               = CalculateBytesPerRowWithColorSpaceAndVideoWidth(
-                       fOutputVideoFormat.display.format, 
fRawDecodedPicture->width);
+               = 
CalculateBytesPerRowWithColorSpaceAndVideoWidth(fOutputColorSpace,
+                       fRawDecodedPicture->width);
        fHeader.u.raw_video.field_gamma = 1.0;
        fHeader.u.raw_video.field_sequence = fFrame;
        fHeader.u.raw_video.field_number = 0;
@@ -947,8 +937,8 @@ AVCodecDecoder::_UpdateMediaHeaderForVideoFrame()
 void
 AVCodecDecoder::_DeinterlaceAndColorConvertVideoFrame()
 {
-       int width = fOutputVideoFormat.display.line_width;
-       int height = fOutputVideoFormat.display.line_count;
+       int displayWidth = fHeader.u.raw_video.display_line_width;
+       int displayHeight = fHeader.u.raw_video.display_line_count;
        AVPicture deinterlacedPicture;
        bool useDeinterlacedPicture = false;
 
@@ -963,11 +953,11 @@ AVCodecDecoder::_DeinterlaceAndColorConvertVideoFrame()
                rawPicture.linesize[2] = fRawDecodedPicture->linesize[2];
                rawPicture.linesize[3] = fRawDecodedPicture->linesize[3];
 
-               avpicture_alloc(&deinterlacedPicture,
-                       fContext->pix_fmt, width, height);
+               avpicture_alloc(&deinterlacedPicture, fContext->pix_fmt, 
displayWidth,
+                       displayHeight);
 
                if (avpicture_deinterlace(&deinterlacedPicture, &rawPicture,
-                               fContext->pix_fmt, width, height) < 0) {
+                               fContext->pix_fmt, displayWidth, displayHeight) 
< 0) {
                        TRACE("[v] avpicture_deinterlace() - error\n");
                } else
                        useDeinterlacedPicture = true;
@@ -976,22 +966,20 @@ AVCodecDecoder::_DeinterlaceAndColorConvertVideoFrame()
        // Some decoders do not set pix_fmt until they have decoded 1 frame
 #if USE_SWS_FOR_COLOR_SPACE_CONVERSION
        if (fSwsContext == NULL) {
-               fSwsContext = sws_getContext(fContext->width, fContext->height,
-                       fContext->pix_fmt, fContext->width, fContext->height,
-                       colorspace_to_pixfmt(fOutputVideoFormat.display.format),
+               fSwsContext = sws_getContext(displayWidth, displayHeight,
+                       fContext->pix_fmt, displayWidth, displayHeight,
+                       colorspace_to_pixfmt(fOutputColorSpace),
                        SWS_FAST_BILINEAR, NULL, NULL, NULL);
        }
 #else
        if (fFormatConversionFunc == NULL) {
-               fFormatConversionFunc = resolve_colorspace(
-                       fOutputVideoFormat.display.format, fContext->pix_fmt,
-                       fContext->width, fContext->height);
+               fFormatConversionFunc = resolve_colorspace(fOutputColorSpace,
+                       fContext->pix_fmt, displayWidth, displayHeight);
        }
 #endif
 
        fDecodedDataSizeInBytes = avpicture_get_size(
-               colorspace_to_pixfmt(fOutputVideoFormat.display.format),
-               fContext->width, fContext->height);
+               colorspace_to_pixfmt(fOutputColorSpace), displayWidth, 
displayHeight);
 
        if (fDecodedData == NULL)
                fDecodedData
@@ -999,7 +987,7 @@ AVCodecDecoder::_DeinterlaceAndColorConvertVideoFrame()
 
        fPostProcessedDecodedPicture->data[0] = fDecodedData;
        fPostProcessedDecodedPicture->linesize[0]
-               = fOutputVideoFormat.display.bytes_per_row;
+               = fHeader.u.raw_video.bytes_per_row;
 
 #if USE_SWS_FOR_COLOR_SPACE_CONVERSION
        if (fSwsContext != NULL) {
@@ -1023,22 +1011,22 @@ AVCodecDecoder::_DeinterlaceAndColorConvertVideoFrame()
 
 #if USE_SWS_FOR_COLOR_SPACE_CONVERSION
                        sws_scale(fSwsContext, deinterlacedFrame.data,
-                               deinterlacedFrame.linesize, 0, fContext->height,
+                               deinterlacedFrame.linesize, 0, displayHeight,
                                fPostProcessedDecodedPicture->data,
                                fPostProcessedDecodedPicture->linesize);
 #else
                        (*fFormatConversionFunc)(&deinterlacedFrame,
-                               fPostProcessedDecodedPicture, width, height);
+                               fPostProcessedDecodedPicture, displayWidth, 
displayHeight);
 #endif
                } else {
 #if USE_SWS_FOR_COLOR_SPACE_CONVERSION
                        sws_scale(fSwsContext, fRawDecodedPicture->data,
-                               fRawDecodedPicture->linesize, 0, 
fContext->height,
+                               fRawDecodedPicture->linesize, 0, displayHeight,
                                fPostProcessedDecodedPicture->data,
                                fPostProcessedDecodedPicture->linesize);
 #else
                        (*fFormatConversionFunc)(fRawDecodedPicture,
-                               fPostProcessedDecodedPicture, width, height);
+                               fPostProcessedDecodedPicture, displayWidth, 
displayHeight);
 #endif
                }
        }
diff --git a/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.h 
b/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.h
index fc604c8..25de738 100644
--- a/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.h
+++ b/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.h
@@ -75,7 +75,6 @@ private:
                                                                        // 
decoded audio / video frame
 
                        media_format            fInputFormat;
-                       media_raw_video_format fOutputVideoFormat;
 
                        int64                           fFrame;
                        bool                            fIsAudio;
@@ -98,6 +97,7 @@ private:
                        int                                     fBlockAlign;
 
                        bigtime_t                       fStartTime;
+                       color_space                     fOutputColorSpace;
                        int32                           fOutputFrameCount;
                        float                           fOutputFrameRate;
                        int                                     
fOutputFrameSize;

############################################################################

Revision:    hrev47618
Commit:      6a18ef8358523873c8536722e009a4ab85b1049b
URL:         http://cgit.haiku-os.org/haiku/commit/?id=6a18ef8
Author:      Colin Günther <coling@xxxxxx>
Date:        Sun Aug  3 22:48:22 2014 UTC

MediaKit: Remove superflous code in mpeg2_decoder_test.

- Thanks to automatic video decoding parameter detection, we no longer need to
  manually hack the correct parameters for this test to succeed, jiha!

----------------------------------------------------------------------------

diff --git a/src/tests/kits/media/mpeg2_decoder_test/mpeg2_decoder_test.cpp 
b/src/tests/kits/media/mpeg2_decoder_test/mpeg2_decoder_test.cpp
index 8d65ad9..65bf9fc 100644
--- a/src/tests/kits/media/mpeg2_decoder_test/mpeg2_decoder_test.cpp
+++ b/src/tests/kits/media/mpeg2_decoder_test/mpeg2_decoder_test.cpp
@@ -213,16 +213,6 @@ CreateMpeg2MediaFormat()
                return kFailedToCreateMpeg2MediaFormat;
        }
 
-       // TODO: The following code block can be removed, once the ffmpeg addon 
can
-       // determine the codec output parameters from the encoded data.
-       mpeg2MediaFormat->u.encoded_video.output.first_active = 0;
-       mpeg2MediaFormat->u.encoded_video.output.last_active = 575;
-       mpeg2MediaFormat->u.encoded_video.output.orientation
-               = B_VIDEO_TOP_LEFT_RIGHT;
-       mpeg2MediaFormat->u.encoded_video.output.display.format = B_YUV420;
-       mpeg2MediaFormat->u.encoded_video.output.display.line_width = 720;
-       mpeg2MediaFormat->u.encoded_video.output.display.line_count = 576;
-
        return mpeg2MediaFormat;
 }
 


Other related posts:

  • » [haiku-commits] haiku: hrev47618 - in src: add-ons/media/plugins/ffmpeg tests/kits/media/mpeg2_decoder_test - coling