LCOV - code coverage report
Current view: top level - dom/media/platforms/agnostic - TheoraDecoder.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 108 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 17 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim:set ts=2 sw=2 sts=2 et cindent: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "TheoraDecoder.h"
       8             : #include "TimeUnits.h"
       9             : #include "XiphExtradata.h"
      10             : #include "gfx2DGlue.h"
      11             : #include "mozilla/PodOperations.h"
      12             : #include "nsError.h"
      13             : 
      14             : #include <algorithm>
      15             : 
      16             : #undef LOG
      17             : #define LOG(arg, ...) MOZ_LOG(gMediaDecoderLog, mozilla::LogLevel::Debug, ("TheoraDecoder(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
      18             : 
      19             : namespace mozilla {
      20             : 
      21             : using namespace gfx;
      22             : using namespace layers;
      23             : 
      24             : extern LazyLogModule gMediaDecoderLog;
      25             : 
      26           0 : ogg_packet InitTheoraPacket(const unsigned char* aData, size_t aLength,
      27             :                          bool aBOS, bool aEOS,
      28             :                          int64_t aGranulepos, int64_t aPacketNo)
      29             : {
      30             :   ogg_packet packet;
      31           0 :   packet.packet = const_cast<unsigned char*>(aData);
      32           0 :   packet.bytes = aLength;
      33           0 :   packet.b_o_s = aBOS;
      34           0 :   packet.e_o_s = aEOS;
      35           0 :   packet.granulepos = aGranulepos;
      36           0 :   packet.packetno = aPacketNo;
      37           0 :   return packet;
      38             : }
      39             : 
      40           0 : TheoraDecoder::TheoraDecoder(const CreateDecoderParams& aParams)
      41             :   : mImageAllocator(aParams.mKnowsCompositor)
      42           0 :   , mImageContainer(aParams.mImageContainer)
      43           0 :   , mTaskQueue(aParams.mTaskQueue)
      44             :   , mTheoraSetupInfo(nullptr)
      45             :   , mTheoraDecoderContext(nullptr)
      46             :   , mPacketCount(0)
      47           0 :   , mInfo(aParams.VideoConfig())
      48             : {
      49           0 :   MOZ_COUNT_CTOR(TheoraDecoder);
      50           0 : }
      51             : 
      52           0 : TheoraDecoder::~TheoraDecoder()
      53             : {
      54           0 :   MOZ_COUNT_DTOR(TheoraDecoder);
      55           0 :   th_setup_free(mTheoraSetupInfo);
      56           0 :   th_comment_clear(&mTheoraComment);
      57           0 :   th_info_clear(&mTheoraInfo);
      58           0 : }
      59             : 
      60             : RefPtr<ShutdownPromise>
      61           0 : TheoraDecoder::Shutdown()
      62             : {
      63           0 :   RefPtr<TheoraDecoder> self = this;
      64           0 :   return InvokeAsync(mTaskQueue, __func__, [self, this]() {
      65           0 :     if (mTheoraDecoderContext) {
      66           0 :       th_decode_free(mTheoraDecoderContext);
      67           0 :       mTheoraDecoderContext = nullptr;
      68             :     }
      69           0 :     return ShutdownPromise::CreateAndResolve(true, __func__);
      70           0 :   });
      71             : }
      72             : 
      73             : RefPtr<MediaDataDecoder::InitPromise>
      74           0 : TheoraDecoder::Init()
      75             : {
      76           0 :   th_comment_init(&mTheoraComment);
      77           0 :   th_info_init(&mTheoraInfo);
      78             : 
      79           0 :   nsTArray<unsigned char*> headers;
      80           0 :   nsTArray<size_t> headerLens;
      81           0 :   if (!XiphExtradataToHeaders(headers, headerLens,
      82           0 :       mInfo.mCodecSpecificConfig->Elements(),
      83           0 :       mInfo.mCodecSpecificConfig->Length())) {
      84           0 :     return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
      85             :   }
      86           0 :   for (size_t i = 0; i < headers.Length(); i++) {
      87           0 :     if (NS_FAILED(DoDecodeHeader(headers[i], headerLens[i]))) {
      88             :       return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR,
      89           0 :                                           __func__);
      90             :     }
      91             :   }
      92           0 :   if (mPacketCount != 3) {
      93           0 :     return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
      94             :   }
      95             : 
      96           0 :   mTheoraDecoderContext = th_decode_alloc(&mTheoraInfo, mTheoraSetupInfo);
      97           0 :   if (mTheoraDecoderContext) {
      98           0 :     return InitPromise::CreateAndResolve(TrackInfo::kVideoTrack, __func__);
      99             :   } else {
     100           0 :     return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
     101             :   }
     102             : 
     103             : }
     104             : 
     105             : RefPtr<MediaDataDecoder::FlushPromise>
     106           0 : TheoraDecoder::Flush()
     107             : {
     108           0 :   return InvokeAsync(mTaskQueue, __func__, []() {
     109             :     return FlushPromise::CreateAndResolve(true, __func__);
     110           0 :   });
     111             : }
     112             : 
     113             : nsresult
     114           0 : TheoraDecoder::DoDecodeHeader(const unsigned char* aData, size_t aLength)
     115             : {
     116           0 :   bool bos = mPacketCount == 0;
     117             :   ogg_packet pkt =
     118           0 :     InitTheoraPacket(aData, aLength, bos, false, 0, mPacketCount++);
     119             : 
     120           0 :   int r = th_decode_headerin(&mTheoraInfo,
     121             :                              &mTheoraComment,
     122             :                              &mTheoraSetupInfo,
     123           0 :                              &pkt);
     124           0 :   return r > 0 ? NS_OK : NS_ERROR_FAILURE;
     125             : }
     126             : 
     127             : RefPtr<MediaDataDecoder::DecodePromise>
     128           0 : TheoraDecoder::ProcessDecode(MediaRawData* aSample)
     129             : {
     130           0 :   MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
     131             : 
     132           0 :   const unsigned char* aData = aSample->Data();
     133           0 :   size_t aLength = aSample->Size();
     134             : 
     135           0 :   bool bos = mPacketCount == 0;
     136             :   ogg_packet pkt = InitTheoraPacket(
     137             :     aData, aLength, bos, false,
     138           0 :     aSample->mTimecode.ToMicroseconds(), mPacketCount++);
     139             : 
     140           0 :   int ret = th_decode_packetin(mTheoraDecoderContext, &pkt, nullptr);
     141           0 :   if (ret == 0 || ret == TH_DUPFRAME) {
     142             :     th_ycbcr_buffer ycbcr;
     143           0 :     th_decode_ycbcr_out(mTheoraDecoderContext, ycbcr);
     144             : 
     145           0 :     int hdec = !(mTheoraInfo.pixel_fmt & 1);
     146           0 :     int vdec = !(mTheoraInfo.pixel_fmt & 2);
     147             : 
     148           0 :     VideoData::YCbCrBuffer b;
     149           0 :     b.mPlanes[0].mData = ycbcr[0].data;
     150           0 :     b.mPlanes[0].mStride = ycbcr[0].stride;
     151           0 :     b.mPlanes[0].mHeight = mTheoraInfo.frame_height;
     152           0 :     b.mPlanes[0].mWidth = mTheoraInfo.frame_width;
     153           0 :     b.mPlanes[0].mOffset = b.mPlanes[0].mSkip = 0;
     154             : 
     155           0 :     b.mPlanes[1].mData = ycbcr[1].data;
     156           0 :     b.mPlanes[1].mStride = ycbcr[1].stride;
     157           0 :     b.mPlanes[1].mHeight = mTheoraInfo.frame_height >> vdec;
     158           0 :     b.mPlanes[1].mWidth = mTheoraInfo.frame_width >> hdec;
     159           0 :     b.mPlanes[1].mOffset = b.mPlanes[1].mSkip = 0;
     160             : 
     161           0 :     b.mPlanes[2].mData = ycbcr[2].data;
     162           0 :     b.mPlanes[2].mStride = ycbcr[2].stride;
     163           0 :     b.mPlanes[2].mHeight = mTheoraInfo.frame_height >> vdec;
     164           0 :     b.mPlanes[2].mWidth = mTheoraInfo.frame_width >> hdec;
     165           0 :     b.mPlanes[2].mOffset = b.mPlanes[2].mSkip = 0;
     166             : 
     167             :     IntRect pictureArea(mTheoraInfo.pic_x, mTheoraInfo.pic_y,
     168           0 :                         mTheoraInfo.pic_width, mTheoraInfo.pic_height);
     169             : 
     170           0 :     VideoInfo info;
     171           0 :     info.mDisplay = mInfo.mDisplay;
     172             :     RefPtr<VideoData> v =
     173           0 :       VideoData::CreateAndCopyData(info,
     174             :                                    mImageContainer,
     175             :                                    aSample->mOffset,
     176             :                                    aSample->mTime,
     177             :                                    aSample->mDuration,
     178             :                                    b,
     179           0 :                                    aSample->mKeyframe,
     180             :                                    aSample->mTimecode,
     181           0 :                                    mInfo.ScaledImageRect(mTheoraInfo.frame_width,
     182           0 :                                                          mTheoraInfo.frame_height),
     183           0 :                                    mImageAllocator);
     184           0 :     if (!v) {
     185           0 :       LOG(
     186             :         "Image allocation error source %ux%u display %ux%u picture %ux%u",
     187             :         mTheoraInfo.frame_width,
     188             :         mTheoraInfo.frame_height,
     189             :         mInfo.mDisplay.width,
     190             :         mInfo.mDisplay.height,
     191             :         mInfo.mImage.width,
     192             :         mInfo.mImage.height);
     193             :       return DecodePromise::CreateAndReject(
     194           0 :         MediaResult(NS_ERROR_OUT_OF_MEMORY,
     195           0 :                     RESULT_DETAIL("Insufficient memory")),
     196           0 :         __func__);
     197             :     }
     198           0 :     return DecodePromise::CreateAndResolve(DecodedData{v}, __func__);
     199             :   }
     200           0 :   LOG("Theora Decode error: %d", ret);
     201             :   return DecodePromise::CreateAndReject(
     202           0 :     MediaResult(NS_ERROR_DOM_MEDIA_DECODE_ERR,
     203           0 :                 RESULT_DETAIL("Theora decode error:%d", ret)),
     204           0 :     __func__);
     205             : }
     206             : 
     207             : RefPtr<MediaDataDecoder::DecodePromise>
     208           0 : TheoraDecoder::Decode(MediaRawData* aSample)
     209             : {
     210             :   return InvokeAsync<MediaRawData*>(mTaskQueue, this, __func__,
     211           0 :                                     &TheoraDecoder::ProcessDecode, aSample);
     212             : }
     213             : 
     214             : RefPtr<MediaDataDecoder::DecodePromise>
     215           0 : TheoraDecoder::Drain()
     216             : {
     217           0 :   return InvokeAsync(mTaskQueue, __func__, [] {
     218           0 :     return DecodePromise::CreateAndResolve(DecodedData(), __func__);
     219           0 :   });
     220             : }
     221             : 
     222             : /* static */
     223             : bool
     224           0 : TheoraDecoder::IsTheora(const nsACString& aMimeType)
     225             : {
     226           0 :   return aMimeType.EqualsLiteral("video/theora");
     227             : }
     228             : 
     229             : } // namespace mozilla
     230             : #undef LOG

Generated by: LCOV version 1.13