PageRenderTime 82ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/csrc/com/xuggle/xuggler/StreamCoder.cpp

https://github.com/extremolo/xuggle-xuggler
C++ | 2112 lines | 1691 code | 216 blank | 205 comment | 358 complexity | ffac5f47f5c9cfb041ccee768d74d206 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, GPL-3.0, LGPL-3.0, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. /*******************************************************************************
  2. * Copyright (c) 2008, 2010 Xuggle Inc. All rights reserved.
  3. *
  4. * This file is part of Xuggle-Xuggler-Main.
  5. *
  6. * Xuggle-Xuggler-Main is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Lesser General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Xuggle-Xuggler-Main is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with Xuggle-Xuggler-Main. If not, see <http://www.gnu.org/licenses/>.
  18. *******************************************************************************/
  19. #include <stdexcept>
  20. #include <cstring>
  21. #define attribute_deprecated
  22. #include <com/xuggle/ferry/Logger.h>
  23. #include <com/xuggle/ferry/RefPointer.h>
  24. #include <com/xuggle/xuggler/Global.h>
  25. #include <com/xuggle/xuggler/StreamCoder.h>
  26. #include <com/xuggle/xuggler/Codec.h>
  27. #include <com/xuggle/xuggler/Rational.h>
  28. #include <com/xuggle/xuggler/AudioSamples.h>
  29. #include <com/xuggle/xuggler/VideoPicture.h>
  30. #include <com/xuggle/xuggler/Packet.h>
  31. #include <com/xuggle/xuggler/Property.h>
  32. #include <com/xuggle/xuggler/MetaData.h>
  33. extern "C" {
  34. #include <libavutil/dict.h>
  35. }
  36. VS_LOG_SETUP(VS_CPP_PACKAGE);
  37. namespace com {
  38. namespace xuggle {
  39. namespace xuggler {
  40. using namespace com::xuggle::ferry;
  41. StreamCoder::StreamCoder() :
  42. mCodec(0)
  43. {
  44. mCodecContext = 0;
  45. // default to DECODING.
  46. mDirection = DECODING;
  47. mOpened = false;
  48. mStream = 0;
  49. mAudioFrameBuffer = 0;
  50. mBytesInFrameBuffer = 0;
  51. mFakePtsTimeBase = IRational::make(1, AV_TIME_BASE);
  52. mFakeNextPts = Global::NO_PTS;
  53. mFakeCurrPts = Global::NO_PTS;
  54. mLastPtsEncoded = Global::NO_PTS;
  55. mSamplesCoded = 0;
  56. mLastExternallySetTimeStamp = Global::NO_PTS;
  57. mDefaultAudioFrameSize = 576;
  58. mNumDroppedFrames = 0;
  59. mAutomaticallyStampPacketsForStream = true;
  60. for(uint32_t i = 0; i < sizeof(mPtsBuffer)/sizeof(mPtsBuffer[0]); i++)
  61. {
  62. mPtsBuffer[i] = Global::NO_PTS;
  63. }
  64. }
  65. StreamCoder::~StreamCoder()
  66. {
  67. reset();
  68. }
  69. void
  70. StreamCoder::resetOptions(AVCodecContext* ctx)
  71. {
  72. if (!ctx)
  73. return;
  74. if (ctx->codec && ctx->codec->priv_class && ctx->priv_data)
  75. av_opt_free(ctx->priv_data);
  76. av_opt_free(ctx);
  77. av_freep(&ctx->priv_data);
  78. }
  79. void
  80. StreamCoder::reset()
  81. {
  82. // Auto-close if the caller forgot to close this
  83. // stream-coder
  84. if (mOpened)
  85. {
  86. VS_LOG_DEBUG("Closing dangling StreamCoder");
  87. (void) this->close();
  88. }
  89. mAutomaticallyStampPacketsForStream = true;
  90. mOpened = false;
  91. // Don't free if we're attached to a Stream.
  92. // The Container will do that.
  93. if (mCodecContext) {
  94. // for reasons that I'm sure they will fix some day, avformat_free_context
  95. // does not free private options. it should.
  96. resetOptions(mCodecContext);
  97. if(!mStream)
  98. {
  99. av_freep(&mCodecContext->extradata);
  100. av_freep(&mCodecContext->subtitle_header);
  101. av_freep(&mCodecContext);
  102. }
  103. }
  104. mCodecContext = 0;
  105. // We do not refcount the stream
  106. mStream = 0;
  107. }
  108. int32_t
  109. StreamCoder :: readyAVContexts(
  110. Direction aDirection,
  111. StreamCoder *aCoder,
  112. Stream* aStream,
  113. Codec *aCodec,
  114. AVCodecContext *avContext,
  115. AVCodec *avCodec)
  116. {
  117. int retval = -1;
  118. if (!avContext)
  119. return retval;
  120. if (avContext->sample_fmt == AV_SAMPLE_FMT_NONE)
  121. avContext->sample_fmt = AV_SAMPLE_FMT_S16;
  122. if (!aCodec) {
  123. if (avCodec) {
  124. aCoder->mCodec = Codec::make(avCodec);
  125. } else if (aDirection == ENCODING) {
  126. aCoder->mCodec = dynamic_cast<Codec*>(ICodec::findEncodingCodecByIntID(avContext->codec_id));
  127. } else {
  128. aCoder->mCodec = dynamic_cast<Codec*>(ICodec::findDecodingCodecByIntID(avContext->codec_id));
  129. }
  130. } else
  131. aCoder->mCodec.reset(aCodec, true);
  132. aCodec = aCoder->mCodec.value(); // re-use reference
  133. avCodec = aCodec ? aCodec->getAVCodec() : 0;
  134. if (aCoder->mCodecContext) {
  135. // was previously set; we should do something about that.
  136. // VS_LOG_ERROR("Warning... mojo rising");
  137. resetOptions(aCoder->mCodecContext);
  138. }
  139. aCoder->mCodecContext = avContext;
  140. aCoder->mStream = aStream;
  141. aCoder->mDirection = aDirection;
  142. avContext->opaque = aCodec;
  143. // these settings are necessary to have property setting work correctly
  144. // and avContext->codec will need to be temporarily disabled BEFORE
  145. // #open is called.
  146. avContext->codec_id = avCodec ? avCodec->id : CODEC_ID_NONE;
  147. avContext->codec_type = avCodec ? avCodec->type : AVMEDIA_TYPE_UNKNOWN;
  148. avContext->codec = avCodec;
  149. switch (avContext->codec_type)
  150. {
  151. case AVMEDIA_TYPE_AUDIO:
  152. if (avContext->block_align == 1 && avContext->codec_id == CODEC_ID_MP3)
  153. avContext->block_align = 0;
  154. if (avContext->codec_id == CODEC_ID_AC3)
  155. avContext->block_align = 0;
  156. break;
  157. default:
  158. break;
  159. }
  160. VS_LOG_TRACE("StreamCoder %p codec set to: %s [%s]",
  161. aCoder,
  162. avCodec ? avCodec->name : "unknown",
  163. avCodec ? avCodec->long_name : "unknown; caller must call IStreamCoder.setCodec(ICodec)");
  164. if (!avCodec && (avContext->codec_type == AVMEDIA_TYPE_AUDIO || avContext->codec_type == AVMEDIA_TYPE_VIDEO)) {
  165. VS_LOG_WARN("DEPRECATED; StreamCoder %p created without Codec. Caller must call"
  166. " IStreamCoder.setCodec(ICodec) before any other methods", aCoder);
  167. }
  168. retval = 0;
  169. return retval;
  170. }
  171. void
  172. StreamCoder::setCodec(ICodec * aCodec)
  173. {
  174. Codec* codec = dynamic_cast<Codec*>(aCodec);
  175. AVCodec* avCodec = 0;
  176. if (!codec) {
  177. VS_LOG_INFO("Cannot set codec to null codec");
  178. return;
  179. }
  180. avCodec = codec->getAVCodec();
  181. if (!mCodecContext) {
  182. VS_LOG_ERROR("No codec context");
  183. return;
  184. }
  185. if (mCodecContext->codec_id != CODEC_ID_NONE || mCodecContext->codec) {
  186. VS_LOG_INFO("Codec already set to codec: %d. Ignoring setCodec call",
  187. mCodecContext->codec_id);
  188. return;
  189. }
  190. if (mCodec.value() == aCodec) {
  191. // setting to the same value; don't reset anything
  192. return;
  193. }
  194. if (mCodecContext) {
  195. // avcodec_get_context_defaults3 does not clear these out if already allocated
  196. // so we do.
  197. resetOptions(mCodecContext);
  198. av_freep(&mCodecContext->extradata);
  199. av_freep(&mCodecContext->subtitle_header);
  200. avcodec_get_context_defaults3(mCodecContext, avCodec);
  201. } else {
  202. mCodecContext = avcodec_alloc_context3(avCodec);
  203. }
  204. if (mCodecContext)
  205. readyAVContexts(mDirection,
  206. this,
  207. mStream,
  208. codec,
  209. mCodecContext,
  210. 0);
  211. }
  212. void
  213. StreamCoder::setCodec(ICodec::ID id)
  214. {
  215. setCodec((int32_t) id);
  216. }
  217. void
  218. StreamCoder::setCodec(int32_t id)
  219. {
  220. RefPointer<Codec> codec = 0;
  221. if (ENCODING == mDirection)
  222. {
  223. codec = Codec::findEncodingCodecByIntID(id);
  224. }
  225. else
  226. {
  227. codec = Codec::findDecodingCodecByIntID(id);
  228. }
  229. if (codec)
  230. setCodec(codec.value());
  231. }
  232. StreamCoder*
  233. StreamCoder::make(Direction direction, ICodec::ID id)
  234. {
  235. RefPointer<Codec> codec = 0;
  236. StreamCoder* retval = 0;
  237. if (ENCODING == direction)
  238. {
  239. codec = Codec::findEncodingCodec(id);
  240. }
  241. else
  242. {
  243. codec = Codec::findDecodingCodec(id);
  244. }
  245. if (codec)
  246. retval = StreamCoder::make(direction, codec.value());
  247. return retval;
  248. }
  249. StreamCoder *
  250. StreamCoder :: make (Direction direction, Codec* codec)
  251. {
  252. StreamCoder* retval= 0;
  253. try
  254. {
  255. AVCodecContext* codecCtx=0;
  256. AVCodec* avCodec = 0;
  257. if (codec)
  258. avCodec = codec->getAVCodec();
  259. retval = StreamCoder::make();
  260. if (!retval)
  261. throw std::bad_alloc();
  262. codecCtx = avcodec_alloc_context3(avCodec);
  263. if (readyAVContexts(
  264. direction,
  265. retval,
  266. 0,
  267. codec,
  268. codecCtx,
  269. avCodec) < 0)
  270. throw std::runtime_error("could not initialize codec");
  271. }
  272. catch (std::exception & e)
  273. {
  274. VS_REF_RELEASE(retval);
  275. }
  276. return retval;
  277. }
  278. StreamCoder *
  279. StreamCoder::make(Direction direction, IStreamCoder* aCoder)
  280. {
  281. StreamCoder *retval = 0;
  282. StreamCoder *coder = dynamic_cast<StreamCoder*> (aCoder);
  283. try
  284. {
  285. if (!coder)
  286. throw std::runtime_error("cannot make stream coder from null coder");
  287. RefPointer<Codec> codecToUse;
  288. codecToUse = coder->getCodec();
  289. retval = make(direction, codecToUse.value());
  290. if (!retval)
  291. throw std::bad_alloc();
  292. AVCodecContext* codec = retval->mCodecContext;
  293. AVCodecContext* icodec = coder->mCodecContext;
  294. // no really; I hate FFmpeg memory management; a lot of sensible
  295. // defaults got set up that we'll need to clear now.
  296. resetOptions(codec);
  297. av_freep(&codec->extradata);
  298. av_freep(&codec->subtitle_header);
  299. // temporarily set this back to zero
  300. codec->codec = 0;
  301. avcodec_copy_context(codec, icodec);
  302. // and copy it back by hand to ensure setProperty methods
  303. // work again
  304. codec->codec = icodec->codec;
  305. RefPointer<IStream> stream = coder->getStream();
  306. RefPointer<IRational> streamBase = stream ? stream->getTimeBase() : 0;
  307. double base = streamBase ? streamBase->getDouble() : 0;
  308. if (base && av_q2d(icodec->time_base) * icodec->ticks_per_frame > base
  309. && base < 1.0 / 1000)
  310. {
  311. codec->time_base.num *= icodec->ticks_per_frame;
  312. }
  313. if (!codec->time_base.num || !codec->time_base.den)
  314. {
  315. RefPointer<IRational> iStreamBase = coder->getTimeBase();
  316. if (iStreamBase)
  317. {
  318. codec->time_base.num = iStreamBase->getNumerator();
  319. codec->time_base.den = iStreamBase->getDenominator();
  320. }
  321. }
  322. if (readyAVContexts(
  323. direction,
  324. retval,
  325. 0,
  326. codecToUse.value(),
  327. codec,
  328. icodec->codec) < 0)
  329. throw std::runtime_error("could not initialize AVContext");
  330. }
  331. catch (std::exception &e)
  332. {
  333. VS_LOG_WARN("Error: %s", e.what());
  334. VS_REF_RELEASE(retval);
  335. }
  336. return retval;
  337. }
  338. StreamCoder *
  339. StreamCoder::make(Direction direction, AVCodecContext * codecCtx,
  340. AVCodec* avCodec, Stream* stream)
  341. {
  342. StreamCoder *retval = 0;
  343. RefPointer<Codec> codec;
  344. if (codecCtx)
  345. {
  346. try
  347. {
  348. retval = StreamCoder::make();
  349. if (readyAVContexts(
  350. direction,
  351. retval,
  352. stream,
  353. 0,
  354. codecCtx,
  355. avCodec) < 0)
  356. throw std::runtime_error("could not initialize codec");
  357. }
  358. catch (std::exception &e)
  359. {
  360. VS_REF_RELEASE(retval);
  361. throw e;
  362. }
  363. }
  364. return retval;
  365. }
  366. IStream*
  367. StreamCoder::getStream()
  368. {
  369. // Acquire for the caller.
  370. VS_REF_ACQUIRE(mStream);
  371. return mStream;
  372. }
  373. Codec *
  374. StreamCoder::getCodec()
  375. {
  376. return mCodec ? mCodec.get() : 0;
  377. }
  378. ICodec::Type
  379. StreamCoder::getCodecType()
  380. {
  381. ICodec::Type retval = ICodec::CODEC_TYPE_UNKNOWN;
  382. if (mCodecContext)
  383. {
  384. retval = (ICodec::Type) mCodecContext->codec_type;
  385. }
  386. else
  387. {
  388. VS_LOG_WARN("Attempt to get CodecType from uninitialized StreamCoder");
  389. }
  390. return retval;
  391. }
  392. ICodec::ID
  393. StreamCoder::getCodecID()
  394. {
  395. ICodec::ID retval = ICodec::CODEC_ID_NONE;
  396. if (mCodecContext)
  397. {
  398. retval = (ICodec::ID) mCodecContext->codec_id;
  399. }
  400. else
  401. {
  402. VS_LOG_WARN("Attempt to get CodecID from uninitialized StreamCoder");
  403. }
  404. return retval;
  405. }
  406. int32_t
  407. StreamCoder::getBitRate()
  408. {
  409. return (mCodecContext ? mCodecContext->bit_rate : -1);
  410. }
  411. void
  412. StreamCoder::setBitRate(int32_t val)
  413. {
  414. if (mCodecContext && !mOpened)
  415. mCodecContext->bit_rate = val;
  416. }
  417. int32_t
  418. StreamCoder::getBitRateTolerance()
  419. {
  420. return (mCodecContext ? mCodecContext->bit_rate_tolerance : -1);
  421. }
  422. void
  423. StreamCoder::setBitRateTolerance(int32_t val)
  424. {
  425. if (mCodecContext && !mOpened)
  426. mCodecContext->bit_rate_tolerance = val;
  427. }
  428. int32_t
  429. StreamCoder::getHeight()
  430. {
  431. return (mCodecContext ? mCodecContext->height : -1);
  432. }
  433. void
  434. StreamCoder::setHeight(int32_t val)
  435. {
  436. if (mCodecContext && !mOpened)
  437. mCodecContext->height = val;
  438. }
  439. int32_t
  440. StreamCoder::getWidth()
  441. {
  442. return (mCodecContext ? mCodecContext->width : -1);
  443. }
  444. void
  445. StreamCoder::setWidth(int32_t val)
  446. {
  447. if (mCodecContext && !mOpened)
  448. mCodecContext->width = val;
  449. }
  450. IRational*
  451. StreamCoder::getTimeBase()
  452. {
  453. // we make a new value and return it; caller must
  454. // release.
  455. IRational *retval = 0;
  456. // annoyingly, some codec contexts will NOT have
  457. // a timebase... so we take it from stream then.
  458. if (mCodecContext && mCodecContext->time_base.den
  459. && mCodecContext->time_base.num)
  460. {
  461. retval = Rational::make(&mCodecContext->time_base);
  462. }
  463. else if (mAutomaticallyStampPacketsForStream)
  464. {
  465. retval = mStream ? mStream->getTimeBase() : 0;
  466. }
  467. return retval;
  468. }
  469. void
  470. StreamCoder::setTimeBase(IRational* src)
  471. {
  472. if (mCodecContext && src && !mOpened)
  473. {
  474. mCodecContext->time_base.num = src->getNumerator();
  475. mCodecContext->time_base.den = src->getDenominator();
  476. }
  477. else
  478. {
  479. VS_LOG_INFO("Failed to setTimeBase on StreamCoder");
  480. }
  481. }
  482. int64_t
  483. StreamCoder::getNextPredictedPts()
  484. {
  485. return mFakeNextPts;
  486. }
  487. IRational*
  488. StreamCoder::getFrameRate()
  489. {
  490. return (mStream ? mStream->getFrameRate() : 0);
  491. }
  492. void
  493. StreamCoder::setFrameRate(IRational* src)
  494. {
  495. if (mStream && !mOpened)
  496. mStream->setFrameRate(src);
  497. }
  498. int32_t
  499. StreamCoder::getNumPicturesInGroupOfPictures()
  500. {
  501. return (mCodecContext ? mCodecContext->gop_size : -1);
  502. }
  503. void
  504. StreamCoder::setNumPicturesInGroupOfPictures(int32_t val)
  505. {
  506. if (mCodecContext && !mOpened)
  507. mCodecContext->gop_size = val;
  508. }
  509. IPixelFormat::Type
  510. StreamCoder::getPixelType()
  511. {
  512. IPixelFormat::Type retval = IPixelFormat::NONE;
  513. int32_t type = 0;
  514. if (mCodecContext)
  515. {
  516. retval = (IPixelFormat::Type) mCodecContext->pix_fmt;
  517. // little check here to see if we have an undefined int32_t.
  518. type = (int32_t) retval;
  519. if (type != mCodecContext->pix_fmt) {
  520. VS_LOG_ERROR("Undefined pixel format type: %d", mCodecContext->pix_fmt);
  521. retval = IPixelFormat::NONE;
  522. }
  523. }
  524. return retval;
  525. }
  526. void
  527. StreamCoder::setPixelType(IPixelFormat::Type type)
  528. {
  529. if (mCodecContext && !mOpened)
  530. {
  531. mCodecContext->pix_fmt = (enum PixelFormat) type;
  532. }
  533. }
  534. int32_t
  535. StreamCoder::getSampleRate()
  536. {
  537. return (mCodecContext ? mCodecContext->sample_rate : -1);
  538. }
  539. void
  540. StreamCoder::setSampleRate(int32_t val)
  541. {
  542. if (mCodecContext && !mOpened && val > 0)
  543. mCodecContext->sample_rate = val;
  544. }
  545. IAudioSamples::Format
  546. StreamCoder::getSampleFormat()
  547. {
  548. return (IAudioSamples::Format) (mCodecContext ? mCodecContext->sample_fmt
  549. : -1);
  550. }
  551. void
  552. StreamCoder::setSampleFormat(IAudioSamples::Format val)
  553. {
  554. if (mCodecContext && !mOpened && val > 0)
  555. mCodecContext->sample_fmt = (enum AVSampleFormat) val;
  556. }
  557. int32_t
  558. StreamCoder::getChannels()
  559. {
  560. return (mCodecContext ? mCodecContext->channels : -1);
  561. }
  562. void
  563. StreamCoder::setChannels(int32_t val)
  564. {
  565. if (mCodecContext && !mOpened && val > 0)
  566. mCodecContext->channels = val;
  567. }
  568. int32_t
  569. StreamCoder::getGlobalQuality()
  570. {
  571. return (mCodecContext ? mCodecContext->global_quality : FF_LAMBDA_MAX);
  572. }
  573. void
  574. StreamCoder::setGlobalQuality(int32_t newQuality)
  575. {
  576. if (newQuality < 0 || newQuality > FF_LAMBDA_MAX)
  577. newQuality = FF_LAMBDA_MAX;
  578. if (mCodecContext)
  579. mCodecContext->global_quality = newQuality;
  580. }
  581. int32_t
  582. StreamCoder::getFlags()
  583. {
  584. return (mCodecContext ? mCodecContext->flags : 0);
  585. }
  586. void
  587. StreamCoder::setFlags(int32_t newFlags)
  588. {
  589. if (mCodecContext)
  590. mCodecContext->flags = newFlags;
  591. }
  592. bool
  593. StreamCoder::getFlag(IStreamCoder::Flags flag)
  594. {
  595. bool result = false;
  596. if (mCodecContext)
  597. result = mCodecContext->flags & flag;
  598. return result;
  599. }
  600. void
  601. StreamCoder::setFlag(IStreamCoder::Flags flag, bool value)
  602. {
  603. if (mCodecContext)
  604. {
  605. if (value)
  606. {
  607. mCodecContext->flags |= flag;
  608. }
  609. else
  610. {
  611. mCodecContext->flags &= (~flag);
  612. }
  613. }
  614. }
  615. int32_t
  616. StreamCoder::open()
  617. {
  618. return open(0, 0);
  619. }
  620. int32_t
  621. StreamCoder::open(IMetaData* aOptions, IMetaData* aUnsetOptions)
  622. {
  623. int32_t retval = -1;
  624. AVDictionary* tmp=0;
  625. try
  626. {
  627. if (!mCodecContext)
  628. throw std::runtime_error("no codec context");
  629. if (!mCodec)
  630. {
  631. RefPointer<ICodec> codec = this->getCodec();
  632. // This should set mCodec and then release
  633. // the local reference.
  634. }
  635. if (!mCodec)
  636. throw std::runtime_error("no codec set for coder");
  637. // Time to set options
  638. if (aOptions) {
  639. MetaData* options = dynamic_cast<MetaData*>(aOptions);
  640. if (!options)
  641. throw new std::runtime_error("wow... who's passing us crap?");
  642. // make a copy of the data returned.
  643. av_dict_copy(&tmp, options->getDictionary(), 0);
  644. }
  645. // don't allow us to open a coder without a time base
  646. if (mDirection == ENCODING && mCodecContext->time_base.num == 0)
  647. {
  648. if (this->getCodecType() == ICodec::CODEC_TYPE_AUDIO)
  649. {
  650. if (mCodecContext->sample_rate > 0)
  651. {
  652. mCodecContext->time_base.num = 1;
  653. mCodecContext->time_base.den = mCodecContext->sample_rate;
  654. }
  655. else
  656. {
  657. throw std::runtime_error("no sample rate set on coder");
  658. }
  659. }
  660. else
  661. throw std::runtime_error("no timebase set on coder");
  662. }
  663. // Fix for issue #14: http://code.google.com/p/xuggle/issues/detail?id=14
  664. if (mStream)
  665. {
  666. RefPointer<IContainer> container = mStream->getContainer();
  667. if (container)
  668. {
  669. RefPointer<IContainerFormat> format = container->getContainerFormat();
  670. if (format && mDirection == ENCODING && format->getOutputFlag(
  671. IContainerFormat::FLAG_GLOBALHEADER))
  672. {
  673. this->setFlag(FLAG_GLOBAL_HEADER, true);
  674. }
  675. }
  676. }
  677. {
  678. /*
  679. * This is a very annoying bug. FFmpeg will NOT find sub-codec options
  680. * if AVCodecContext->codec is not set to a non-null value, but
  681. * avcodec_open2 will fail if it is set null. To allow users to set
  682. * options easily prior to opening the AVCodecContext, we stash the
  683. * value we had been using, and we check after the open call and log
  684. * an error if it changed for some reason.
  685. */
  686. AVCodec* cachedCodec = mCodecContext->codec;
  687. mCodecContext->codec = 0;
  688. retval = avcodec_open2(mCodecContext, mCodec->getAVCodec(), &tmp);
  689. if (retval >= 0 && cachedCodec != 0 && cachedCodec != mCodecContext->codec)
  690. {
  691. VS_LOG_ERROR("When opening StreamCoder the codec was changed by FFmpeg. This is not good");
  692. }
  693. if (retval < 0)
  694. {
  695. mCodecContext->codec = cachedCodec;
  696. throw std::runtime_error("could not open codec");
  697. }
  698. }
  699. mOpened = true;
  700. mNumDroppedFrames = 0;
  701. mSamplesCoded = mSamplesForEncoding = mLastExternallySetTimeStamp = 0;
  702. mFakeCurrPts = mFakeNextPts = mLastPtsEncoded = Global::NO_PTS;
  703. for(uint32_t i = 0; i < sizeof(mPtsBuffer)/sizeof(mPtsBuffer[0]); i++)
  704. {
  705. mPtsBuffer[i] = Global::NO_PTS;
  706. }
  707. // Do any post open initialization here.
  708. if (this->getCodecType() == ICodec::CODEC_TYPE_AUDIO)
  709. {
  710. int32_t frame_bytes = getAudioFrameSize() * getChannels()
  711. * IAudioSamples::findSampleBitDepth(
  712. (IAudioSamples::Format) mCodecContext->sample_fmt) / 8;
  713. if (frame_bytes <= 0)
  714. frame_bytes = AVCODEC_MAX_AUDIO_FRAME_SIZE;
  715. if (!mAudioFrameBuffer || mAudioFrameBuffer->getBufferSize()
  716. < frame_bytes)
  717. // Re-create it.
  718. mAudioFrameBuffer = IBuffer::make(this, frame_bytes);
  719. mBytesInFrameBuffer = 0;
  720. }
  721. if (aUnsetOptions)
  722. {
  723. MetaData* unsetOptions = dynamic_cast<MetaData*>(aUnsetOptions);
  724. if (!unsetOptions)
  725. throw std::runtime_error("really... seriously?");
  726. unsetOptions->copy(tmp);
  727. }
  728. }
  729. catch (std::bad_alloc & e)
  730. {
  731. throw e;
  732. }
  733. catch (std::exception & e)
  734. {
  735. VS_LOG_WARN("Error: %s", e.what());
  736. retval = -1;
  737. }
  738. if (tmp)
  739. av_dict_free(&tmp);
  740. return retval;
  741. }
  742. int32_t
  743. StreamCoder::close()
  744. {
  745. int32_t retval = -1;
  746. if (mCodecContext && mOpened)
  747. {
  748. retval = avcodec_close(mCodecContext);
  749. mOpened = false;
  750. }
  751. mBytesInFrameBuffer = 0;
  752. return retval;
  753. }
  754. int32_t
  755. StreamCoder::decodeAudio(IAudioSamples *pOutSamples, IPacket *pPacket,
  756. int32_t startingByte)
  757. {
  758. int32_t retval = -1;
  759. AudioSamples *samples = dynamic_cast<AudioSamples*> (pOutSamples);
  760. Packet* packet = dynamic_cast<Packet*> (pPacket);
  761. if (samples)
  762. // reset the samples
  763. samples->setComplete(false, 0, getSampleRate(), getChannels(),
  764. (IAudioSamples::Format) mCodecContext->sample_fmt, Global::NO_PTS);
  765. if (!samples) {
  766. VS_LOG_WARN("Attempting to decode when not ready; no samples");
  767. return retval;
  768. }
  769. if (!packet) {
  770. VS_LOG_WARN("Attempting to decode when not ready; no packet");
  771. return retval;
  772. }
  773. if (!mOpened) {
  774. VS_LOG_WARN("Attempting to decode when not ready; codec not opened");
  775. return retval;
  776. }
  777. if (!mCodecContext) {
  778. VS_LOG_WARN("Attempting to decode when not ready; internal context not allocated");
  779. return retval;
  780. }
  781. if (mDirection != DECODING) {
  782. VS_LOG_WARN("Attempting to decode when not ready; StreamCoder is set to encode, not decode");
  783. return retval;
  784. }
  785. if (!mCodec || !mCodec->canDecode()) {
  786. VS_LOG_WARN("Attempting to decode when not ready; codec set cannot decode");
  787. return retval;
  788. }
  789. if (getCodecType() != ICodec::CODEC_TYPE_AUDIO) {
  790. VS_LOG_WARN("Attempting to decode when not ready; codec set is not an audio codec");
  791. return retval;
  792. }
  793. int outBufSize = 0;
  794. int32_t inBufSize = 0;
  795. // When decoding with FFMPEG, ffmpeg needs the sample buffer
  796. // to be at least this long.
  797. samples->ensureCapacity(AVCODEC_MAX_AUDIO_FRAME_SIZE);
  798. outBufSize = samples->getMaxBufferSize();
  799. inBufSize = packet->getSize() - startingByte;
  800. if (inBufSize > 0 && outBufSize > 0)
  801. {
  802. RefPointer<IBuffer> buffer = packet->getData();
  803. uint8_t * inBuf = 0;
  804. int16_t * outBuf = 0;
  805. VS_ASSERT(buffer, "no buffer in packet!");
  806. if (buffer)
  807. inBuf = (uint8_t*) buffer->getBytes(startingByte, inBufSize);
  808. outBuf = samples->getRawSamples(0);
  809. VS_ASSERT(inBuf, "no in buffer");
  810. VS_ASSERT(outBuf, "no out buffer");
  811. if (outBuf && inBuf)
  812. {
  813. VS_LOG_TRACE("Attempting decodeAudio(%p, %p, %d, %p, %d);",
  814. mCodecContext,
  815. outBuf,
  816. outBufSize,
  817. inBuf,
  818. inBufSize);
  819. AVPacket pkt;
  820. av_init_packet(&pkt);
  821. if (packet && packet->getAVPacket())
  822. pkt = *packet->getAVPacket();
  823. // copy in our buffer
  824. pkt.data = inBuf;
  825. pkt.size = inBufSize;
  826. mCodecContext->reordered_opaque = packet->getPts();
  827. {
  828. AVFrame frame;
  829. int got_frame = 0;
  830. avcodec_get_frame_defaults(&frame);
  831. retval = avcodec_decode_audio4(mCodecContext, &frame, &got_frame, &pkt);
  832. // the API for decoding audio changed ot support planar audio and we
  833. // need to back-port
  834. if (retval >= 0 && got_frame) {
  835. int ch, plane_size;
  836. int planar = av_sample_fmt_is_planar(mCodecContext->sample_fmt);
  837. int data_size = av_samples_get_buffer_size(&plane_size,
  838. mCodecContext->channels,
  839. frame.nb_samples,
  840. mCodecContext->sample_fmt,
  841. 1);
  842. if (outBufSize < data_size) {
  843. VS_LOG_ERROR("Output buffer is not large enough; no audio actually returned");
  844. outBufSize = 0;
  845. } else {
  846. memcpy(outBuf, frame.extended_data[0], plane_size);
  847. if (planar && mCodecContext->channels > 1) {
  848. uint8_t *out = ((uint8_t*)outBuf)+plane_size;
  849. for(ch = 1; ch < mCodecContext->channels; ch++) {
  850. memcpy(out, frame.extended_data[ch], plane_size);
  851. out += plane_size;
  852. }
  853. }
  854. outBufSize = data_size;
  855. }
  856. }
  857. }
  858. VS_LOG_TRACE("Finished %d decodeAudio(%p, %p, %d, %p, %d);",
  859. retval,
  860. mCodecContext,
  861. outBuf,
  862. outBufSize,
  863. inBuf,
  864. inBufSize);
  865. }
  866. if (retval >= 0)
  867. {
  868. // outBufSize is an In-Out parameter
  869. if (outBufSize < 0)
  870. // this can happen for some MPEG decoders
  871. outBufSize = 0;
  872. IAudioSamples::Format format =
  873. (IAudioSamples::Format) mCodecContext->sample_fmt;
  874. int32_t bytesPerSample = (IAudioSamples::findSampleBitDepth(format) / 8
  875. * getChannels());
  876. int32_t numSamples = outBufSize / bytesPerSample;
  877. // The audio decoder doesn't set a PTS, so we need to manufacture one.
  878. RefPointer<IRational> timeBase =
  879. this->mStream ? this->mStream->getTimeBase() : 0;
  880. if (!timeBase)
  881. timeBase = this->getTimeBase();
  882. int64_t packetTs = packet->getPts();
  883. if (packetTs == Global::NO_PTS)
  884. packetTs = packet->getDts();
  885. if (packetTs == Global::NO_PTS && mFakeNextPts == Global::NO_PTS)
  886. {
  887. // the container doesn't have time stamps; assume we start
  888. // at zero
  889. VS_LOG_TRACE("Setting fake pts to 0");
  890. mFakeNextPts = 0;
  891. }
  892. if (packetTs != Global::NO_PTS)
  893. {
  894. // The packet had a valid stream, and a valid time base
  895. if (timeBase->getNumerator() != 0 && timeBase->getDenominator() != 0)
  896. {
  897. int64_t tsDelta = Global::NO_PTS;
  898. if (mFakeNextPts != Global::NO_PTS)
  899. {
  900. int64_t fakeTsInStreamTimeBase = Global::NO_PTS;
  901. // rescale our fake into the time base of stream
  902. fakeTsInStreamTimeBase = timeBase->rescale(mFakeNextPts,
  903. mFakePtsTimeBase.value());
  904. tsDelta = fakeTsInStreamTimeBase - packetTs;
  905. }
  906. // now, compare it to our internal value; if our internally calculated value
  907. // is within 1 tick of the packet's time stamp (in the packet's time base),
  908. // then we're probably right;
  909. // otherwise, we should reset the stream's fake time stamp based on this
  910. // packet
  911. if (mFakeNextPts != Global::NO_PTS && (tsDelta >= -1 && tsDelta
  912. <= 1))
  913. {
  914. // we're the right value; keep our fake next pts
  915. VS_LOG_TRACE("Keeping mFakeNextPts: %lld", mFakeNextPts);
  916. }
  917. else
  918. {
  919. // rescale to our internal timebase
  920. int64_t packetTsInMicroseconds = mFakePtsTimeBase->rescale(
  921. packetTs, timeBase.value());
  922. VS_LOG_TRACE("%p Gap in audio (%lld); Resetting calculated ts from %lld to %lld",
  923. this,
  924. tsDelta,
  925. mFakeNextPts,
  926. packetTsInMicroseconds);
  927. mLastExternallySetTimeStamp = packetTsInMicroseconds;
  928. mSamplesCoded = 0;
  929. mFakeNextPts = mLastExternallySetTimeStamp;
  930. }
  931. }
  932. }
  933. // Use the last value of the next pts
  934. mFakeCurrPts = mFakeNextPts;
  935. // adjust our next Pts pointer
  936. if (numSamples > 0)
  937. {
  938. mSamplesCoded += numSamples;
  939. mFakeNextPts = mLastExternallySetTimeStamp
  940. + IAudioSamples::samplesToDefaultPts(mSamplesCoded,
  941. getSampleRate());
  942. }
  943. // copy the packet PTS
  944. samples->setComplete(numSamples > 0, numSamples, getSampleRate(),
  945. getChannels(), format, mFakeCurrPts);
  946. }
  947. }
  948. return retval;
  949. }
  950. int32_t
  951. StreamCoder::decodeVideo(IVideoPicture *pOutFrame, IPacket *pPacket,
  952. int32_t byteOffset)
  953. {
  954. int32_t retval = -1;
  955. VideoPicture* frame = dynamic_cast<VideoPicture*> (pOutFrame);
  956. Packet* packet = dynamic_cast<Packet*> (pPacket);
  957. if (frame)
  958. // reset the frame
  959. frame->setComplete(false, IPixelFormat::NONE, -1, -1, mFakeCurrPts);
  960. if (!frame) {
  961. VS_LOG_WARN("Attempting to decode when not ready; no frame");
  962. return retval;
  963. }
  964. if (!packet) {
  965. VS_LOG_WARN("Attempting to decode when not ready; no packet");
  966. return retval;
  967. }
  968. if (!mOpened) {
  969. VS_LOG_WARN("Attempting to decode when not ready; codec not opened");
  970. return retval;
  971. }
  972. if (!mCodecContext) {
  973. VS_LOG_WARN("Attempting to decode when not ready; internal context not allocated");
  974. return retval;
  975. }
  976. if (mDirection != DECODING) {
  977. VS_LOG_WARN("Attempting to decode when not ready; StreamCoder is set to encode, not decode");
  978. return retval;
  979. }
  980. if (!mCodec || !mCodec->canDecode()) {
  981. VS_LOG_WARN("Attempting to decode when not ready; codec set cannot decode");
  982. return retval;
  983. }
  984. if (getCodecType() != ICodec::CODEC_TYPE_VIDEO) {
  985. VS_LOG_WARN("Attempting to decode when not ready; codec set is not a video codec");
  986. return retval;
  987. }
  988. AVFrame *avFrame = avcodec_alloc_frame();
  989. if (avFrame)
  990. {
  991. RefPointer<IBuffer> buffer = packet->getData();
  992. int frameFinished = 0;
  993. int32_t inBufSize = 0;
  994. uint8_t * inBuf = 0;
  995. inBufSize = packet->getSize() - byteOffset;
  996. VS_ASSERT(buffer, "no buffer in packet?");
  997. if (buffer)
  998. inBuf = (uint8_t*) buffer->getBytes(byteOffset, inBufSize);
  999. VS_ASSERT(inBuf, "incorrect size or no data in packet");
  1000. if (inBufSize > 0 && inBuf)
  1001. {
  1002. VS_LOG_TRACE("Attempting decodeVideo(%p, %p, %d, %p, %d);",
  1003. mCodecContext,
  1004. avFrame,
  1005. frameFinished,
  1006. inBuf,
  1007. inBufSize);
  1008. AVPacket pkt;
  1009. av_init_packet(&pkt);
  1010. if (packet && packet->getAVPacket())
  1011. pkt = *packet->getAVPacket();
  1012. // copy in our buffer
  1013. pkt.data = inBuf;
  1014. pkt.size = inBufSize;
  1015. mCodecContext->reordered_opaque = packet->getPts();
  1016. retval = avcodec_decode_video2(mCodecContext, avFrame, &frameFinished,
  1017. &pkt);
  1018. VS_LOG_TRACE("Finished %d decodeVideo(%p, %p, %d, %p, %d);",
  1019. retval,
  1020. mCodecContext,
  1021. avFrame,
  1022. frameFinished,
  1023. inBuf,
  1024. inBufSize);
  1025. if (frameFinished)
  1026. {
  1027. // copy FFMPEG's buffer into our buffer; don't try to get efficient
  1028. // and reuse the buffer FFMPEG is using; in order to allow our
  1029. // buffers to be thread safe, we must do a copy here.
  1030. frame->copyAVFrame(avFrame, getPixelType(), getWidth(), getHeight());
  1031. RefPointer<IRational> timeBase = 0;
  1032. timeBase = this->mStream ? this->mStream->getTimeBase() : 0;
  1033. if (!timeBase)
  1034. timeBase = this->getTimeBase();
  1035. int64_t packetTs = avFrame->reordered_opaque;
  1036. // if none, assume this packet's decode time, since
  1037. // it's presentation time should have been in reordered_opaque
  1038. if (packetTs == Global::NO_PTS)
  1039. packetTs = packet->getDts();
  1040. if (packetTs != Global::NO_PTS)
  1041. {
  1042. if (timeBase->getNumerator() != 0)
  1043. {
  1044. // The decoder set a PTS, so we let it override us
  1045. int64_t nextPts = mFakePtsTimeBase->rescale(packetTs,
  1046. timeBase.value());
  1047. // some youtube videos incorrectly return a packet
  1048. // with the wrong re-ordered opaque setting. this
  1049. // detects that and uses the PTS from the packet instead.
  1050. // See: http://code.google.com/p/xuggle/issues/detail?id=165
  1051. // in this way we enforce that timestamps are always
  1052. // increasing
  1053. if (nextPts < mFakeNextPts && packet->getPts() != Global::NO_PTS)
  1054. nextPts = mFakePtsTimeBase->rescale(packet->getPts(),
  1055. timeBase.value());
  1056. mFakeNextPts = nextPts;
  1057. }
  1058. }
  1059. // Use the last value of the next pts
  1060. mFakeCurrPts = mFakeNextPts;
  1061. double frameDelay = av_rescale(timeBase->getNumerator(),
  1062. AV_TIME_BASE, timeBase->getDenominator());
  1063. frameDelay += avFrame->repeat_pict * (frameDelay * 0.5);
  1064. // adjust our next Pts pointer
  1065. mFakeNextPts += (int64_t) frameDelay;
  1066. // VS_LOG_DEBUG("frame complete: %s; pts: %lld; packet ts: %lld; opaque ts: %lld; tb: %ld/%ld",
  1067. // (frameFinished ? "yes" : "no"),
  1068. // mFakeCurrPts,
  1069. // (packet ? packet->getDts() : 0),
  1070. // packetTs,
  1071. // timeBase->getNumerator(),
  1072. // timeBase->getDenominator()
  1073. // );
  1074. }
  1075. frame->setComplete(frameFinished, this->getPixelType(),
  1076. this->getWidth(), this->getHeight(), mFakeCurrPts);
  1077. }
  1078. av_free(avFrame);
  1079. }
  1080. return retval;
  1081. }
  1082. int32_t
  1083. StreamCoder::encodeVideo(IPacket *pOutPacket, IVideoPicture *pFrame,
  1084. int32_t suggestedBufferSize)
  1085. {
  1086. int32_t retval = -1;
  1087. VideoPicture *frame = dynamic_cast<VideoPicture*> (pFrame);
  1088. Packet *packet = dynamic_cast<Packet*> (pOutPacket);
  1089. RefPointer<IBuffer> encodingBuffer;
  1090. try
  1091. {
  1092. if (packet)
  1093. packet->reset();
  1094. if (getCodecType() != ICodec::CODEC_TYPE_VIDEO)
  1095. throw std::runtime_error(
  1096. "Attempting to encode video with non video coder");
  1097. if (frame && frame->getPixelType() != this->getPixelType())
  1098. throw std::runtime_error(
  1099. "picture is not of the same PixelType as this Coder expected");
  1100. if (frame && frame->getWidth() != this->getWidth())
  1101. throw std::runtime_error("picture is not of the same width as this Coder");
  1102. if (frame && frame->getHeight() != this->getHeight())
  1103. throw std::runtime_error(
  1104. "picture is not of the same height as this Coder");
  1105. if (mDirection != ENCODING)
  1106. throw std::runtime_error("Decoding StreamCoder not valid for encoding");
  1107. if (!mCodec)
  1108. throw std::runtime_error("Codec not set");
  1109. if (!mCodec->canEncode())
  1110. throw std::runtime_error("Codec cannot be used to encode");
  1111. if (mCodecContext && mOpened && mDirection == ENCODING && packet)
  1112. {
  1113. uint8_t* buf = 0;
  1114. uint32_t bufLen = 0;
  1115. // First, get the right buffer size.
  1116. if (suggestedBufferSize <= 0)
  1117. {
  1118. if (frame)
  1119. {
  1120. suggestedBufferSize = frame->getSize();
  1121. }
  1122. else
  1123. {
  1124. suggestedBufferSize = avpicture_get_size(
  1125. (PixelFormat) getPixelType(), getWidth(), getHeight());
  1126. }
  1127. }
  1128. VS_ASSERT(suggestedBufferSize> 0, "no buffer size in input frame");
  1129. suggestedBufferSize = FFMAX(suggestedBufferSize, FF_MIN_BUFFER_SIZE);
  1130. retval = packet->allocateNewPayload(suggestedBufferSize);
  1131. if (retval >= 0)
  1132. {
  1133. encodingBuffer = packet->getData();
  1134. }
  1135. if (encodingBuffer)
  1136. {
  1137. buf = (uint8_t*) encodingBuffer->getBytes(0, suggestedBufferSize);
  1138. bufLen = encodingBuffer->getBufferSize();
  1139. }
  1140. if (buf && bufLen)
  1141. {
  1142. // Change the PTS in our frame to the timebase of the encoded stream
  1143. RefPointer<IRational> thisTimeBase = getTimeBase();
  1144. /*
  1145. * We make a copy of the AVFrame object and explicitly copy
  1146. * over the values that we know encoding cares about.
  1147. *
  1148. * This is because often some programs decode into an VideoPicture
  1149. * and just want to pass that to encodeVideo. If we just
  1150. * leave the values that Ffmpeg had in the AVFrame during
  1151. * decoding, strange errors can result.
  1152. *
  1153. * Plus, this forces us to KNOW what we're passing into the encoder.
  1154. */
  1155. AVFrame* avFrame = 0;
  1156. bool dropFrame = false;
  1157. if (frame)
  1158. {
  1159. avFrame = avcodec_alloc_frame();
  1160. if (!avFrame)
  1161. throw std::bad_alloc();
  1162. frame->fillAVFrame(avFrame);
  1163. // convert into the time base that this coder wants
  1164. // to output in
  1165. int64_t codecTimeBasePts = thisTimeBase->rescale(frame->getPts(),
  1166. mFakePtsTimeBase.value(), IRational::ROUND_DOWN);
  1167. if (mLastPtsEncoded != Global::NO_PTS)
  1168. {
  1169. // adjust for rounding;
  1170. // fixes http://code.google.com/p/xuggle/issues/detail?id=180
  1171. if (codecTimeBasePts < mLastPtsEncoded)
  1172. {
  1173. VS_LOG_TRACE(
  1174. "Dropping frame with timestamp %lld (if coder supports higher time-base use that instead)",
  1175. frame->getPts());
  1176. dropFrame = true;
  1177. }
  1178. else if (codecTimeBasePts == mLastPtsEncoded)
  1179. {
  1180. // else we're close enough; increment by 1
  1181. ++codecTimeBasePts;
  1182. }
  1183. }
  1184. VS_LOG_TRACE("Rescaling ts: %lld to %lld (last: %lld) (from base %d/%d to %d/%d)",
  1185. frame->getPts(),
  1186. codecTimeBasePts,
  1187. mLastPtsEncoded,
  1188. mFakePtsTimeBase->getNumerator(),
  1189. mFakePtsTimeBase->getDenominator(),
  1190. thisTimeBase->getNumerator(),
  1191. thisTimeBase->getDenominator());
  1192. avFrame->pts = codecTimeBasePts;
  1193. if (!dropFrame)
  1194. mLastPtsEncoded = avFrame->pts;
  1195. }
  1196. if (!dropFrame)
  1197. {
  1198. VS_LOG_TRACE("Attempting encodeVideo(%p, %p, %d, %p)",
  1199. mCodecContext,
  1200. buf,
  1201. bufLen,
  1202. avFrame);
  1203. retval = avcodec_encode_video(mCodecContext, buf, bufLen, avFrame);
  1204. VS_LOG_TRACE("Finished %d encodeVideo(%p, %p, %d, %p)",
  1205. retval,
  1206. mCodecContext,
  1207. buf,
  1208. bufLen,
  1209. avFrame);
  1210. }
  1211. else
  1212. {
  1213. ++mNumDroppedFrames;
  1214. retval = 0;
  1215. }
  1216. if (retval >= 0)
  1217. {
  1218. int64_t dts = (avFrame ? mLastPtsEncoded : mLastPtsEncoded + 1);
  1219. int64_t duration = 1;
  1220. if (retval > 0) {
  1221. int32_t num = thisTimeBase->getNumerator();
  1222. int32_t den = thisTimeBase->getDenominator();
  1223. if (num*1000LL > den)
  1224. {
  1225. if (mCodecContext->coded_frame
  1226. && mCodecContext->coded_frame->repeat_pict)
  1227. {
  1228. num = num * (1+mCodecContext->coded_frame->repeat_pict);
  1229. }
  1230. }
  1231. duration = av_rescale(1,
  1232. num * (int64_t)den * mCodecContext->ticks_per_frame,
  1233. den * (int64_t) thisTimeBase->getNumerator());
  1234. // This will be zero if the Codec does not use b-frames;
  1235. // although we provide space for delaying up to the
  1236. // max H264 delay, in reality we only need delay by 1 tick.
  1237. int32_t delay = FFMAX(mCodecContext->has_b_frames,
  1238. !!mCodecContext->max_b_frames);
  1239. if (mCodecContext->coded_frame
  1240. && mCodecContext->coded_frame->pts != Global::NO_PTS)
  1241. {
  1242. int64_t pts = mCodecContext->coded_frame->pts;
  1243. mPtsBuffer[0] = pts;
  1244. int32_t i;
  1245. // If first time through set others to some 'sensible' defaults.
  1246. // If the first PTS is zero, this leads to starting negative
  1247. // dts values, but FFmpeg allows that so we do too.
  1248. for(i = 1; i < delay + 1 && mPtsBuffer[i] == Global::NO_PTS; i++)
  1249. mPtsBuffer[i] = pts + (i-delay-1)*duration;
  1250. // Order the PTS values in increasing order and the lowest
  1251. // one will magically be the DTS we should use for this packet.
  1252. for(i = 0; i < delay && mPtsBuffer[i] > mPtsBuffer[i+1]; i++)
  1253. FFSWAP(int64_t, mPtsBuffer[i], mPtsBuffer[i+1]);
  1254. dts = mPtsBuffer[0];
  1255. // VS_LOG_ERROR("type: %d; output: dts: %lld; pts: %lld",
  1256. // mCodecContext->coded_frame->pict_type,
  1257. // dts,
  1258. // pts);
  1259. }
  1260. }
  1261. setPacketParameters(
  1262. packet,
  1263. retval,
  1264. // if the last packet, increment the pts encoded
  1265. // by one
  1266. dts,
  1267. thisTimeBase.value(),
  1268. (mCodecContext->coded_frame ? mCodecContext->coded_frame->key_frame
  1269. : 0), duration);
  1270. }
  1271. if (avFrame)
  1272. av_free(avFrame);
  1273. }
  1274. }
  1275. else
  1276. {
  1277. VS_LOG_WARN("Attempting to encode when not ready");
  1278. }
  1279. }
  1280. catch (std::bad_alloc & e)
  1281. {
  1282. retval = -1;
  1283. throw e;
  1284. }
  1285. catch (std::exception & e)
  1286. {
  1287. VS_LOG_WARN("Got error: %s", e.what());
  1288. retval = -1;
  1289. }
  1290. return retval;
  1291. }
  1292. int32_t
  1293. StreamCoder::encodeAudio(IPacket * pOutPacket, IAudioSamples* pSamples,
  1294. uint32_t startingSample)
  1295. {
  1296. int32_t retval = -1;
  1297. AudioSamples *samples = dynamic_cast<AudioSamples*> (pSamples);
  1298. Packet *packet = dynamic_cast<Packet*> (pOutPacket);
  1299. RefPointer<IBuffer> encodingBuffer;
  1300. bool usingInternalFrameBuffer = false;
  1301. try
  1302. {
  1303. if (mDirection != ENCODING)
  1304. throw std::runtime_error("Decoding StreamCoder not valid for encoding");
  1305. if (!mCodec)
  1306. throw std::runtime_error("Codec not set");
  1307. if (!mCodec->canEncode()) {
  1308. std::string msg = "Codec cannot be used to encode: ";
  1309. msg += mCodec->getName();
  1310. throw std::runtime_error(msg);
  1311. }
  1312. if (!packet)
  1313. throw std::invalid_argument("Invalid packet to encode to");
  1314. // Zero out our packet
  1315. packet->reset();
  1316. if (!mCodecContext)
  1317. throw std::runtime_error("StreamCoder not initialized properly");
  1318. if (!mOpened)
  1319. throw std::runtime_error("StreamCoder not open");
  1320. if (getCodecType() != ICodec::CODEC_TYPE_AUDIO)
  1321. throw std::runtime_error(
  1322. "Attempting to encode audio with non audio coder");
  1323. if (!mAudioFrameBuffer)
  1324. throw std::runtime_error("Audio Frame Buffer not initialized");
  1325. // First, how many bytes do we need to encode a packet?
  1326. int32_t frameSize = 0;
  1327. int32_t frameBytes = 0;
  1328. int32_t availableSamples = (samples ? samples->getNumSamples()
  1329. - startingSample : 0);
  1330. int32_t samplesConsumed = 0;
  1331. int16_t *avSamples = (samples ? samples->getRawSamples(startingSample) : 0);
  1332. if (samples)
  1333. {
  1334. if (samples->getChannels() != getChannels())
  1335. throw std::invalid_argument(
  1336. "channels in sample do not match StreamCoder");
  1337. if (samples->getSampleRate() != getSampleRate())
  1338. throw std::invalid_argument(
  1339. "sample rate in sample does not match StreamCoder");
  1340. if (!samples->isComplete())
  1341. throw std::invalid_argument("input samples are not complete");
  1342. if (mFakeNextPts == Global::NO_PTS && samples->getTimeStamp()
  1343. != Global::NO_PTS)
  1344. mFakeNextPts = samples->getTimeStamp()
  1345. + IAudioSamples::samplesToDefaultPts(startingSample,
  1346. getSampleRate());
  1347. }
  1348. if (mFakeNextPts == Global::NO_PTS)
  1349. mFakeNextPts = 0;
  1350. if (availableSamples < 0 || (avSamples && availableSamples == 0))
  1351. throw std::invalid_argument(
  1352. "no bytes in buffer at specified starting sample");
  1353. int32_t bytesPerSample = (samples ? samples->getSampleSize()
  1354. : IAudioSamples::findSampleBitDepth(
  1355. (IAudioSamples::Format) mCodecContext->sample_fmt) / 8
  1356. * getChannels());
  1357. /*
  1358. * This gets tricky; There may be more audio samples passed to
  1359. * us than can fit in an audio frame, or there may be less.
  1360. *
  1361. * If less, we need to cache for a future call.
  1362. *
  1363. * If more, we need to just use what's needed, and let the caller
  1364. * know the number of samples we used.
  1365. *
  1366. * What happens when we exhaust all audio, but we still don't
  1367. * have enough to decode a frame? answer: the caller passes us
  1368. * NULL as the pInSamples, and we just silently drop the incomplete
  1369. * frame.
  1370. *
  1371. * To simplify coding here (and hence open for optimization if
  1372. * this ends up being a bottleneck), I always copy audio samples
  1373. * into a frame buffer, and then only encode from the frame buffer
  1374. * in this class.
  1375. */
  1376. frameSize = getAudioFrameSize();
  1377. frameBytes = frameSize * bytesPerSample;
  1378. // More error checking
  1379. VS_ASSERT(frameBytes <= mAudioFrameBuffer->getBufferSize(),
  1380. "did frameSize change from open?");
  1381. if (frameBytes > mAudioFrameBuffer->getBufferSize())
  1382. throw std::runtime_error("not enough memory in internal frame buffer");
  1383. VS_ASSERT(mBytesInFrameBuffer <= frameBytes,
  1384. "did frameSize change from open?");
  1385. if (frameBytes < mBytesInFrameBuffer)
  1386. throw std::runtime_error(
  1387. "too many bytes left over in internal frame buffer");
  1388. unsigned char * frameBuffer = (unsigned char*) mAudioFrameBuffer->getBytes(
  1389. 0, frameBytes);
  1390. if (!frameBuffer)
  1391. throw std::runtime_error("could not get internal frame buffer");
  1392. int32_t bytesToCopyToFrameBuffer = frameBytes - mBytesInFrameBuffer;
  1393. bytesToCopyToFrameBuffer = FFMIN(bytesToCopyToFrameBuffer,
  1394. availableSamples*bytesPerSample);
  1395. if (avSamples)
  1396. {
  1397. if (availableSamples >= frameSize && mBytesInFrameBuffer == 0)
  1398. {
  1399. VS_LOG_TRACE("audioEncode: Using passed in buffer: %d, %d, %d",
  1400. availableSamples, frameSize, mBytesInFrameBuffer);
  1401. frameBuffer = (unsigned char*) avSamples;
  1402. samplesConsumed = frameSize;
  1403. usingInternalFrameBuffer = false;
  1404. }
  1405. else
  1406. {
  1407. VS_LOG_TRACE("audioEncode: Using internal buffer: %d, %d, %d",
  1408. availableSamples, frameSize, mBytesInFrameBuffer);
  1409. memcpy(frameBuffer + mBytesInFrameBuffer, avSamples,
  1410. bytesToCopyToFrameBuffer);
  1411. mBytesInFrameBuffer += bytesToCopyToFrameBuffer;
  1412. samplesConsumed = bytesToCopyToFrameBuffer / bytesPerSample;
  1413. retval = samplesConsumed;
  1414. usingInternalFrameBuffer = true;
  1415. }
  1416. }
  1417. else
  1418. {
  1419. // drop everything in the frame buffer, and instead
  1420. // just pass a null buffer to the encoder.
  1421. // this should happen when the caller passes NULL for the
  1422. // input samples
  1423. frameBuffer = 0;
  1424. }
  1425. mSamplesForEncoding += samplesConsumed;
  1426. VS_LOG_TRACE("Consumed %ld for total of %lld",
  1427. samplesConsumed, mSamplesForEncoding);
  1428. if (!frameBuffer || !usingInternalFrameBuffer || mBytesInFrameBuffer
  1429. >= frameBytes)
  1430. {
  1431. // First, get the right buffer size.
  1432. int32_t bufferSize = frameBytes;
  1433. if (mCodecContext->codec->id == CODEC_ID_FLAC
  1434. || mCodecContext->codec->id == CODEC_ID_VORBIS)
  1435. {
  1436. // FLAC & VORBIS audio for some reason gives an error if your output buffer isn't
  1437. // over double the frame size, so we fake it here. This could be further optimized
  1438. // to only require an exact number, but this math is simpler and will always
  1439. // be large enough.
  1440. bufferSize = (64 + getAudioFrameSize() * (bytesPerSample + 1)) * 2;
  1441. }
  1442. VS_ASSERT(bufferSize> 0, "no buffer size in samples");
  1443. retval = packet->allocateNewPayload(bufferSize);
  1444. if (retval >= 0)
  1445. {
  1446. encodingBuffer = packet->getData();
  1447. }
  1448. uint8_t* buf = 0;
  1449. if (encodingBuffer)
  1450. {
  1451. buf = (uint8_t*) encodingBuffer->getBytes(0, bufferSize);
  1452. }
  1453. if (buf && bufferSize)
  1454. {
  1455. VS_LOG_TRACE("Attempting encodeAudio(%p, %p, %d, %p)",
  1456. mCodecContext,
  1457. buf,
  1458. bufferSize,
  1459. frameBuffer);
  1460. // This hack works around the fact that PCM's codecs
  1461. // calculate samples from buffer length, and sets
  1462. // the wrong frame size, but in
  1463. // reality we're always passing in 2 byte samples.
  1464. double pcmCorrection = 1.0;
  1465. switch (mCodecContext->codec->id)
  1466. {
  1467. case CODEC_ID_PCM_S32LE:
  1468. case CODEC_ID_PCM_S32BE:
  1469. case CODEC_ID_PCM_U32LE:
  1470. case CODEC_ID_PCM_U32BE:
  1471. pcmCorrection = 2.0;
  1472. break;
  1473. case CODEC_ID_PCM_S24LE:
  1474. case CODEC_ID_PCM_S24BE:
  1475. case CODEC_ID_PCM_U24LE:
  1476. case CODEC_ID_PCM_U24BE:
  1477. case CODEC_ID_PCM_S24DAUD:
  1478. pcmCorrection = 1.5;
  1479. break;
  1480. case CODEC_ID_PCM_S16LE:
  1481. case CODEC_ID_PCM_S16BE:
  1482. case CODEC_ID_PCM_U16LE:
  1483. case CODEC_ID_PCM_U16BE:
  1484. pcmCorrection = 1.0;
  1485. break;
  1486. case CODEC_ID_PCM_ALAW:
  1487. case CODEC_ID_PCM_MULAW:
  1488. case CODEC_ID_PCM_S8:
  1489. case CODEC_ID_PCM_U8:
  1490. case CODEC_ID_PCM_ZORK:
  1491. pcmCorrection = 0.5;
  1492. break;
  1493. default:
  1494. pcmCorrection = 1.0;
  1495. }
  1496. retval = avcodec_encode_audio(mCodecContext, buf, (int32_t) (bufferSize
  1497. * pcmCorrection), (int16_t*) frameBuffer);
  1498. VS_LOG_TRACE("Finished %d encodeAudio(%p, %p, %d, %p)",
  1499. retval,
  1500. mCodecContext,
  1501. buf,
  1502. bufferSize,
  1503. frameBuffer);
  1504. // regardless of what happened, nuke any data in our frame
  1505. // buffer.
  1506. mBytesInFrameBuffer = 0;
  1507. if (retval >= 0)
  1508. {
  1509. // and only do this if a packet is returned
  1510. if (retval > 0)
  1511. {
  1512. mSamplesCoded += frameSize;
  1513. // let's check to see if the time stamp of passed in
  1514. // samples (if any) are within tolerance of our expected
  1515. // time stamp. if not, this is most likely happening
  1516. // because the IStreamCoder's data source lost a packet.
  1517. // We will adjust our starting time stamps then for this new
  1518. // packet
  1519. mFakeCurrPts = mFakeNextPts;
  1520. if (samples && samples->getTimeStamp() != Global::NO_PTS)
  1521. {
  1522. int64_t samplesTs = samples->getTimeStamp()
  1523. + IAudioSamples::samplesToDefaultPts(startingSample
  1524. + samplesConsumed, getSampleRate());
  1525. int64_t samplesCached = mSamplesForEncoding - mSamplesCoded;
  1526. int64_t tsDelta = IAudioSamples::samplesToDefaultPts(
  1527. samplesCached, getSampleRate());
  1528. int64_t gap = sa

Large files files are truncated, but you can click here to view the full file