MediaData.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "MediaData.h"
  6. #include "MediaInfo.h"
  7. #include "VideoUtils.h"
  8. #include "ImageContainer.h"
  9. #include <stdint.h>
  10. namespace mozilla {
  11. using namespace mozilla::gfx;
  12. using layers::ImageContainer;
  13. using layers::PlanarYCbCrImage;
  14. using layers::PlanarYCbCrData;
  15. const char* AudioData::sTypeName = "audio";
  16. const char* VideoData::sTypeName = "video";
  17. void
  18. AudioData::EnsureAudioBuffer()
  19. {
  20. if (mAudioBuffer)
  21. return;
  22. mAudioBuffer = SharedBuffer::Create(mFrames*mChannels*sizeof(AudioDataValue));
  23. AudioDataValue* data = static_cast<AudioDataValue*>(mAudioBuffer->Data());
  24. for (uint32_t i = 0; i < mFrames; ++i) {
  25. for (uint32_t j = 0; j < mChannels; ++j) {
  26. data[j*mFrames + i] = mAudioData[i*mChannels + j];
  27. }
  28. }
  29. }
  30. size_t
  31. AudioData::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
  32. {
  33. size_t size =
  34. aMallocSizeOf(this) + mAudioData.SizeOfExcludingThis(aMallocSizeOf);
  35. if (mAudioBuffer) {
  36. size += mAudioBuffer->SizeOfIncludingThis(aMallocSizeOf);
  37. }
  38. return size;
  39. }
  40. bool
  41. AudioData::IsAudible() const
  42. {
  43. if (!mAudioData) {
  44. return false;
  45. }
  46. for (uint32_t frame = 0; frame < mFrames; ++frame) {
  47. for (uint32_t channel = 0; channel < mChannels; ++channel) {
  48. if (mAudioData[frame * mChannels + channel] != 0) {
  49. return true;
  50. }
  51. }
  52. }
  53. return false;
  54. }
  55. /* static */
  56. already_AddRefed<AudioData>
  57. AudioData::TransferAndUpdateTimestampAndDuration(AudioData* aOther,
  58. int64_t aTimestamp,
  59. int64_t aDuration)
  60. {
  61. NS_ENSURE_TRUE(aOther, nullptr);
  62. RefPtr<AudioData> v = new AudioData(aOther->mOffset,
  63. aTimestamp,
  64. aDuration,
  65. aOther->mFrames,
  66. Move(aOther->mAudioData),
  67. aOther->mChannels,
  68. aOther->mRate);
  69. return v.forget();
  70. }
  71. static bool
  72. ValidatePlane(const VideoData::YCbCrBuffer::Plane& aPlane)
  73. {
  74. return aPlane.mWidth <= PlanarYCbCrImage::MAX_DIMENSION &&
  75. aPlane.mHeight <= PlanarYCbCrImage::MAX_DIMENSION &&
  76. aPlane.mWidth * aPlane.mHeight < MAX_VIDEO_WIDTH * MAX_VIDEO_HEIGHT &&
  77. aPlane.mStride > 0 && aPlane.mWidth <= aPlane.mStride;
  78. }
  79. VideoData::VideoData(int64_t aOffset,
  80. int64_t aTime,
  81. int64_t aDuration,
  82. bool aKeyframe,
  83. int64_t aTimecode,
  84. IntSize aDisplay,
  85. layers::ImageContainer::FrameID aFrameID)
  86. : MediaData(VIDEO_DATA, aOffset, aTime, aDuration, 1)
  87. , mDisplay(aDisplay)
  88. , mFrameID(aFrameID)
  89. , mSentToCompositor(false)
  90. {
  91. NS_ASSERTION(mDuration >= 0, "Frame must have non-negative duration.");
  92. mKeyframe = aKeyframe;
  93. mTimecode = aTimecode;
  94. }
  95. VideoData::~VideoData()
  96. {
  97. }
  98. size_t
  99. VideoData::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
  100. {
  101. size_t size = aMallocSizeOf(this);
  102. // Currently only PLANAR_YCBCR has a well defined function for determining
  103. // it's size, so reporting is limited to that type.
  104. if (mImage && mImage->GetFormat() == ImageFormat::PLANAR_YCBCR) {
  105. const mozilla::layers::PlanarYCbCrImage* img =
  106. static_cast<const mozilla::layers::PlanarYCbCrImage*>(mImage.get());
  107. size += img->SizeOfIncludingThis(aMallocSizeOf);
  108. }
  109. return size;
  110. }
  111. /* static */
  112. already_AddRefed<VideoData>
  113. VideoData::ShallowCopyUpdateDuration(const VideoData* aOther,
  114. int64_t aDuration)
  115. {
  116. RefPtr<VideoData> v = new VideoData(aOther->mOffset,
  117. aOther->mTime,
  118. aDuration,
  119. aOther->mKeyframe,
  120. aOther->mTimecode,
  121. aOther->mDisplay,
  122. aOther->mFrameID);
  123. v->mImage = aOther->mImage;
  124. return v.forget();
  125. }
  126. /* static */
  127. already_AddRefed<VideoData>
  128. VideoData::ShallowCopyUpdateTimestamp(const VideoData* aOther,
  129. int64_t aTimestamp)
  130. {
  131. NS_ENSURE_TRUE(aOther, nullptr);
  132. RefPtr<VideoData> v = new VideoData(aOther->mOffset,
  133. aTimestamp,
  134. aOther->GetEndTime() - aTimestamp,
  135. aOther->mKeyframe,
  136. aOther->mTimecode,
  137. aOther->mDisplay,
  138. aOther->mFrameID);
  139. v->mImage = aOther->mImage;
  140. return v.forget();
  141. }
  142. /* static */
  143. already_AddRefed<VideoData>
  144. VideoData::ShallowCopyUpdateTimestampAndDuration(const VideoData* aOther,
  145. int64_t aTimestamp,
  146. int64_t aDuration)
  147. {
  148. NS_ENSURE_TRUE(aOther, nullptr);
  149. RefPtr<VideoData> v = new VideoData(aOther->mOffset,
  150. aTimestamp,
  151. aDuration,
  152. aOther->mKeyframe,
  153. aOther->mTimecode,
  154. aOther->mDisplay,
  155. aOther->mFrameID);
  156. v->mImage = aOther->mImage;
  157. return v.forget();
  158. }
  159. /* static */
  160. bool VideoData::SetVideoDataToImage(PlanarYCbCrImage* aVideoImage,
  161. const VideoInfo& aInfo,
  162. const YCbCrBuffer &aBuffer,
  163. const IntRect& aPicture,
  164. bool aCopyData)
  165. {
  166. if (!aVideoImage) {
  167. return false;
  168. }
  169. const YCbCrBuffer::Plane &Y = aBuffer.mPlanes[0];
  170. const YCbCrBuffer::Plane &Cb = aBuffer.mPlanes[1];
  171. const YCbCrBuffer::Plane &Cr = aBuffer.mPlanes[2];
  172. PlanarYCbCrData data;
  173. data.mYChannel = Y.mData + Y.mOffset;
  174. data.mYSize = IntSize(Y.mWidth, Y.mHeight);
  175. data.mYStride = Y.mStride;
  176. data.mYSkip = Y.mSkip;
  177. data.mCbChannel = Cb.mData + Cb.mOffset;
  178. data.mCrChannel = Cr.mData + Cr.mOffset;
  179. data.mCbCrSize = IntSize(Cb.mWidth, Cb.mHeight);
  180. data.mCbCrStride = Cb.mStride;
  181. data.mCbSkip = Cb.mSkip;
  182. data.mCrSkip = Cr.mSkip;
  183. data.mPicX = aPicture.x;
  184. data.mPicY = aPicture.y;
  185. data.mPicSize = aPicture.Size();
  186. data.mStereoMode = aInfo.mStereoMode;
  187. data.mYUVColorSpace = aBuffer.mYUVColorSpace;
  188. aVideoImage->SetDelayedConversion(true);
  189. if (aCopyData) {
  190. return aVideoImage->CopyData(data);
  191. } else {
  192. return aVideoImage->AdoptData(data);
  193. }
  194. }
  195. /* static */
  196. already_AddRefed<VideoData>
  197. VideoData::CreateAndCopyData(const VideoInfo& aInfo,
  198. ImageContainer* aContainer,
  199. int64_t aOffset,
  200. int64_t aTime,
  201. int64_t aDuration,
  202. const YCbCrBuffer& aBuffer,
  203. bool aKeyframe,
  204. int64_t aTimecode,
  205. const IntRect& aPicture)
  206. {
  207. if (!aContainer) {
  208. // Create a dummy VideoData with no image. This gives us something to
  209. // send to media streams if necessary.
  210. RefPtr<VideoData> v(new VideoData(aOffset,
  211. aTime,
  212. aDuration,
  213. aKeyframe,
  214. aTimecode,
  215. aInfo.mDisplay,
  216. 0));
  217. return v.forget();
  218. }
  219. // The following situation should never happen unless there is a bug
  220. // in the decoder
  221. if (aBuffer.mPlanes[1].mWidth != aBuffer.mPlanes[2].mWidth ||
  222. aBuffer.mPlanes[1].mHeight != aBuffer.mPlanes[2].mHeight) {
  223. NS_ERROR("C planes with different sizes");
  224. return nullptr;
  225. }
  226. // The following situations could be triggered by invalid input
  227. if (aPicture.width <= 0 || aPicture.height <= 0) {
  228. // In debug mode, makes the error more noticeable
  229. MOZ_ASSERT(false, "Empty picture rect");
  230. return nullptr;
  231. }
  232. if (!ValidatePlane(aBuffer.mPlanes[0]) || !ValidatePlane(aBuffer.mPlanes[1]) ||
  233. !ValidatePlane(aBuffer.mPlanes[2])) {
  234. NS_WARNING("Invalid plane size");
  235. return nullptr;
  236. }
  237. // Ensure the picture size specified in the headers can be extracted out of
  238. // the frame we've been supplied without indexing out of bounds.
  239. CheckedUint32 xLimit = aPicture.x + CheckedUint32(aPicture.width);
  240. CheckedUint32 yLimit = aPicture.y + CheckedUint32(aPicture.height);
  241. if (!xLimit.isValid() || xLimit.value() > aBuffer.mPlanes[0].mStride ||
  242. !yLimit.isValid() || yLimit.value() > aBuffer.mPlanes[0].mHeight)
  243. {
  244. // The specified picture dimensions can't be contained inside the video
  245. // frame, we'll stomp memory if we try to copy it. Fail.
  246. NS_WARNING("Overflowing picture rect");
  247. return nullptr;
  248. }
  249. RefPtr<VideoData> v(new VideoData(aOffset,
  250. aTime,
  251. aDuration,
  252. aKeyframe,
  253. aTimecode,
  254. aInfo.mDisplay,
  255. 0));
  256. // Currently our decoder only knows how to output to ImageFormat::PLANAR_YCBCR
  257. // format.
  258. if (!v->mImage) {
  259. v->mImage = aContainer->CreatePlanarYCbCrImage();
  260. }
  261. if (!v->mImage) {
  262. return nullptr;
  263. }
  264. NS_ASSERTION(v->mImage->GetFormat() == ImageFormat::PLANAR_YCBCR ||
  265. v->mImage->GetFormat() == ImageFormat::GRALLOC_PLANAR_YCBCR,
  266. "Wrong format?");
  267. PlanarYCbCrImage* videoImage = v->mImage->AsPlanarYCbCrImage();
  268. MOZ_ASSERT(videoImage);
  269. if (!VideoData::SetVideoDataToImage(videoImage, aInfo, aBuffer, aPicture,
  270. true /* aCopyData */)) {
  271. return nullptr;
  272. }
  273. return v.forget();
  274. }
  275. /* static */
  276. already_AddRefed<VideoData>
  277. VideoData::CreateFromImage(const VideoInfo& aInfo,
  278. int64_t aOffset,
  279. int64_t aTime,
  280. int64_t aDuration,
  281. const RefPtr<Image>& aImage,
  282. bool aKeyframe,
  283. int64_t aTimecode,
  284. const IntRect& aPicture)
  285. {
  286. RefPtr<VideoData> v(new VideoData(aOffset,
  287. aTime,
  288. aDuration,
  289. aKeyframe,
  290. aTimecode,
  291. aInfo.mDisplay,
  292. 0));
  293. v->mImage = aImage;
  294. return v.forget();
  295. }
  296. MediaRawData::MediaRawData()
  297. : MediaData(RAW_DATA, 0)
  298. , mCrypto(mCryptoInternal)
  299. {
  300. }
  301. MediaRawData::MediaRawData(const uint8_t* aData, size_t aSize)
  302. : MediaData(RAW_DATA, 0)
  303. , mCrypto(mCryptoInternal)
  304. , mBuffer(aData, aSize)
  305. {
  306. }
  307. already_AddRefed<MediaRawData>
  308. MediaRawData::Clone() const
  309. {
  310. RefPtr<MediaRawData> s = new MediaRawData;
  311. s->mTimecode = mTimecode;
  312. s->mTime = mTime;
  313. s->mDuration = mDuration;
  314. s->mOffset = mOffset;
  315. s->mKeyframe = mKeyframe;
  316. s->mExtraData = mExtraData;
  317. s->mCryptoInternal = mCryptoInternal;
  318. s->mTrackInfo = mTrackInfo;
  319. s->mEOS = mEOS;
  320. if (!s->mBuffer.Append(mBuffer.Data(), mBuffer.Length())) {
  321. return nullptr;
  322. }
  323. return s.forget();
  324. }
  325. MediaRawData::~MediaRawData()
  326. {
  327. }
  328. size_t
  329. MediaRawData::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
  330. {
  331. size_t size = aMallocSizeOf(this);
  332. size += mBuffer.SizeOfExcludingThis(aMallocSizeOf);
  333. return size;
  334. }
  335. MediaRawDataWriter*
  336. MediaRawData::CreateWriter()
  337. {
  338. return new MediaRawDataWriter(this);
  339. }
  340. MediaRawDataWriter::MediaRawDataWriter(MediaRawData* aMediaRawData)
  341. : mCrypto(aMediaRawData->mCryptoInternal)
  342. , mTarget(aMediaRawData)
  343. {
  344. }
  345. bool
  346. MediaRawDataWriter::SetSize(size_t aSize)
  347. {
  348. return mTarget->mBuffer.SetLength(aSize);
  349. }
  350. bool
  351. MediaRawDataWriter::Prepend(const uint8_t* aData, size_t aSize)
  352. {
  353. return mTarget->mBuffer.Prepend(aData, aSize);
  354. }
  355. bool
  356. MediaRawDataWriter::Replace(const uint8_t* aData, size_t aSize)
  357. {
  358. return mTarget->mBuffer.Replace(aData, aSize);
  359. }
  360. void
  361. MediaRawDataWriter::Clear()
  362. {
  363. mTarget->mBuffer.Clear();
  364. }
  365. uint8_t*
  366. MediaRawDataWriter::Data()
  367. {
  368. return mTarget->mBuffer.Data();
  369. }
  370. size_t
  371. MediaRawDataWriter::Size()
  372. {
  373. return mTarget->Size();
  374. }
  375. } // namespace mozilla