AVPKit
com::avpkit::core::StreamCoder Class Reference
Inheritance diagram for com::avpkit::core::StreamCoder:
Collaboration diagram for com::avpkit::core::StreamCoder:

Public Member Functions

virtual Direction getDirection ()
 Get the direction. More...
 
virtual IStreamgetStream ()
 The associated Stream we're working on. More...
 
virtual CodecgetCodec ()
 The Codec this StreamCoder will use. More...
 
virtual ICodec::Type getCodecType ()
 A short hand for getCodec().getType(). More...
 
virtual ICodec::ID getCodecID ()
 A short hand for getCodec().getID(). More...
 
virtual void setCodec (ICodec *)
 Set the Codec to the passed in Codec, discarding the old Codec if set. More...
 
virtual void setCodec (ICodec::ID)
 Look up a Codec based on the passed in ID, and then set it. More...
 
virtual void setCodecID (ICodec::ID id)
 Look up a Codec based on the passed in ID, and then set it. More...
 
virtual int32_t getBitRate ()
 The bit rate. More...
 
virtual void setBitRate (int32_t rate)
 When ENCODING, sets the bit rate to use. More...
 
virtual int32_t getBitRateTolerance ()
 The bit rate tolerance. More...
 
virtual void setBitRateTolerance (int32_t tolerance)
 When ENCODING set the bit rate tolerance. More...
 
virtual int32_t getHeight ()
 The height, in pixels. More...
 
virtual void setHeight (int32_t)
 Set the height, in pixels. More...
 
virtual int32_t getWidth ()
 The width, in pixels. More...
 
virtual void setWidth (int32_t)
 Set the width, in pixels. More...
 
virtual IRationalgetTimeBase ()
 Get the time base this stream will ENCODE in, or the time base we detect while DECODING. More...
 
virtual void setTimeBase (IRational *newTimeBase)
 Set the time base we'll use to ENCODE with. More...
 
virtual IRationalgetFrameRate ()
 Get the frame-rate the attached stream claims to be using when DECODING, or the frame-rate we'll claim we're using when ENCODING. More...
 
virtual void setFrameRate (IRational *newFrameRate)
 Set the frame rate we'll set in the headers of this stream while ENCODING. More...
 
virtual int32_t getNumPicturesInGroupOfPictures ()
 The the number of pictures in this Group of Pictures (GOP). More...
 
virtual void setNumPicturesInGroupOfPictures (int32_t gops)
 Set the GOPS on this stream. More...
 
virtual IPixelFormat::Type getPixelType ()
 For Video streams, get the Pixel Format in use by the stream. More...
 
virtual void setPixelType (IPixelFormat::Type pixelFmt)
 Set the pixel format to ENCODE with. More...
 
virtual int32_t getSampleRate ()
 Get the sample rate we use for this stream. More...
 
virtual void setSampleRate (int32_t sampleRate)
 Set the sample rate to use when ENCODING. More...
 
virtual int32_t getChannels ()
 Get the number of channels in this audio stream. More...
 
virtual void setChannels (int32_t channels)
 Set the number of channels to use when ENCODING. More...
 
virtual IAudioSamples::Format getSampleFormat ()
 Get the audio sample format. More...
 
virtual void setSampleFormat (IAudioSamples::Format aFormat)
 Set the sample format when ENCODING. More...
 
virtual int32_t getGlobalQuality ()
 Get the Global Quality setting this codec uses for video if a VideoPicture doesn't have a quality set. More...
 
virtual void setGlobalQuality (int32_t newQuality)
 Set the Global Quality to a new value. More...
 
virtual int32_t getFlags ()
 Get the flags associated with this codec. More...
 
virtual void setFlags (int32_t newFlags)
 Set the FFMPEG flags to use with this codec. More...
 
virtual bool getFlag (Flags flag)
 Get the setting for the specified flag. More...
 
virtual void setFlag (Flags flag, bool value)
 Set the flag. More...
 
virtual int32_t getAudioFrameSize ()
 For this stream, get the number of audio samples that are represented in a packet of information. More...
 
virtual int32_t open ()
 
virtual int32_t close ()
 Close a Codec that was opened on this StreamCoder. More...
 
virtual int32_t decodeAudio (IAudioSamples *pOutSamples, IPacket *packet, int32_t byteOffset)
 Decode this packet into pOutSamples. More...
 
virtual int32_t decodeVideo (IVideoPicture *pOutFrame, IPacket *packet, int32_t byteOffset)
 Decode this packet into pOutFrame. More...
 
virtual int32_t encodeVideo (IPacket *pOutPacket, IVideoPicture *pFrame, int32_t suggestedBufferSize)
 Encode the given frame using this StreamCoder. More...
 
virtual int32_t encodeAudio (IPacket *pOutPacket, IAudioSamples *pSamples, int32_t sampleToStartFrom)
 Encode the given samples using this StreamCoder. More...
 
virtual int64_t getNextPredictedPts ()
 For this stream, get the next Pts that we expect to decode. More...
 
virtual int32_t getCodecTag ()
 Returns the 4-byte FOURCC tag (Least Significant Byte first). More...
 
virtual void setCodecTag (int32_t)
 Set the 4-byte FOURCC tag for this coder. More...
 
virtual int32_t getNumProperties ()
 Returns the total number of settable properties on this object. More...
 
virtual IPropertygetPropertyMetaData (int32_t propertyNo)
 Returns the name of the numbered property. More...
 
virtual IPropertygetPropertyMetaData (const char *name)
 Returns the name of the numbered property. More...
 
virtual int32_t setProperty (const char *name, const char *value)
 Sets a property on this Object. More...
 
virtual int32_t setProperty (const char *name, double value)
 Looks up the property 'name' and sets the value of the property to 'value'. More...
 
virtual int32_t setProperty (const char *name, int64_t value)
 Looks up the property 'name' and sets the value of the property to 'value'. More...
 
virtual int32_t setProperty (const char *name, bool value)
 Looks up the property 'name' and sets the value of the property to 'value'. More...
 
virtual int32_t setProperty (const char *name, IRational *value)
 Looks up the property 'name' and sets the value of the property to 'value'. More...
 
virtual char * getPropertyAsString (const char *name)
 Gets a property on this Object. More...
 
virtual double getPropertyAsDouble (const char *name)
 Gets the value of this property, and returns as a double;. More...
 
virtual int64_t getPropertyAsLong (const char *name)
 Gets the value of this property, and returns as an long;. More...
 
virtual IRationalgetPropertyAsRational (const char *name)
 Gets the value of this property, and returns as an IRational;. More...
 
virtual bool getPropertyAsBoolean (const char *name)
 Gets the value of this property, and returns as a boolean. More...
 
virtual bool isOpen ()
 Returns true if this IStreamCoder is currently open. More...
 
virtual int32_t getDefaultAudioFrameSize ()
 Get the default audio frame size (in samples). More...
 
virtual void setDefaultAudioFrameSize (int32_t)
 Set the default audio frame size. More...
 
void setCodec (int32_t)
 
int32_t setStream (Stream *, bool assumeOnlyStream)
 
int32_t streamClosed (Stream *)
 
virtual int64_t getNumDroppedFrames ()
 Get the number of frames this StreamCoder had to drop to encode at the specified getTimeBase(). More...
 
virtual void setAutomaticallyStampPacketsForStream (bool value)
 Should the IStreamCoder automatically adjust time stamps on output packets for the IStream it is ultimately destined for. More...
 
virtual bool getAutomaticallyStampPacketsForStream ()
 Does this IStreamCoder automatically adjust time stamps on output packets for the IStream it is ultimately destined for. More...
 
virtual int32_t acquire ()
 Internal Only. More...
 
virtual int32_t release ()
 Internal Only. More...
 
virtual int32_t setExtraData (com::avpkit::ferry::IBuffer *src, int32_t offset, int32_t length, bool allocNew)
 Copies data from the given buffer into the extra-data area maintained by encoders. More...
 
virtual int32_t getExtraData (com::avpkit::ferry::IBuffer *dest, int32_t offset, int32_t maxBytesToCopy)
 Copies the current content of the extra-data buffer maintained by this codec (e.g. More...
 
virtual int32_t getExtraDataSize ()
 Gets the current number of bytes of data maintained in the coder extra-data area. More...
 
virtual CodecStandardsCompliance getStandardsCompliance ()
 Gets the current level of standards compliance. More...
 
virtual int32_t setStandardsCompliance (CodecStandardsCompliance compliance)
 Set the level of standards compliance. More...
 
virtual int32_t setHardwareDecoding (IPixelFormat::Type type, void *surface=NULL)
 Try to change current decoder to an HW decoder compatible with pixel format. More...
 
virtual void * getHardwareSurface ()
 
virtual int32_t open (IMetaData *options, IMetaData *unsetOptions)
 Open the codec with the given options. More...
 
virtual int32_t setProperty (IMetaData *valuesToSet, IMetaData *valuesNotFound)
 
- Public Member Functions inherited from com::avpkit::ferry::RefCounted
virtual RefCountedcopyReference ()
 Create a new Java object that refers to the same native object. More...
 
virtual int32_t getCurrentRefCount ()
 Return the current reference count on this object. More...
 
void setJavaAllocator (void *allocator)
 This method is public but not part of the standard API. More...
 
void * getJavaAllocator ()
 This method is public but not part of the standard API. More...
 

Static Public Member Functions

static StreamCodermake (Direction direction)
 This method creates a StreamCoder that is not tied to any container or stream.
 
static attribute_deprecated StreamCodermake (Direction direction, AVCodecContext *context, const AVCodec *, Stream *stream)
 This method creates a StreamCoder that is tied to a specific stream in a container.
 
static StreamCodermake (Direction direction, AVCodecParameters *codecpar, const AVCodec *, Stream *stream)
 
static StreamCodermake (Direction direction, IStreamCoder *copyCoder)
 
static StreamCodermake (Direction direction, Codec *codec)
 
static StreamCodermake (Direction direction, ICodec::ID id)
 
- Static Public Member Functions inherited from com::avpkit::core::IStreamCoder
static IStreamCodermake (Direction direction)
 
static IStreamCodermake (Direction direction, IStreamCoder *copyCoder)
 Creates a new IStreamCoder object by copying all the settings in copyCoder. More...
 
static IStreamCodermake (Direction direction, ICodec *codec)
 Create a standalone StreamCoder that can encode or decode data independent of the stream it is attached to. More...
 
static IStreamCodermake (Direction direction, ICodec::ID id)
 Create a standalone StreamCoder that can encode or decode data independent of the stream it is attached to. More...
 

Additional Inherited Members

- Public Types inherited from com::avpkit::core::IStreamCoder
enum  Direction { ENCODING , DECODING }
 The Direction in which this StreamCoder will work.
 
enum  Flags {
  FLAG_QSCALE =0x0002 , FLAG_4MV =0x0004 , FLAG_QPEL =0x0010 , FLAG_GMC =0x0020 ,
  FLAG_MV0 =0x0040 , FLAG_INPUT_PRESERVED =0x0100 , FLAG_PASS1 =0x0200 , FLAG_PASS2 =0x0400 ,
  FLAG_GRAY =0x2000 , FLAG_EMU_EDGE =0x4000 , FLAG_PSNR =0x8000 , FLAG_TRUNCATED =0x00010000 ,
  FLAG_NORMALIZE_AQP =0x00020000 , FLAG_INTERLACED_DCT =0x00040000 , FLAG_LOW_DELAY =0x00080000 , FLAG_GLOBAL_HEADER =0x00400000 ,
  FLAG_BITEXACT =0x00800000 , FLAG_AC_PRED =0x01000000 , FLAG_CBP_RD =0x04000000 , FLAG_QP_RD =0x08000000 ,
  FLAG_LOOP_FILTER =0x00000800 , FLAG_INTERLACED_ME =0x20000000 , FLAG_CLOSED_GOP =0x80000000 , FLAG2_FAST =0x00000001 ,
  FLAG2_STRICT_GOP =0x00000002 , FLAG2_NO_OUTPUT =0x00000004 , FLAG2_LOCAL_HEADER =0x00000008 , FLAG2_SKIP_RD =0x00004000 ,
  FLAG2_CHUNKS =0x00008000 , FLAG2_SHOW_ALL =0x00400000
}
 AVPKIT Flags that can be passed to the setFlag(Flags, bool) method. More...
 
enum  CodecStandardsCompliance {
  COMPLIANCE_VERY_STRICT =2 , COMPLIANCE_STRICT =1 , COMPLIANCE_NORMAL =0 , COMPLIANCE_UNOFFICIAL =-1 ,
  COMPLIANCE_EXPERIMENTAL =-2
}
 An enumeration of how strictly Codecs may follow the spec. More...
 
typedef enum com::avpkit::core::IStreamCoder::Direction Direction
 The Direction in which this StreamCoder will work.
 
typedef enum com::avpkit::core::IStreamCoder::Flags Flags
 AVPKIT Flags that can be passed to the setFlag(Flags, bool) method.
 
- Protected Member Functions inherited from com::avpkit::ferry::RefCounted
virtual void destroy ()
 This method is called by RefCounted objects when their Ref Count reaches zero and they are about to be destroyed.
 
- Protected Attributes inherited from com::avpkit::ferry::RefCounted
AtomicIntegermRefCount
 This is the internal reference count, represented as an AtomicInteger to make sure it is thread safe.
 
void * mAllocator
 Not part of public API.
 

Detailed Description

Definition at line 34 of file StreamCoder.h.

Member Function Documentation

◆ acquire()

int32_t com::avpkit::core::StreamCoder::acquire ( )
virtual

Internal Only.

DO NOT USE FROM JAVA.

Acquire a reference to this object. This increments the native internal ref count in native code by +1.

This method is called internally by Ferry in Java, and you should not call it without knowing what you are doing. But if you do call it, make sure you call release() once for each call you make to this method.

Returns
The refcount after the acquire. Note due to multi-threaded issues, you should not rely on this value, as it may change before the method returns to you.

Reimplemented from com::avpkit::ferry::RefCounted.

Definition at line 2067 of file StreamCoder.cpp.

2068 {
2069  int32_t retval = 0;
2070  retval = RefCounted::acquire();
2071  VS_LOG_TRACE("Acquired %p: %d", this, retval);
2072  return retval;
2073 }
virtual int32_t acquire()
Internal Only.
Definition: RefCounted.cpp:63

◆ close()

int32_t com::avpkit::core::StreamCoder::close ( )
virtual

Close a Codec that was opened on this StreamCoder.

Returns
>= 0 on success; < 0 on error.

Implements com::avpkit::core::IStreamCoder.

Definition at line 906 of file StreamCoder.cpp.

907 {
908  int32_t retval = -1;
909  if (mCodecContext && mOpened)
910  {
911  retval = avcodec_close(mCodecContext);
912  swr_free(&swrContext);
913  mOpened = false;
914  }
915  mBytesInFrameBuffer = 0;
916  return retval;
917 }

◆ decodeAudio()

int32_t com::avpkit::core::StreamCoder::decodeAudio ( IAudioSamples pOutSamples,
IPacket packet,
int32_t  byteOffset 
)
virtual

Decode this packet into pOutSamples.

It will try to fill up the audio samples object, starting from the byteOffset inside this packet.

The caller is responsible for allocating the IAudioSamples object. This function will overwrite any data in the samples object.

Note that the IAudioSamples object passed in must have a IAudioSamples#getMaxBufferSize() of at least 192kbytes. Sorry, but this requirement is imposed on us via FFmpeg. If the buffer is not large enough, this method will reallocate the underlying buffers to make them at least 192kbytes.

Parameters
pOutSamplesThe AudioSamples we decode to
packetThe packet we're attempting to decode from.
byteOffsetWhere in the packet payload to start decoding
Returns
number of bytes actually processed from the packet, or negative for error

Implements com::avpkit::core::IStreamCoder.

Definition at line 920 of file StreamCoder.cpp.

922 {
923  int32_t retval = -1;
924  AudioSamples *samples = static_cast<AudioSamples*> (pOutSamples);
925  Packet* packet = static_cast<Packet*> (pPacket);
926 
927  if (samples)
928  // reset the samples
929  samples->setComplete(false, 0, getSampleRate(), getChannels(),
931  if (!samples) {
932  VS_LOG_WARN("Attempting to decode when not ready; no samples");
933  return retval;
934  }
935 // if (!packet) {
936 // VS_LOG_WARN("Attempting to decode when not ready; no packet");
937 // return retval;
938 // }
939  if (!mOpened) {
940  VS_LOG_WARN("Attempting to decode when not ready; codec not opened");
941  return retval;
942  }
943  if (!mCodecContext) {
944  VS_LOG_WARN("Attempting to decode when not ready; internal context not allocated");
945  return retval;
946  }
947  if (mDirection != DECODING) {
948  VS_LOG_WARN("Attempting to decode when not ready; StreamCoder is set to encode, not decode");
949  return retval;
950  }
951  if (!mCodec || !mCodec->canDecode()) {
952  VS_LOG_WARN("Attempting to decode when not ready; codec set cannot decode");
953  return retval;
954  }
955  if (getCodecType() != ICodec::CODEC_TYPE_AUDIO) {
956  VS_LOG_WARN("Attempting to decode when not ready; codec set is not an audio codec");
957  return retval;
958  }
959 
960 
961  int outBufSize = 0;
962  int32_t inBufSize = 0;
963 
964  // When decoding with FFMPEG, ffmpeg needs the sample buffer
965  // to be at least this long.
966  samples->ensureCapacity(192000); //AVCODEC_MAX_AUDIO_FRAME_SIZE
967  outBufSize = samples->getMaxBufferSize();
968  if (packet)
969  inBufSize = packet->getSize() - startingByte;
970 
971  if (inBufSize > 0 && outBufSize > 0 || mCodec->getAVCodec()->capabilities & AV_CODEC_CAP_DELAY)
972  {
973 
974  uint8_t * inBuf = 0;
975  uint8_t * outBuf = 0;
976  uint64_t outChannelLayout;
977  AVFrame* frame = av_frame_alloc();
978 
979  if (packet)
980  {
981  RefPointer<IBuffer> buffer = packet->getData();
982  VS_ASSERT(buffer, "no buffer in packet!");
983  if (buffer)
984  inBuf = (uint8_t*) buffer->getBytes(startingByte, inBufSize);
985  VS_ASSERT(inBuf, "no in buffer");
986  }
987 
988  outBuf = (uint8_t*) samples->getRawSamples(0);
989  VS_ASSERT(outBuf, "no out buffer");
990 
991  if (outBuf)
992  {
993  VS_LOG_TRACE("Attempting decodeAudio(%p, %p, %d, %p, %d);",
994  mCodecContext,
995  outBuf,
996  outBufSize,
997  inBuf,
998  inBufSize);
999 
1000  AVPacket pkt;
1001  av_init_packet(&pkt);
1002  pkt.data = NULL;
1003  pkt.size = 0;
1004 
1005  if (inBuf)
1006  {
1007  if (packet && packet->getAVPacket())
1008  pkt = *packet->getAVPacket();
1009  // copy in our buffer
1010  pkt.data = inBuf;
1011  pkt.size = inBufSize;
1012  mCodecContext->reordered_opaque = packet->getPts();
1013  }
1014 
1015 
1016  {
1017 
1018  int got_frame = 0;
1019  retval = avcodec_decode_audio4(mCodecContext, frame, &got_frame, &pkt);
1020 // char ch_layout[64];
1021 // av_get_channel_layout_string(ch_layout,
1022 // sizeof (ch_layout),
1023 // 0,
1024 // frame->channel_layout);
1025 // VS_LOG_ERROR("ch layout: %s", ch_layout);
1026  outChannelLayout = frame->channel_layout;
1027  // the API for decoding audio changed ot support planar audio and we
1028  // need to back-port
1029 
1030 
1031 
1032  if (retval >= 0 && got_frame) {
1033  if (!swr_is_initialized(swrContext)){
1034  swr_alloc_set_opts(swrContext, // we're using an existing context
1035  //av_get_default_channel_layout(av_frame_get_channels(frame)),
1036  frame->channel_layout == 0 ? av_get_default_channel_layout(frame->channels) : frame->channel_layout, // out_ch_layout
1037  AV_SAMPLE_FMT_S16, // out_sample_fmt
1038  frame->sample_rate, // out_sample_rate
1039  //av_frame_get_channel_layout(frame) == 0 ? av_get_default_channel_layout(av_frame_get_channels(frame)) : av_frame_get_channel_layout(frame), // in_ch_layout
1040  frame->channel_layout == 0 ? av_get_default_channel_layout(frame->channels) : frame->channel_layout, // in_ch_layout
1041  mCodecContext->sample_fmt, // in_sample_fmt
1042  frame->sample_rate, // in_sample_rate
1043  0, // log_offset
1044  NULL);
1045  swr_init(swrContext);
1046  }
1047 
1048  int outChannels = av_frame_get_channels(frame);
1049  uint8_t* output[1] = {outBuf};
1050 
1051  int out_samples = swr_convert(swrContext, output, frame->nb_samples, (const uint8_t**)frame->extended_data, frame->nb_samples);
1052  if (out_samples < 0) {
1053  VS_LOG_ERROR("fail to convert samples: %s", Error::make(out_samples)->getDescription());
1054  //av_freep(&output);
1055  return out_samples;
1056  }
1057  int data_size = av_samples_get_buffer_size(NULL,
1058  outChannels,
1059  out_samples,
1060  AV_SAMPLE_FMT_S16,
1061  0);
1062 //
1063 // VS_LOG_DEBUG("Finished %d convertAudio(%p, %d, %d, %d, %d, %d);",
1064 // data_size,
1065 // plane_size,
1066 // mCodecContext,
1067 // out_samples,
1068 // frame->nb_samples,
1069 // av_frame_get_channels(frame),
1070 // outBufSize);
1071 
1072  if (outBufSize < data_size) {
1073  VS_LOG_ERROR("Output buffer is not large enough; no audio actually returned");
1074  outBufSize = 0;
1075  } else {
1076 // memcpy(outBuf, output, data_size);
1077  outBufSize = data_size;
1078 // av_freep(&output);
1079  }
1080  }
1081 
1082  }
1083  VS_LOG_TRACE("Finished %d decodeAudio(%p, %p, %d, %p, %d);",
1084  retval,
1085  mCodecContext,
1086  outBuf,
1087  outBufSize,
1088  inBuf,
1089  inBufSize);
1090  }
1091  if (retval >= 0)
1092  {
1093  // outBufSize is an In-Out parameter
1094  if (outBufSize < 0)
1095  // this can happen for some MPEG decoders
1096  outBufSize = 0;
1097 
1099  int32_t bytesPerSample = (IAudioSamples::findSampleBitDepth(format) / 8
1100  * getChannels());
1101  int32_t numSamples = outBufSize / bytesPerSample;
1102 
1103  // The audio decoder doesn't set a PTS, so we need to manufacture one.
1104  RefPointer<IRational> timeBase =
1105  this->mStream ? this->mStream->getTimeBase() : 0;
1106  if (!timeBase)
1107  timeBase = this->getTimeBase();
1108 
1109  int64_t packetTs = frame->best_effort_timestamp;
1110 // if (packetTs == Global::NO_PTS)
1111 // packetTs = packet->getDts();
1112 
1113  if (packetTs == Global::NO_PTS && mFakeNextPts == Global::NO_PTS)
1114  {
1115  // the container doesn't have time stamps; assume we start
1116  // at zero
1117  VS_LOG_TRACE("Setting fake pts to 0");
1118  mFakeNextPts = 0;
1119  }
1120  if (packetTs != Global::NO_PTS)
1121  {
1122  // The packet had a valid stream, and a valid time base
1123  if (timeBase->getNumerator() != 0 && timeBase->getDenominator() != 0)
1124  {
1125  int64_t tsDelta = Global::NO_PTS;
1126  if (mFakeNextPts != Global::NO_PTS)
1127  {
1128  int64_t fakeTsInStreamTimeBase = Global::NO_PTS;
1129  // rescale our fake into the time base of stream
1130  fakeTsInStreamTimeBase = timeBase->rescale(mFakeNextPts,
1131  mFakePtsTimeBase.value());
1132  tsDelta = fakeTsInStreamTimeBase - packetTs;
1133  }
1134 
1135  // now, compare it to our internal value; if our internally calculated value
1136  // is within 1 tick of the packet's time stamp (in the packet's time base),
1137  // then we're probably right;
1138  // otherwise, we should reset the stream's fake time stamp based on this
1139  // packet
1140  if (mFakeNextPts != Global::NO_PTS && (tsDelta >= -1 && tsDelta
1141  <= 1))
1142  {
1143  // we're the right value; keep our fake next pts
1144  VS_LOG_TRACE("Keeping mFakeNextPts: %lld", mFakeNextPts);
1145  }
1146  else
1147  {
1148  // rescale to our internal timebase
1149  int64_t packetTsInMicroseconds = mFakePtsTimeBase->rescale(
1150  packetTs, timeBase.value());
1151  VS_LOG_TRACE("%p Gap in audio (%lld); Resetting calculated ts from %lld to %lld",
1152  this,
1153  tsDelta,
1154  mFakeNextPts,
1155  packetTsInMicroseconds);
1156  mLastExternallySetTimeStamp = packetTsInMicroseconds;
1157  mSamplesCoded = 0;
1158  mFakeNextPts = mLastExternallySetTimeStamp;
1159  }
1160  }
1161  }
1162  // Use the last value of the next pts
1163  mFakeCurrPts = mFakeNextPts;
1164  // adjust our next Pts pointer
1165  if (numSamples > 0)
1166  {
1167  mSamplesCoded += numSamples;
1168  mFakeNextPts = mLastExternallySetTimeStamp
1169  + IAudioSamples::samplesToDefaultPts(mSamplesCoded,
1170  getSampleRate());
1171  }
1172 
1173  // copy the packet PTS
1174  samples->setComplete(numSamples > 0, numSamples, getSampleRate(),
1175  getChannels(), (IAudioSamples::ChannelLayout)outChannelLayout, format, mFakeCurrPts);
1176  }
1177 
1178  av_frame_free(&frame);
1179  }
1180 
1181  return retval;
1182 }
static const int64_t NO_PTS
A value that means no time stamp is set for a given object.
Definition: Global.h:50
static int32_t findSampleBitDepth(Format format)
A convenience method that returns the # of bits in a given format.
Format
The format we use to represent audio.
Definition: IAudioSamples.h:46
static int64_t samplesToDefaultPts(int64_t samples, int sampleRate)
Converts a number of samples at a given sampleRate into Microseconds.
virtual IRational * getTimeBase()
Get the time base this stream will ENCODE in, or the time base we detect while DECODING.
virtual int32_t getChannels()
Get the number of channels in this audio stream.
virtual int32_t getSampleRate()
Get the sample rate we use for this stream.
virtual ICodec::Type getCodecType()
A short hand for getCodec().getType().
virtual IRational * getTimeBase()
The time base in which all timestamps (e.g.
Definition: Stream.cpp:137
This class is only useful from C++.
Definition: RefPointer.h:47
T * value()
Return the managed pointer without calling RefCounted::acquire() on it.
Definition: RefPointer.h:226

References com::avpkit::core::AudioSamples::ensureCapacity(), com::avpkit::core::Packet::getData(), com::avpkit::core::AudioSamples::getMaxBufferSize(), com::avpkit::core::Packet::getPts(), com::avpkit::core::Packet::getSize(), com::avpkit::core::AudioSamples::setComplete(), and com::avpkit::ferry::RefPointer< T >::value().

◆ decodeVideo()

int32_t com::avpkit::core::StreamCoder::decodeVideo ( IVideoPicture pOutFrame,
IPacket packet,
int32_t  byteOffset 
)
virtual

Decode this packet into pOutFrame.

The caller is responsible for allocating the IVideoPicture object. This function will potentially overwrite any data in the frame object, but you should pass the same IVideoPicture into this function repeatedly until IVideoPicture::isComplete() is true.

Parameters
pOutFrameThe AudioSamples we decode.
packetThe packet we're attempting to decode from.
byteOffsetWhere in the packet payload to start decoding
Returns
number of bytes actually processed from the packet, or negative for error

Implements com::avpkit::core::IStreamCoder.

Definition at line 1185 of file StreamCoder.cpp.

1187 {
1188  int32_t retval = -1;
1189  VideoPicture* frame = static_cast<VideoPicture*> (pOutFrame);
1190  Packet* packet = static_cast<Packet*> (pPacket);
1191  if (frame)
1192  // reset the frame
1193  frame->setComplete(false, IPixelFormat::NONE, -1, -1, mFakeCurrPts);
1194 
1195  if (!frame) {
1196  VS_LOG_WARN("Attempting to decode when not ready; no frame");
1197  return retval;
1198  }
1199 // if (!packet) {
1200 // VS_LOG_WARN("Attempting to decode when not ready; no packet");
1201 // return retval;
1202 // }
1203  if (!mOpened) {
1204  VS_LOG_WARN("Attempting to decode when not ready; codec not opened");
1205  return retval;
1206  }
1207  if (!mCodecContext) {
1208  VS_LOG_WARN("Attempting to decode when not ready; internal context not allocated");
1209  return retval;
1210  }
1211  if (mDirection != DECODING) {
1212  VS_LOG_WARN("Attempting to decode when not ready; StreamCoder is set to encode, not decode");
1213  return retval;
1214  }
1215  if (!mCodec || !mCodec->canDecode()) {
1216  VS_LOG_WARN("Attempting to decode when not ready; codec set cannot decode");
1217  return retval;
1218  }
1219  if (getCodecType() != ICodec::CODEC_TYPE_VIDEO) {
1220  VS_LOG_WARN("Attempting to decode when not ready; codec set is not a video codec");
1221  return retval;
1222  }
1223 
1224  AVFrame *avFrame = av_frame_alloc();
1225  if (avFrame)
1226  {
1227  int frameFinished = 0;
1228  int32_t inBufSize = 0;
1229  uint8_t * inBuf = 0;
1230  if (packet) {
1231  RefPointer<IBuffer> buffer = packet->getData();
1232  inBufSize = packet->getSize() - byteOffset;
1233 
1234  VS_ASSERT(buffer, "no buffer in packet?");
1235  if (buffer)
1236  inBuf = (uint8_t*) buffer->getBytes(byteOffset, inBufSize);
1237 
1238  VS_ASSERT(inBuf, "incorrect size or no data in packet");
1239  }
1240 
1241  if (inBufSize > 0 && inBuf || mCodec->getAVCodec()->capabilities & AV_CODEC_CAP_DELAY)
1242  {
1243  AVPacket pkt;
1244  av_init_packet(&pkt);
1245  pkt.data = NULL;
1246  pkt.size = 0;
1247 
1248  if (inBuf) {
1249  VS_LOG_TRACE("Attempting decodeVideo(%p, %p, %d, %p, %d);",
1250  mCodecContext,
1251  avFrame,
1252  frameFinished,
1253  inBuf,
1254  inBufSize);
1255  if (packet && packet->getAVPacket())
1256  pkt = *packet->getAVPacket();
1257  pkt.data = inBuf;
1258  pkt.size = inBufSize;
1259  }
1260  //mCodecContext->reordered_opaque = packet->getPts();
1261  retval = avcodec_decode_video2(mCodecContext, avFrame, &frameFinished,
1262  &pkt);
1263  VS_LOG_TRACE("Finished %d decodeVideo(%p, %p, %d, %p, %d);",
1264  retval,
1265  mCodecContext,
1266  avFrame,
1267  frameFinished,
1268  inBuf,
1269  inBufSize);
1270 
1271  if (retval >= 0)
1272  {
1273 
1274  if (frameFinished)
1275  {
1276  // copy FFMPEG's buffer into our buffer; don't try to get efficient
1277  // and reuse the buffer FFMPEG is using; in order to allow our
1278  // buffers to be thread safe, we must do a copy here.
1279  avFrame->hw_frames_ctx = mCodecContext->hw_frames_ctx;
1280  frame->copyAVFrame(avFrame, getPixelType(), getWidth(), getHeight());
1281  RefPointer<IRational> timeBase = 0;
1282  timeBase = this->mStream ? this->mStream->getTimeBase() : 0;
1283  if (!timeBase)
1284  timeBase = this->getTimeBase();
1285 
1286  int64_t packetTs = avFrame->best_effort_timestamp;
1287 
1288  if (packetTs != Global::NO_PTS)
1289  {
1290  if (timeBase->getNumerator() != 0)
1291  {
1292  // The decoder set a PTS, so we let it override us
1293  int64_t nextPts = mFakePtsTimeBase->rescale(packetTs,
1294  timeBase.value());
1295  // some youtube videos incorrectly return a packet
1296  // with the wrong re-ordered opaque setting. this
1297  // detects that and uses the PTS from the packet instead.
1298  // See: http://code.google.com/p/avpkit/issues/detail?id=165
1299  // in this way we enforce that timestamps are always
1300  // increasing
1301  // if (avFrame->reordered_opaque != Global::NO_PTS && nextPts < mFakeNextPts && packet->getPts() != Global::NO_PTS) {
1302  // VS_LOG_WARN("Bad order in pts packet pts will be used instead of frame pts (packetTs: %ld, reordered_opaque: %ld, nextPts: %ld, mFakeNextPts: %ld, packet pts: %ld)",
1303  // packetTs,
1304  // avFrame->reordered_opaque,
1305  // nextPts,
1306  // mFakeNextPts,
1307  // packet->getPts());
1308  // nextPts = mFakePtsTimeBase->rescale(packet->getPts(),
1309  // timeBase.value());
1310  // }
1311  mFakeNextPts = nextPts;
1312  }
1313  }
1314 
1315  // Use the last value of the next pts
1316  mFakeCurrPts = mFakeNextPts;
1317  double frameDelay = av_rescale(timeBase->getNumerator(),
1318  AV_TIME_BASE, timeBase->getDenominator());
1319  frameDelay += avFrame->repeat_pict * (frameDelay * 0.5);
1320 
1321  // adjust our next Pts pointer
1322  mFakeNextPts += (int64_t) frameDelay;
1323  // VS_LOG_DEBUG("frame complete: %s; pts: %lld; packet ts: %lld; opaque ts: %lld; tb: %ld/%ld",
1324  // (frameFinished ? "yes" : "no"),
1325  // mFakeCurrPts,
1326  // (packet ? packet->getDts() : 0),
1327  // packetTs,
1328  // timeBase->getNumerator(),
1329  // timeBase->getDenominator()
1330  // );
1331  }
1332  frame->setComplete(frameFinished, this->getPixelType(),
1333  this->getWidth(), this->getHeight(), mFakeCurrPts);
1334 
1335  }
1336  }
1337  av_frame_free(&avFrame);
1338  }
1339 
1340  return retval;
1341 }
virtual int32_t getHeight()
The height, in pixels.
virtual IPixelFormat::Type getPixelType()
For Video streams, get the Pixel Format in use by the stream.
virtual int32_t getWidth()
The width, in pixels.

References com::avpkit::core::VideoPicture::copyAVFrame(), com::avpkit::core::Packet::getData(), com::avpkit::core::Packet::getSize(), com::avpkit::core::VideoPicture::setComplete(), and com::avpkit::ferry::RefPointer< T >::value().

◆ encodeAudio()

int32_t com::avpkit::core::StreamCoder::encodeAudio ( IPacket pOutPacket,
IAudioSamples pSamples,
int32_t  sampleToStartFrom 
)
virtual

Encode the given samples using this StreamCoder.

The VideoPicture will allocate a buffer to use internally for this, and will free it when the frame destroys itself.

Callers should call this repeatedly on a set of samples until we consume all the samples.

Also, when done in order to flush the encoder, caller should call this method passing in 0 (null) for pSamples to tell the encoder to flush any data it was keeping a hold of.

Parameters
pOutPacket[out] The packet to encode into. It will point to a buffer allocated in the frame. Caller should check IPacket::isComplete() after call to find out if we had enough information to encode a full packet.
pSamples[in] The samples to consume
sampleToStartFrom[in] Which sample you want to start with This is usually zero, but if you're using a codec that packetizes output with small number of samples, you may need to call encodeAudio repeatedly with different starting samples to consume all of your samples.
Returns
number of samples we consumed when encoding, or negative for errors.

Implements com::avpkit::core::IStreamCoder.

Definition at line 1565 of file StreamCoder.cpp.

1567 {
1568  int32_t retval = -1;
1569  AudioSamples *samples = static_cast<AudioSamples*> (pSamples);
1570  Packet *packet = static_cast<Packet*> (pOutPacket);
1571  RefPointer<IBuffer> encodingBuffer;
1572  bool usingInternalFrameBuffer = false;
1573 
1574  try
1575  {
1576  if (mDirection != ENCODING)
1577  throw std::runtime_error("Decoding StreamCoder not valid for encoding");
1578  if (!mCodec)
1579  throw std::runtime_error("Codec not set");
1580  if (!mCodec->canEncode()) {
1581  std::string msg = "Codec cannot be used to encode: ";
1582  msg += mCodec->getName();
1583  throw std::runtime_error(msg);
1584  }
1585  if (!packet)
1586  throw std::invalid_argument("Invalid packet to encode to");
1587  // Zero out our packet
1588  packet->reset();
1589 
1590  if (!mCodecContext)
1591  throw std::runtime_error("StreamCoder not initialized properly");
1592  if (!mOpened)
1593  throw std::runtime_error("StreamCoder not open");
1594  if (getCodecType() != ICodec::CODEC_TYPE_AUDIO)
1595  throw std::runtime_error(
1596  "Attempting to encode audio with non audio coder");
1597  if (!mAudioFrameBuffer)
1598  throw std::runtime_error("Audio Frame Buffer not initialized");
1599 
1600  // First, how many bytes do we need to encode a packet?
1601  int32_t frameSize = 0;
1602  int32_t frameBytes = 0;
1603  int32_t availableSamples = (samples ? samples->getNumSamples()
1604  - startingSample : 0);
1605  int32_t samplesConsumed = 0;
1606  short *avSamples = (samples ? samples->getRawSamples(startingSample) : 0);
1607 
1608  if (samples)
1609  {
1610  if (samples->getChannels() != getChannels())
1611  throw std::invalid_argument(
1612  "channels in sample do not match StreamCoder");
1613  if (samples->getSampleRate() != getSampleRate())
1614  throw std::invalid_argument(
1615  "sample rate in sample does not match StreamCoder");
1616 
1617  if (!samples->isComplete())
1618  throw std::invalid_argument("input samples are not complete");
1619 
1620  if (mFakeNextPts == Global::NO_PTS && samples->getTimeStamp()
1621  != Global::NO_PTS)
1622  mFakeNextPts = samples->getTimeStamp()
1623  + IAudioSamples::samplesToDefaultPts(startingSample,
1624  getSampleRate());
1625 
1626  }
1627 
1628  if (mFakeNextPts == Global::NO_PTS)
1629  mFakeNextPts = 0;
1630 
1631  if (availableSamples < 0 || (avSamples && availableSamples == 0))
1632  throw std::invalid_argument(
1633  "no bytes in buffer at specified starting sample");
1634 
1635  int32_t bytesPerSample = (samples ? samples->getSampleSize()
1637  (IAudioSamples::FMT_S16)) / 8
1638  * getChannels());
1639 
1640  /*
1641  * This gets tricky; There may be more audio samples passed to
1642  * us than can fit in an audio frame, or there may be less.
1643  *
1644  * If less, we need to cache for a future call.
1645  *
1646  * If more, we need to just use what's needed, and let the caller
1647  * know the number of samples we used.
1648  *
1649  * What happens when we exhaust all audio, but we still don't
1650  * have enough to decode a frame? answer: the caller passes us
1651  * NULL as the pInSamples, and we just silently drop the incomplete
1652  * frame.
1653  *
1654  * To simplify coding here (and hence open for optimization if
1655  * this ends up being a bottleneck), I always copy audio samples
1656  * into a frame buffer, and then only encode from the frame buffer
1657  * in this class.
1658  */
1659  frameSize = getAudioFrameSize();
1660  frameBytes = frameSize * bytesPerSample;
1661 
1662  // More error checking
1663  VS_ASSERT(frameBytes <= mAudioFrameBuffer->getBufferSize(),
1664  "did frameSize change from open?");
1665  if (frameBytes > mAudioFrameBuffer->getBufferSize())
1666  throw std::runtime_error("not enough memory in internal frame buffer");
1667 
1668  VS_ASSERT(mBytesInFrameBuffer <= frameBytes,
1669  "did frameSize change from open?");
1670  if (frameBytes < mBytesInFrameBuffer)
1671  throw std::runtime_error(
1672  "too many bytes left over in internal frame buffer");
1673 
1674  uint8_t * frameBuffer = (uint8_t*) mAudioFrameBuffer->getBytes(
1675  0, frameBytes);
1676  if (!frameBuffer)
1677  throw std::runtime_error("could not get internal frame buffer");
1678 
1679  int32_t bytesToCopyToFrameBuffer = frameBytes - mBytesInFrameBuffer;
1680  bytesToCopyToFrameBuffer = FFMIN(bytesToCopyToFrameBuffer,
1681  availableSamples*bytesPerSample);
1682 
1683  uint8_t *convertAvSamples;
1684 
1685  if (avSamples)
1686  {
1687  if (availableSamples >= frameSize && mBytesInFrameBuffer == 0)
1688  { //TODO: gerer CODEC_CAP_VARIABLE_FRAME_SIZE CODEC_CAP_SMALL_LAST_FRAME
1689  VS_LOG_TRACE("audioEncode: Using passed in buffer: %d, %d, %d",
1690  availableSamples, frameSize, mBytesInFrameBuffer);
1691  frameBuffer = (uint8_t*)avSamples;
1692  samplesConsumed = frameSize;
1693  usingInternalFrameBuffer = false;
1694  }
1695  else
1696  {
1697  VS_LOG_TRACE("audioEncode: Using internal buffer: %d, %d, %d %d %d",
1698  availableSamples, frameSize, mBytesInFrameBuffer);
1699  if (bytesToCopyToFrameBuffer != 0){
1700  memcpy(frameBuffer + mBytesInFrameBuffer, avSamples, bytesToCopyToFrameBuffer);
1701  mBytesInFrameBuffer += bytesToCopyToFrameBuffer;
1702  }
1703  samplesConsumed = bytesToCopyToFrameBuffer / bytesPerSample;
1704  retval = samplesConsumed;
1705  usingInternalFrameBuffer = true;
1706 
1707  }
1708 
1709  if (mPtsOfFrameBuffer == Global::NO_PTS) {
1710  RefPointer<IRational> thisTimeBase = getTimeBase();
1711  mPtsOfFrameBuffer = thisTimeBase->rescale(samples->getTimeStamp() + IAudioSamples::samplesToDefaultPts(startingSample, samples->getSampleRate()), mFakePtsTimeBase.value());
1712  }
1713  }
1714  else
1715  {
1716  // drop everything in the frame buffer, and instead
1717  // just pass a null buffer to the encoder.
1718 
1719  // this should happen when the caller passes NULL for the
1720  // input samples
1721  frameBuffer = NULL;
1722  }
1723  mSamplesForEncoding += samplesConsumed;
1724  VS_LOG_TRACE("Consumed %ld for total of %lld Need %d got %d",
1725  samplesConsumed, mSamplesForEncoding, frameBytes, mBytesInFrameBuffer);
1726 
1727  if (!frameBuffer || !usingInternalFrameBuffer || mBytesInFrameBuffer
1728  >= frameBytes)
1729  {
1730  // First, get the right buffer size.
1731  int32_t bufferSize = frameBytes;
1732  if (mCodecContext->codec->id == AV_CODEC_ID_FLAC
1733  || mCodecContext->codec->id == AV_CODEC_ID_VORBIS)
1734  {
1735  // FLAC & VORBIS audio for some reason gives an error if your output buffer isn't
1736  // over double the frame size, so we fake it here. This could be further optimized
1737  // to only require an exact number, but this math is simpler and will always
1738  // be large enough.
1739  bufferSize = (64 + getAudioFrameSize() * (bytesPerSample + 1)) * 2;
1740  }
1741  VS_ASSERT(bufferSize> 0, "no buffer size in samples");
1742  retval = packet->allocateNewPayload(bufferSize);
1743  if (retval >= 0)
1744  {
1745  encodingBuffer = packet->getData();
1746  }
1747 
1748  uint8_t* buf = 0;
1749 
1750  if (encodingBuffer)
1751  {
1752  buf = (uint8_t*) encodingBuffer->getBytes(0, bufferSize);
1753  }
1754  if (buf && bufferSize)
1755  {
1756  VS_LOG_TRACE("Attempting encodeAudio(%p, %p, %d, %p)",
1757  mCodecContext,
1758  buf,
1759  bufferSize,
1760  frameBuffer);
1761 
1762  // This hack works around the fact that PCM's codecs
1763  // calculate samples from buffer length, and sets
1764  // the wrong frame size, but in
1765  // reality we're always passing in 2 byte samples.
1766  // TODO :delete if not necessary
1767 // double pcmCorrection = 1.0;
1768 // switch (mCodecContext->codec->id)
1769 // {
1770 // case AV_CODEC_ID_PCM_S32LE:
1771 // case AV_CODEC_ID_PCM_S32BE:
1772 // case AV_CODEC_ID_PCM_U32LE:
1773 // case AV_CODEC_ID_PCM_U32BE:
1774 // pcmCorrection = 2.0;
1775 // break;
1776 // case AV_CODEC_ID_PCM_S24LE:
1777 // case AV_CODEC_ID_PCM_S24BE:
1778 // case AV_CODEC_ID_PCM_U24LE:
1779 // case AV_CODEC_ID_PCM_U24BE:
1780 // case AV_CODEC_ID_PCM_S24DAUD:
1781 // pcmCorrection = 1.5;
1782 // break;
1783 // case AV_CODEC_ID_PCM_S16LE:
1784 // case AV_CODEC_ID_PCM_S16BE:
1785 // case AV_CODEC_ID_PCM_U16LE:
1786 // case AV_CODEC_ID_PCM_U16BE:
1787 // pcmCorrection = 1.0;
1788 // break;
1789 // case AV_CODEC_ID_PCM_ALAW:
1790 // case AV_CODEC_ID_PCM_MULAW:
1791 // case AV_CODEC_ID_PCM_S8:
1792 // case AV_CODEC_ID_PCM_U8:
1793 // case AV_CODEC_ID_PCM_ZORK:
1794 // pcmCorrection = 0.5;
1795 // break;
1796 // default:
1797 // pcmCorrection = 1.0;
1798 // }
1799 
1800  int size = 0;
1801  int got_packet;
1802  AVPacket pkt;
1803  av_init_packet(&pkt);
1804  pkt.data = NULL;
1805  pkt.size = 0;
1806 
1807  if(!pSamples){
1808  retval = avcodec_encode_audio2(mCodecContext, &pkt, NULL, &got_packet);
1809  }else{
1810  int ret = 0;
1811  if (!swr_is_initialized(swrContext)){
1812  swr_alloc_set_opts(swrContext, // we're using existing context
1813  (int64_t)samples->getChannelLayout(), // out_ch_layout
1814  mCodecContext->sample_fmt, // out_sample_fmt
1815  samples->getSampleRate(), // out_sample_rate
1816  (int64_t)samples->getChannelLayout(), // in_ch_layout
1817  AV_SAMPLE_FMT_S16, // in_sample_fmt
1818  samples->getSampleRate(), // in_sample_rate
1819  0, // log_offset
1820  NULL);
1821  swr_init(swrContext);
1822  }
1823 
1824 
1825  AVFrame* codingFrame = av_frame_alloc();
1826  codingFrame->nb_samples = frameSize;
1827  codingFrame->format = mCodecContext->sample_fmt;
1828  codingFrame->channel_layout = (uint64_t)samples->getChannelLayout();
1829 
1830  if (samples->getPts() != Global::NO_PTS) {
1831  codingFrame->pts = mPtsOfFrameBuffer;
1832  }
1833 
1834 
1835 
1836  retval = av_frame_get_buffer(codingFrame, 0);
1837  if (retval<0){
1838  printf("Error %s",Error::make(retval)->getDescription());
1839  av_frame_free(&codingFrame);
1840  throw std::bad_alloc();
1841  }
1842 
1843  ret = swr_convert(swrContext, codingFrame->extended_data, frameSize, (const uint8_t**) &frameBuffer, frameSize);
1844  if (ret < 0) {
1845  VS_LOG_ERROR("fail to convert samples: %s", Error::make(ret)->getDescription());
1846  av_freep(&convertAvSamples);
1847  throw std::runtime_error("fail to convert samples");
1848  }
1849  VS_LOG_TRACE("Finished %d convertAudio(%p, %d, %d, %d, %d, %d);",
1850  ret,
1851  swrContext,
1852  availableSamples > frameSize ? frameSize : availableSamples,
1853  samples->getNumSamples(),
1854  frameSize);
1855 
1856  retval = avcodec_encode_audio2(mCodecContext, &pkt, codingFrame, &got_packet);
1857  av_frame_free(&codingFrame);
1858  }
1859 
1860  if (retval>=0 && got_packet){
1861  packet->wrapAVPacket(&pkt);
1862  size = packet->getSize();
1863  av_packet_unref(&pkt);
1864  }
1865 
1866  VS_LOG_TRACE("Finished %d %d encodeAudio(%d, %p, %d, %d, %p)",
1867  retval,
1868  got_packet,
1869  size,
1870  mCodecContext,
1871  samplesConsumed,
1872  /*buf,*/
1873  bufferSize,
1874  frameBuffer);
1875  // regardless of what happened, nuke any data in our frame
1876  // buffer.
1877  mBytesInFrameBuffer = 0;
1878  mPtsOfFrameBuffer = Global::NO_PTS;
1879  if (retval >= 0)
1880  {
1881  // and only do this if a packet is returned
1882  if (retval >= 0 && got_packet)
1883  {
1884 
1885  mSamplesCoded += frameSize;
1886 
1887  // let's check to see if the time stamp of passed in
1888  // samples (if any) are within tolerance of our expected
1889  // time stamp. if not, this is most likely happening
1890  // because the IStreamCoder's data source lost a packet.
1891  // We will adjust our starting time stamps then for this new
1892  // packet
1893  mFakeCurrPts = mFakeNextPts;
1894  if (samples && samples->getTimeStamp() != Global::NO_PTS)
1895  {
1896  int64_t samplesTs = samples->getTimeStamp()
1897  + IAudioSamples::samplesToDefaultPts(startingSample
1898  + samplesConsumed, getSampleRate());
1899  int64_t samplesCached = mSamplesForEncoding - mSamplesCoded;
1900  int64_t tsDelta = IAudioSamples::samplesToDefaultPts(
1901  samplesCached, getSampleRate());
1902  int64_t gap = samplesTs - (mFakeNextPts + tsDelta);
1903 
1904  // ignore negative gaps; some containers like WMV
1905  // don't actually set the right time stamps, and we
1906  // can assume a negative gap can't happen
1907  if ((gap > 1))
1908  {
1909  VS_LOG_TRACE("reset;"
1910  "samplesTs:%lld;"
1911  "samplesConsumed:%ld;"
1912  "startingSample:%lu;"
1913  "samplesForEncoding:%lld;"
1914  "samplesCoded:%lld;"
1915  "samplesCached:%lld;"
1916  "tsDelta:%lld;"
1917  "fakeNextPts:%lld;"
1918  "gap:%lld;"
1919  "lastExternallySetTs:%lld;"
1920  "new fakeNextPts:%lld;",
1921  samplesTs,
1922  samplesConsumed,
1923  startingSample,
1924  mSamplesForEncoding,
1925  mSamplesCoded,
1926  samplesCached,
1927  tsDelta,
1928  mFakeNextPts,
1929  gap,
1930  mLastExternallySetTimeStamp,
1931  samplesTs - tsDelta);
1932  mLastExternallySetTimeStamp = samplesTs - tsDelta;
1933  mSamplesCoded = 0;
1934  mSamplesForEncoding = samplesCached;
1935  }
1936  }
1937  mFakeNextPts = mLastExternallySetTimeStamp
1938  + IAudioSamples::samplesToDefaultPts(mSamplesCoded,
1939  getSampleRate());
1940 
1941  }
1942  RefPointer<IRational> thisTimeBase = getTimeBase();
1943  int64_t ts;
1944  int64_t duration = IAudioSamples::samplesToDefaultPts(frameSize,
1945  getSampleRate());
1946  if (!thisTimeBase)
1947  {
1948  thisTimeBase.reset(mFakePtsTimeBase.value(), true);
1949  ts = mFakeCurrPts;
1950  }
1951  else
1952  {
1953  ts = thisTimeBase->rescale(mFakeCurrPts, mFakePtsTimeBase.value());
1954  duration
1955  = thisTimeBase->rescale(duration, mFakePtsTimeBase.value());
1956  }
1957  setPacketParameters(packet, size, ts, thisTimeBase.value(), true,
1958  duration, got_packet);
1959  //printf("%d\n",(int)ts);
1960  // setPacketParameters(packet, size, packet->getAVPacket()->dts, thisTimeBase.value(), true,
1961 // packet->getAVPacket()->duration);
1962 
1963  retval = samplesConsumed;
1964  }
1965  else
1966  {
1967  throw std::runtime_error("avcodec_encode_audio failed");
1968  }
1969  }
1970  }
1971  }
1972  catch (std::bad_alloc & e)
1973  {
1974  throw e;
1975  }
1976  catch (std::exception& e)
1977  {
1978  VS_LOG_WARN("error: %s", e.what());
1979  retval = -1;
1980  }
1981 
1982  return retval;
1983 }
virtual int32_t getAudioFrameSize()
For this stream, get the number of audio samples that are represented in a packet of information.
virtual void * getBytes(int32_t offset, int32_t length)=0
Returns up to length bytes, starting at offset in the underlying buffer we're managing.
virtual int32_t getBufferSize()=0
Get the current maximum number of bytes that can be safely placed in this buffer.
void reset(T *ptr=0, bool acquire=false)
Reset the managed pointer, calling RefCounted::release() on the previously managed pointer first.
Definition: RefPointer.h:237

References com::avpkit::core::Packet::allocateNewPayload(), com::avpkit::core::AudioSamples::getChannels(), com::avpkit::core::Packet::getData(), com::avpkit::core::AudioSamples::getNumSamples(), com::avpkit::core::AudioSamples::getPts(), com::avpkit::core::AudioSamples::getSampleRate(), com::avpkit::core::AudioSamples::getSampleSize(), com::avpkit::core::Packet::getSize(), com::avpkit::core::AudioSamples::getTimeStamp(), com::avpkit::core::AudioSamples::isComplete(), com::avpkit::core::Packet::reset(), com::avpkit::ferry::RefPointer< T >::reset(), and com::avpkit::ferry::RefPointer< T >::value().

◆ encodeVideo()

int32_t com::avpkit::core::StreamCoder::encodeVideo ( IPacket pOutPacket,
IVideoPicture pFrame,
int32_t  suggestedBufferSize 
)
virtual

Encode the given frame using this StreamCoder.

The VideoPicture will allocate a buffer to use internally for this, and will free it when the frame destroys itself.

Also, when done in order to flush the encoder, caller should call this method passing in 0 (null) for pFrame to tell the encoder to flush any data it was keeping a hold of.

Parameters
pOutPacket[out] The packet to encode into. It will point to a buffer allocated in the frame. Caller should check IPacket::isComplete() after call to find out if we had enough information to encode a full packet.
pFrame[in/out] The frame to encode
suggestedBufferSizeThe suggested buffer size to allocate or -1 for choose ourselves. If -1 we'll allocate a buffer exactly the same size (+1) as the decoded frame with the guess that you're encoding a frame because you want to use LESS space than that.

@ return >= 0 on success; <0 on error.

Implements com::avpkit::core::IStreamCoder.

Definition at line 1344 of file StreamCoder.cpp.

1346 {
1347  int32_t retval = -1;
1348  VideoPicture *frame = static_cast<VideoPicture*> (pFrame);
1349  Packet *packet = static_cast<Packet*> (pOutPacket);
1350  RefPointer<IBuffer> encodingBuffer;
1351 
1352  try
1353  {
1354  if (packet)
1355  packet->reset();
1356 
1357  if (getCodecType() != ICodec::CODEC_TYPE_VIDEO)
1358  throw std::runtime_error(
1359  "Attempting to encode video with non video coder");
1360 
1361  if (frame && frame->getPixelType() != this->getPixelType())
1362  throw std::runtime_error(
1363  "picture is not of the same PixelType as this Coder expected");
1364  if (frame && frame->getWidth() != this->getWidth())
1365  throw std::runtime_error("picture is not of the same width as this Coder");
1366  if (frame && frame->getHeight() != this->getHeight())
1367  throw std::runtime_error(
1368  "picture is not of the same height as this Coder");
1369 
1370  if (mDirection != ENCODING)
1371  throw std::runtime_error("Decoding StreamCoder not valid for encoding");
1372  if (!mCodec)
1373  throw std::runtime_error("Codec not set");
1374  if (!mCodec->canEncode())
1375  throw std::runtime_error("Codec cannot be used to encode");
1376  if (mCodecContext && mOpened && mDirection == ENCODING && packet)
1377  {
1378  uint8_t* buf = 0;
1379  int32_t bufLen = 0;
1380 
1381  // First, get the right buffer size.
1382  if (suggestedBufferSize <= 0)
1383  {
1384  if (frame)
1385  {
1386  suggestedBufferSize = frame->getSize();
1387  }
1388  else
1389  {
1390  suggestedBufferSize = av_image_get_buffer_size(
1391  (AVPixelFormat) getPixelType(), getWidth(), getHeight(), 1);
1392  }
1393  }
1394  VS_ASSERT(suggestedBufferSize> 0, "no buffer size in input frame");
1395  suggestedBufferSize = FFMAX(suggestedBufferSize, AV_INPUT_BUFFER_MIN_SIZE);
1396 
1397  retval = packet->allocateNewPayload(suggestedBufferSize);
1398  if (retval >= 0)
1399  {
1400  encodingBuffer = packet->getData();
1401  }
1402  if (encodingBuffer)
1403  {
1404  buf = (uint8_t*) encodingBuffer->getBytes(0, suggestedBufferSize);
1405  bufLen = encodingBuffer->getBufferSize();
1406  }
1407 
1408  if (buf && bufLen || mCodec->getAVCodec()->capabilities & AV_CODEC_CAP_DELAY)
1409  {
1410  // Change the PTS in our frame to the timebase of the encoded stream
1411  RefPointer<IRational> thisTimeBase = getTimeBase();
1412 
1413  /*
1414  * We make a copy of the AVFrame object and explicitly copy
1415  * over the values that we know encoding cares about.
1416  *
1417  * This is because often some programs decode into an VideoPicture
1418  * and just want to pass that to encodeVideo. If we just
1419  * leave the values that Ffmpeg had in the AVFrame during
1420  * decoding, strange errors can result.
1421  *
1422  * Plus, this forces us to KNOW what we're passing into the encoder.
1423  */
1424  AVFrame* avFrame = 0;
1425  bool dropFrame = false;
1426  if (frame)
1427  {
1428  avFrame = av_frame_alloc();
1429  if (!avFrame)
1430  throw std::bad_alloc();
1431  frame->fillAVFrame(avFrame);
1432 
1433  // convert into the time base that this coder wants
1434  // to output in
1435  int64_t codecTimeBasePts = thisTimeBase->rescale(frame->getPts(),
1436  mFakePtsTimeBase.value(), IRational::ROUND_DOWN);
1437  if (mLastPtsEncoded != Global::NO_PTS)
1438  {
1439  // adjust for rounding;
1440  // fixes http://code.google.com/p/avpkit/issues/detail?id=180
1441  if (codecTimeBasePts < mLastPtsEncoded)
1442  {
1443  VS_LOG_TRACE(
1444  "Dropping frame with timestamp %lld (if coder supports higher time-base use that instead)",
1445  frame->getPts());
1446  dropFrame = true;
1447  }
1448  else if (codecTimeBasePts == mLastPtsEncoded)
1449  {
1450  // else we're close enough; increment by 1
1451  ++codecTimeBasePts;
1452  }
1453  }
1454  VS_LOG_TRACE("Rescaling ts: %lld to %lld (last: %lld) (from base %d/%d to %d/%d)",
1455  frame->getPts(),
1456  codecTimeBasePts,
1457  mLastPtsEncoded,
1458  mFakePtsTimeBase->getNumerator(),
1459  mFakePtsTimeBase->getDenominator(),
1460  thisTimeBase->getNumerator(),
1461  thisTimeBase->getDenominator());
1462  avFrame->pts = codecTimeBasePts;
1463  if (!dropFrame)
1464  mLastPtsEncoded = avFrame->pts;
1465  }
1466 
1467  int got_pkt;
1468 
1469  if (!dropFrame)
1470  {
1471  VS_LOG_TRACE("Attempting encodeVideo(%p, %p, %d, %p)",
1472  mCodecContext,
1473  buf,
1474  bufLen,
1475  avFrame);
1476  packet->getAVPacket()->size = suggestedBufferSize;
1477  retval = avcodec_encode_video2(mCodecContext, packet->getAVPacket(), avFrame, &got_pkt);
1478 // retval = avcodec_encode_video(mCodecContext, buf, bufLen, avFrame);
1479 
1480  }
1481  else
1482  {
1483  ++mNumDroppedFrames;
1484  retval = 0;
1485  }
1486  if (retval == 0)
1487  {
1488  int64_t dts = (avFrame ? mLastPtsEncoded : mLastPtsEncoded + 1);
1489  int64_t duration = 1;
1490  if (got_pkt) {
1491  int32_t num = thisTimeBase->getNumerator();
1492  int32_t den = thisTimeBase->getDenominator();
1493  if (num*1000LL > den)
1494  {
1495  if (mCodecContext->coded_frame
1496  && mCodecContext->coded_frame->repeat_pict)
1497  {
1498  num = num * (1+mCodecContext->coded_frame->repeat_pict);
1499  }
1500  }
1501  duration = av_rescale(1,
1502  num * (int64_t)den * mCodecContext->ticks_per_frame,
1503  den * (int64_t) thisTimeBase->getNumerator());
1504 
1505  // This will be zero if the Codec does not use b-frames;
1506  // although we provide space for delaying up to the
1507  // max H264 delay, in reality we only need delay by 1 tick.
1508  int32_t delay = FFMAX(mCodecContext->has_b_frames,
1509  mCodecContext->max_b_frames > 0);
1510  dts = packet->getAVPacket()->dts;
1511  if (packet->getAVPacket()->pts != Global::NO_PTS && dts == Global::NO_PTS && delay <= MAX_REORDER_DELAY)
1512  {
1513  int64_t pts = packet->getAVPacket()->pts;
1514  mPtsBuffer[0] = pts;
1515  int32_t i;
1516  // If first time through set others to some 'sensible' defaults.
1517  // If the first PTS is zero, this leads to starting negative
1518  // dts values, but FFmpeg allows that so we do too.
1519  for(i = 1; i < delay + 1 && mPtsBuffer[i] == Global::NO_PTS; i++)
1520  mPtsBuffer[i] = pts + (i-delay-1)*duration;
1521  // Order the PTS values in increasing order and the lowest
1522  // one will magically be the DTS we should use for this packet.
1523  for(i = 0; i < delay && mPtsBuffer[i] > mPtsBuffer[i+1]; i++)
1524  FFSWAP(int64_t, mPtsBuffer[i], mPtsBuffer[i+1]);
1525  dts = mPtsBuffer[0];
1526 // VS_LOG_ERROR("type: %d; output: dts: %lld; pts: %lld",
1527 // mCodecContext->coded_frame->pict_type,
1528 // dts,
1529 // pts);
1530  }
1531  }
1532  setPacketParameters(
1533  packet,
1534  got_pkt ? packet->getAVPacket()->size : retval,
1535  // if the last packet, increment the pts encoded
1536  // by one
1537  dts,
1538  thisTimeBase.value(),
1539  (packet->getAVPacket()->flags & AV_PKT_FLAG_KEY), duration, got_pkt);
1540  }
1541  if (avFrame)
1542  av_free(avFrame);
1543  }
1544  }
1545  else
1546  {
1547  VS_LOG_WARN("Attempting to encode when not ready");
1548  }
1549  }
1550  catch (std::bad_alloc & e)
1551  {
1552  retval = -1;
1553  throw e;
1554  }
1555  catch (std::exception & e)
1556  {
1557  VS_LOG_WARN("Got error: %s", e.what());
1558  retval = -1;
1559  }
1560 
1561  return retval;
1562 }

References com::avpkit::core::Packet::allocateNewPayload(), com::avpkit::core::VideoPicture::fillAVFrame(), com::avpkit::core::Packet::getData(), com::avpkit::core::VideoPicture::getHeight(), com::avpkit::core::VideoPicture::getPixelType(), com::avpkit::core::VideoPicture::getPts(), com::avpkit::core::VideoPicture::getSize(), com::avpkit::core::VideoPicture::getWidth(), com::avpkit::core::Packet::reset(), and com::avpkit::ferry::RefPointer< T >::value().

◆ getAudioFrameSize()

int32_t com::avpkit::core::StreamCoder::getAudioFrameSize ( )
virtual

For this stream, get the number of audio samples that are represented in a packet of information.

Returns
Number of samples per 'frame' of encoded audio

Implements com::avpkit::core::IStreamCoder.

Definition at line 2035 of file StreamCoder.cpp.

2036 {
2037  int32_t retval = 0;
2038  if (mCodec && mCodec->getType() == ICodec::CODEC_TYPE_AUDIO)
2039  {
2040  if (mCodecContext->frame_size <= 1)
2041  {
2042  // Rats; some PCM encoders give a frame size of 1, which is too
2043  //small. We pick a more sensible value.
2044  retval = getDefaultAudioFrameSize();
2045  }
2046  else
2047  {
2048  retval = mCodecContext->frame_size;
2049  }
2050  }
2051  return retval;
2052 }
virtual int32_t getDefaultAudioFrameSize()
Get the default audio frame size (in samples).

◆ getAutomaticallyStampPacketsForStream()

bool com::avpkit::core::StreamCoder::getAutomaticallyStampPacketsForStream ( )
virtual

Does this IStreamCoder automatically adjust time stamps on output packets for the IStream it is ultimately destined for.

Returns
true for yes; false for no
See also
setAutomaticallyStampPacketsForStream(bool)
Since
3.2

Implements com::avpkit::core::IStreamCoder.

Definition at line 2240 of file StreamCoder.cpp.

2241 {
2242  return mAutomaticallyStampPacketsForStream;
2243 }

◆ getBitRate()

int32_t com::avpkit::core::StreamCoder::getBitRate ( )
virtual

The bit rate.

Returns
The bit-rate the stream is, or will be, encoded in.

Implements com::avpkit::core::IStreamCoder.

Definition at line 511 of file StreamCoder.cpp.

512 {
513  return (mCodecContext ? mCodecContext->bit_rate : -1);
514 }

◆ getBitRateTolerance()

int32_t com::avpkit::core::StreamCoder::getBitRateTolerance ( )
virtual

The bit rate tolerance.

Returns
The bit-rate tolerance

Implements com::avpkit::core::IStreamCoder.

Definition at line 522 of file StreamCoder.cpp.

523 {
524  return (mCodecContext ? mCodecContext->bit_rate_tolerance : -1);
525 }

◆ getChannels()

int32_t com::avpkit::core::StreamCoder::getChannels ( )
virtual

Get the number of channels in this audio stream.

Returns
The sample rate (in Hz) we use for this stream, or 0 if unknown.

Implements com::avpkit::core::IStreamCoder.

Definition at line 690 of file StreamCoder.cpp.

691 {
692  return (mCodecContext ? mCodecContext->channels : -1);
693 }

◆ getCodec()

Codec * com::avpkit::core::StreamCoder::getCodec ( )
virtual

The Codec this StreamCoder will use.

Returns
The Codec used by this StreamCoder, or 0 (null) if none.

Implements com::avpkit::core::IStreamCoder.

Definition at line 475 of file StreamCoder.cpp.

476 {
477  return mCodec ? mCodec.get() : 0;
478 }

Referenced by com::avpkit::core::Container::addNewStream().

◆ getCodecID()

ICodec::ID com::avpkit::core::StreamCoder::getCodecID ( )
virtual

A short hand for getCodec().getID().

Note for Native (C++) users:

If you actually write code like the above from Native code, you'd leak a Codec() since you didn't call release() on it. This method is a short hand way to avoid you having to worry about releasing in between.

Returns
The ID of the Codec we'll use.

Implements com::avpkit::core::IStreamCoder.

Definition at line 496 of file StreamCoder.cpp.

497 {
498  ICodec::ID retval = ICodec::AV_CODEC_ID_NONE;
499  if (mCodecContext)
500  {
501  retval = (ICodec::ID) mCodecContext->codec_id;
502  }
503  else
504  {
505  VS_LOG_WARN("Attempt to get CodecID from uninitialized StreamCoder");
506  }
507  return retval;
508 }
ID
These are the codecs this library currently supports.
Definition: ICodec.h:61

◆ getCodecTag()

int32_t com::avpkit::core::StreamCoder::getCodecTag ( )
virtual

Returns the 4-byte FOURCC tag (Least Significant Byte first).

This is really a packed 4-byte array so it's only useful if you use bit-wise operations on it. Some language wrappings may provide more obvious ways of manipulating, but this is the safest way to do this that will work with all wrappers.

Returns
the FOURCC tag.

Implements com::avpkit::core::IStreamCoder.

Definition at line 2085 of file StreamCoder.cpp.

2086 {
2087  return (mCodecContext ? mCodecContext->codec_tag : 0);
2088 }

◆ getCodecType()

ICodec::Type com::avpkit::core::StreamCoder::getCodecType ( )
virtual

A short hand for getCodec().getType().

Note for Native (C++) users:

If you actually write code like the above from Native code, you'd leak a Codec() since you didn't call release() on it. This method is a short hand way to avoid you having to worry about releasing in between.

Returns
The Type of the Codec we'll use.

Implements com::avpkit::core::IStreamCoder.

Definition at line 481 of file StreamCoder.cpp.

482 {
483  ICodec::Type retval = ICodec::CODEC_TYPE_UNKNOWN;
484  if (mCodecContext)
485  {
486  retval = (ICodec::Type) mCodecContext->codec_type;
487  }
488  else
489  {
490  VS_LOG_WARN("Attempt to get CodecType from uninitialized StreamCoder");
491  }
492  return retval;
493 }
Type
The different types of Codecs that can exist in the system.
Definition: ICodec.h:582

◆ getDefaultAudioFrameSize()

int32_t com::avpkit::core::StreamCoder::getDefaultAudioFrameSize ( )
virtual

Get the default audio frame size (in samples).

Some codecs, especially raw codecs, like PCM, don't have a standard frame size. In those cases, we use the value of this setting to determine how many samples to encode into a single packet.

Returns
the number of samples in an audio frame size if the codec doesn't specify the size.
Since
1.21

Implements com::avpkit::core::IStreamCoder.

Definition at line 2189 of file StreamCoder.cpp.

2190 {
2191  return mDefaultAudioFrameSize;
2192 }

◆ getDirection()

virtual Direction com::avpkit::core::StreamCoder::getDirection ( )
inlinevirtual

Get the direction.

Returns
The direction this StreamCoder works in.

Implements com::avpkit::core::IStreamCoder.

Definition at line 43 of file StreamCoder.h.

43 { return mDirection; }

◆ getExtraData()

int32_t com::avpkit::core::StreamCoder::getExtraData ( com::avpkit::ferry::IBuffer dest,
int32_t  offset,
int32_t  maxBytesToCopy 
)
virtual

Copies the current content of the extra-data buffer maintained by this codec (e.g.

header bytes) into the dest buffer.

Parameters
destThe buffer to copy to.
offsetThe position, in bytes, to start writing data to in dest.
maxBytesToCopyThe maximum number of bytes to copy.
Returns
The number of bytes copied, or < 0 on error.
Since
3.3

Implements com::avpkit::core::IStreamCoder.

Definition at line 2281 of file StreamCoder.cpp.

2283 {
2284  if (!mCodecContext || !mCodecContext->extradata
2285  || mCodecContext->extradata_size <= 0 || !dest || offset < 0
2286  || maxBytesToCopy < 0 || dest->getSize() < offset + maxBytesToCopy)
2287  return 0;
2288 
2289  int32_t bytesToCopy = FFMIN(maxBytesToCopy, mCodecContext->extradata_size);
2290  if (bytesToCopy <= 0)
2291  return 0;
2292  void* bytes = dest->getBytes(offset, bytesToCopy);
2293  if (!bytes)
2294  return 0;
2295  memcpy(bytes, mCodecContext->extradata, bytesToCopy);
2296  return bytesToCopy;
2297 }

References com::avpkit::ferry::IBuffer::getBytes().

◆ getExtraDataSize()

int32_t com::avpkit::core::StreamCoder::getExtraDataSize ( )
virtual

Gets the current number of bytes of data maintained in the coder extra-data area.

Returns
The number of bytes. If 0, then no data is currently available.
Since
3.3

Implements com::avpkit::core::IStreamCoder.

Definition at line 2300 of file StreamCoder.cpp.

2301 {
2302  if (mCodecContext)
2303  return mCodecContext->extradata_size;
2304  return 0;
2305 }

◆ getFlag()

bool com::avpkit::core::StreamCoder::getFlag ( Flags  flag)
virtual

Get the setting for the specified flag.

Parameters
flagThe flag you want to find the setting for
Returns
0 for false; non-zero for true

Implements com::avpkit::core::IStreamCoder.

Definition at line 731 of file StreamCoder.cpp.

732 {
733  bool result = false;
734  if (mCodecContext)
735  result = mCodecContext->flags & flag;
736  return result;
737 }

◆ getFlags()

int32_t com::avpkit::core::StreamCoder::getFlags ( )
virtual

Get the flags associated with this codec.

Returns
The (compacted) value of all flags set.

Implements com::avpkit::core::IStreamCoder.

Definition at line 718 of file StreamCoder.cpp.

719 {
720  return (mCodecContext ? mCodecContext->flags : 0);
721 }

◆ getFrameRate()

IRational * com::avpkit::core::StreamCoder::getFrameRate ( )
virtual

Get the frame-rate the attached stream claims to be using when DECODING, or the frame-rate we'll claim we're using when ENCODING.

Returns
The frame rate.

Implements com::avpkit::core::IStreamCoder.

Definition at line 601 of file StreamCoder.cpp.

602 {
603  if (mCodecContext && mCodecContext->framerate.num > 0) {
604  return Rational::make(&mCodecContext->framerate);
605  }
606  return (mStream ? mStream->getFrameRate() : 0);
607 }
static IRational * make()
Get a new rational that will be set to 0/0.
Definition: IRational.cpp:79
virtual IRational * getFrameRate()
Get the (sometimes estimated) frame rate of this container.
Definition: Stream.cpp:125

◆ getGlobalQuality()

int32_t com::avpkit::core::StreamCoder::getGlobalQuality ( )
virtual

Get the Global Quality setting this codec uses for video if a VideoPicture doesn't have a quality set.

Returns
The global quality.

Implements com::avpkit::core::IStreamCoder.

Definition at line 703 of file StreamCoder.cpp.

704 {
705  return (mCodecContext ? mCodecContext->global_quality : FF_LAMBDA_MAX);
706 }

◆ getHeight()

int32_t com::avpkit::core::StreamCoder::getHeight ( )
virtual

The height, in pixels.

Returns
The height of the video frames in the attached stream or -1 if an audio stream, or we cannot determine the height.

Implements com::avpkit::core::IStreamCoder.

Definition at line 533 of file StreamCoder.cpp.

534 {
535  return (mCodecContext ? mCodecContext->height : -1);
536 }

◆ getNextPredictedPts()

int64_t com::avpkit::core::StreamCoder::getNextPredictedPts ( )
virtual

For this stream, get the next Pts that we expect to decode.

Note that this may not actually be the next Pts (for example due to transmission packet drops in the input source). Still it can be a useful tool.

Returns
The next presentation time stamp we expect to decode on this stream. This is always in units of 1/1,000,000 seconds

Implements com::avpkit::core::IStreamCoder.

Definition at line 595 of file StreamCoder.cpp.

596 {
597  return mFakeNextPts;
598 }

◆ getNumDroppedFrames()

int64_t com::avpkit::core::StreamCoder::getNumDroppedFrames ( )
virtual

Get the number of frames this StreamCoder had to drop to encode at the specified getTimeBase().

IStreamCoder objects can encode audio and video, but guarantee that every packet outputted has monotonically increasing timestamps (i.e. 0, 1, 2, 3, 4, 5, etc. without repeats). Sometimes data is passed too quickly into an IStreamCoder via encodeVideo or encodeAudio, and the underlying codec can't handle it that quickly. In those cases the IStreamCoder must drop the most recent frame of data.

If you're seeing a lot of dropped frames you can try either sending less frequent data to the IStreamCoder, or adjusting the getTimeBase() to the highest possible resolution. Be warned though; some codecs (such as MPEG2) require fixed time-bases (like 1/25) and so setting a higher resolution time base might end up with the codec not able to encode any data.

Returns
the number of frames dropped.
Since
3.1

Implements com::avpkit::core::IStreamCoder.

Definition at line 2227 of file StreamCoder.cpp.

2228 {
2229  return mNumDroppedFrames;
2230 }

◆ getNumPicturesInGroupOfPictures()

int32_t com::avpkit::core::StreamCoder::getNumPicturesInGroupOfPictures ( )
virtual

The the number of pictures in this Group of Pictures (GOP).

See the MPEG specs for what a GOP is officially, but this is the minimum number of frames between key-frames (or Intra-Frames in MPEG speak).

Returns
the GOPS for this stream.

Implements com::avpkit::core::IStreamCoder.

Definition at line 622 of file StreamCoder.cpp.

623 {
624  return (mCodecContext ? mCodecContext->gop_size : -1);
625 }

◆ getNumProperties()

int32_t com::avpkit::core::StreamCoder::getNumProperties ( )
virtual

Returns the total number of settable properties on this object.

Returns
total number of options (not including constant definitions)

Implements com::avpkit::core::IStreamCoder.

Definition at line 2098 of file StreamCoder.cpp.

2099 {
2100  return Property::getNumProperties(mCodecContext);
2101 }
static int32_t getNumProperties(void *context)
For internal use.
Definition: Property.cpp:114

◆ getPixelType()

IPixelFormat::Type com::avpkit::core::StreamCoder::getPixelType ( )
virtual

For Video streams, get the Pixel Format in use by the stream.

Returns
the Pixel format, or IPixelFormat::NONE if audio.

Implements com::avpkit::core::IStreamCoder.

Definition at line 635 of file StreamCoder.cpp.

636 {
637  IPixelFormat::Type retval = IPixelFormat::NONE;
638  int32_t type = 0;
639  if (mCodecContext)
640  {
641  retval = (IPixelFormat::Type) mCodecContext->pix_fmt;
642 
643  // little check here to see if we have an undefined int32_t.
644  type = (int32_t) retval;
645  if (type != mCodecContext->pix_fmt) {
646  VS_LOG_ERROR("Undefined pixel format type: %d", mCodecContext->pix_fmt);
647  retval = IPixelFormat::NONE;
648  }
649  }
650  return retval;
651 }

◆ getPropertyAsBoolean()

bool com::avpkit::core::StreamCoder::getPropertyAsBoolean ( const char *  name)
virtual

Gets the value of this property, and returns as a boolean.

Parameters
namename of option
Returns
boolean value of property, or false on error.

Implements com::avpkit::core::IStreamCoder.

Definition at line 2177 of file StreamCoder.cpp.

2178 {
2179  return Property::getPropertyAsBoolean(mCodecContext, aName);
2180 }
static bool getPropertyAsBoolean(void *context, const char *name)
Gets the value of this property, and returns as a boolean.
Definition: Property.cpp:491

◆ getPropertyAsDouble()

double com::avpkit::core::StreamCoder::getPropertyAsDouble ( const char *  name)
virtual

Gets the value of this property, and returns as a double;.

Parameters
namename of option
Returns
double value of property, or 0 on error.

Implements com::avpkit::core::IStreamCoder.

Definition at line 2159 of file StreamCoder.cpp.

2160 {
2161  return Property::getPropertyAsDouble(mCodecContext, aName);
2162 }
static double getPropertyAsDouble(void *context, const char *name)
Gets the value of this property, and returns as a double;.
Definition: Property.cpp:422

◆ getPropertyAsLong()

int64_t com::avpkit::core::StreamCoder::getPropertyAsLong ( const char *  name)
virtual

Gets the value of this property, and returns as an long;.

Parameters
namename of option
Returns
long value of property, or 0 on error.

Implements com::avpkit::core::IStreamCoder.

Definition at line 2165 of file StreamCoder.cpp.

2166 {
2167  return Property::getPropertyAsLong(mCodecContext, aName);
2168 }
static int64_t getPropertyAsLong(void *context, const char *name)
Gets the value of this property, and returns as an long;.
Definition: Property.cpp:446

◆ getPropertyAsRational()

IRational * com::avpkit::core::StreamCoder::getPropertyAsRational ( const char *  name)
virtual

Gets the value of this property, and returns as an IRational;.

Parameters
namename of option
Returns
long value of property, or 0 on error.

Implements com::avpkit::core::IStreamCoder.

Definition at line 2171 of file StreamCoder.cpp.

2172 {
2173  return Property::getPropertyAsRational(mCodecContext, aName);
2174 }
static IRational * getPropertyAsRational(void *context, const char *name)
Gets the value of this property, and returns as an IRational;.
Definition: Property.cpp:467

◆ getPropertyAsString()

char * com::avpkit::core::StreamCoder::getPropertyAsString ( const char *  name)
virtual

Gets a property on this Object.

Note for C++ callers; you must free the returned array with delete[] in order to avoid a memory leak. Other language folks need not worry.

Parameters
nameproperty name
Returns
an string copy of the option value, or null if the option doesn't exist.

Implements com::avpkit::core::IStreamCoder.

Definition at line 2153 of file StreamCoder.cpp.

2154 {
2155  return Property::getPropertyAsString(mCodecContext, aName);
2156 }
static char * getPropertyAsString(void *context, const char *name)
Gets the value of this property, and returns as a new[]ed string.
Definition: Property.cpp:238

◆ getPropertyMetaData() [1/2]

IProperty * com::avpkit::core::StreamCoder::getPropertyMetaData ( const char *  name)
virtual

Returns the name of the numbered property.

Parameters
nameThe property name.
Returns
an IProperty value for this properties meta-data

Implements com::avpkit::core::IStreamCoder.

Definition at line 2110 of file StreamCoder.cpp.

2111 {
2112  return Property::getPropertyMetaData(mCodecContext, name);
2113 }
static IProperty * getPropertyMetaData(void *context, int32_t propertyNo)
Returns the metadata for the numbered property.
Definition: Property.cpp:133

◆ getPropertyMetaData() [2/2]

IProperty * com::avpkit::core::StreamCoder::getPropertyMetaData ( int32_t  propertyNo)
virtual

Returns the name of the numbered property.

Parameters
propertyNoThe property number in the options list.
Returns
an IProperty value for this properties meta-data

Implements com::avpkit::core::IStreamCoder.

Definition at line 2104 of file StreamCoder.cpp.

2105 {
2106  return Property::getPropertyMetaData(mCodecContext, propertyNo);
2107 }

◆ getSampleFormat()

IAudioSamples::Format com::avpkit::core::StreamCoder::getSampleFormat ( )
virtual

Get the audio sample format.

Returns
The sample format of samples for encoding/decoding.

Implements com::avpkit::core::IStreamCoder.

Definition at line 676 of file StreamCoder.cpp.

677 {
678  return (IAudioSamples::Format) (mCodecContext ? mCodecContext->sample_fmt
679  : -1);
680 }

◆ getSampleRate()

int32_t com::avpkit::core::StreamCoder::getSampleRate ( )
virtual

Get the sample rate we use for this stream.

Returns
The sample rate (in Hz) we use for this stream, or -1 if unknown or video.

Implements com::avpkit::core::IStreamCoder.

Definition at line 663 of file StreamCoder.cpp.

664 {
665  return (mCodecContext ? mCodecContext->sample_rate : -1);
666 }

◆ getStandardsCompliance()

IStreamCoder::CodecStandardsCompliance com::avpkit::core::StreamCoder::getStandardsCompliance ( )
virtual

Gets the current level of standards compliance.

Returns
The level of standards compliance.
See also
CodecStandardsCompliance
Since
5.0

Implements com::avpkit::core::IStreamCoder.

Definition at line 2308 of file StreamCoder.cpp.

2309 {
2310  if (mCodecContext)
2311  return (CodecStandardsCompliance) mCodecContext->strict_std_compliance;
2312  return (CodecStandardsCompliance)0;
2313 }
CodecStandardsCompliance
An enumeration of how strictly Codecs may follow the spec.
Definition: IStreamCoder.h:959

◆ getStream()

IStream * com::avpkit::core::StreamCoder::getStream ( )
virtual

The associated Stream we're working on.

Returns
The stream associated with this object.

Implements com::avpkit::core::IStreamCoder.

Definition at line 467 of file StreamCoder.cpp.

468 {
469  // Acquire for the caller.
470  VS_REF_ACQUIRE(mStream);
471  return mStream;
472 }

◆ getTimeBase()

IRational * com::avpkit::core::StreamCoder::getTimeBase ( )
virtual

Get the time base this stream will ENCODE in, or the time base we detect while DECODING.

Caller must call release() on the returned value.

Returns
The time base this StreamCoder is using.

Implements com::avpkit::core::IStreamCoder.

Definition at line 559 of file StreamCoder.cpp.

560 {
561  // we make a new value and return it; caller must
562  // release.
563  IRational *retval = 0;
564 
565  // annoyingly, some codec contexts will NOT have
566  // a timebase... so we take it from stream then.
567  if (mCodecContext && mCodecContext->time_base.den
568  && mCodecContext->time_base.num)
569  {
570  retval = Rational::make(&mCodecContext->time_base);
571  }
572  else if (mAutomaticallyStampPacketsForStream)
573  {
574  retval = mStream ? mStream->getTimeBase() : 0;
575  }
576 
577  return retval;
578 }

◆ getWidth()

int32_t com::avpkit::core::StreamCoder::getWidth ( )
virtual

The width, in pixels.

Returns
The width of the video frames in the attached stream or -1 if an audio stream, or we cannot determine the width.

Implements com::avpkit::core::IStreamCoder.

Definition at line 546 of file StreamCoder.cpp.

547 {
548  return (mCodecContext ? mCodecContext->width : -1);
549 }

◆ isOpen()

bool com::avpkit::core::StreamCoder::isOpen ( )
virtual

Returns true if this IStreamCoder is currently open.

Returns
true if open; false if not

Implements com::avpkit::core::IStreamCoder.

Definition at line 2183 of file StreamCoder.cpp.

2184 {
2185  return mOpened;
2186 }

Referenced by com::avpkit::core::Stream::setStreamCoder().

◆ open() [1/2]

int32_t com::avpkit::core::StreamCoder::open ( )
virtual
Deprecated:
Use open(IMetaData,IMetaData) instead.

Open the Codec associated with this StreamCoder.

You can get the codec through getCodec(...) and set it with setCodec(...). You cannot call any set* methods after you've called open() on this StreamCoder until you close() it.

You must call close() when you're done, but if you don't, the container will clean up after you (but yell at you) when it is closed.

Returns
>= 0 on success; < 0 on error.

Implements com::avpkit::core::IStreamCoder.

Definition at line 757 of file StreamCoder.cpp.

758 {
759  return open(NULL, NULL);
760 }

◆ open() [2/2]

int32_t com::avpkit::core::StreamCoder::open ( IMetaData options,
IMetaData unsetOptions 
)
virtual

Open the codec with the given options.

Callers must call setCodec before calling this method.

Parameters
optionsIf non-NULL, a dictionary of parameter options to set for this codec.
unsetOptionsIf non-NULL, on successful return the prior contents of this set of meta data will be replaced with any settings in 'options' that could not be set on this codec.
Returns
0 on success; <0 on error
Since
5.0

Implements com::avpkit::core::IStreamCoder.

Definition at line 762 of file StreamCoder.cpp.

763 {
764  int32_t retval = -1;
765  AVDictionary* tmp= NULL;
766  try
767  {
768  if (!swrContext)
769  swrContext = swr_alloc();
770  if (!mCodecContext)
771  throw std::runtime_error("no codec context");
772 
773  if (!mCodec)
774  {
775  RefPointer<ICodec> codec = this->getCodec();
776  // This should set mCodec and then release
777  // the local reference.
778  }
779 
780  if (!mCodec)
781  throw std::runtime_error("no codec set for coder");
782 
783  // Time to set options
784  if (aOptions) {
785  MetaData* options = static_cast<MetaData*>(aOptions);
786  if (!options)
787  throw new std::runtime_error("wow... who's passing us crap?");
788 
789  // make a copy of the data returned.
790  av_dict_copy(&tmp, options->getDictionary(), 0);
791  }
792 
793  // don't allow us to open a coder without a time base
794  if (mDirection == ENCODING && mCodecContext->time_base.num == 0)
795  {
796  if (this->getCodecType() == ICodec::CODEC_TYPE_AUDIO)
797  {
798  if (mCodecContext->sample_rate > 0)
799  {
800  mCodecContext->time_base.num = 1;
801  mCodecContext->time_base.den = mCodecContext->sample_rate;
802  }
803  else
804  {
805  throw std::runtime_error("no sample rate set on coder");
806  }
807  }
808  }
809 
810  if (mDirection == ENCODING && this->getCodecType() == ICodec::CODEC_TYPE_AUDIO && !mCodecContext->channel_layout)
811  {
812  mCodecContext->channel_layout = av_get_default_channel_layout(mCodecContext->channels);
813  }
814 
815  // Fix for issue #14: http://code.google.com/p/avpkit/issues/detail?id=14
816  if (mStream)
817  {
818  RefPointer<IContainer> container = mStream->getContainer();
819  if (container)
820  {
821  RefPointer<IContainerFormat> format = container->getContainerFormat();
822  if (format && mDirection == ENCODING && format->getOutputFlag(
823  IContainerFormat::FLAG_GLOBALHEADER))
824  {
825  this->setFlag(FLAG_GLOBAL_HEADER, true);
826  }
827  }
828  }
829 
830  {
831  /*
832  * This is a very annoying bug. FFmpeg will NOT find sub-codec options
833  * if AVCodecContext->codec is not set to a non-null value, but
834  * avcodec_open2 will fail if it is set null. To allow users to set
835  * options easily prior to opening the AVCodecContext, we stash the
836  * value we had been using, and we check after the open call and log
837  * an error if it changed for some reason.
838  */
839  //const AVCodec* cachedCodec = mCodecContext->codec;
840  //mCodecContext->codec = NULL;
841  retval = avcodec_open2(mCodecContext, mCodec->getAVCodec(), &tmp);
842 
843 // if (retval >= 0 && cachedCodec != 0 && cachedCodec != mCodecContext->codec)
844 // {
845 // VS_LOG_ERROR("When opening StreamCoder the codec was changed by FFmpeg. This is not good");
846 // }
847  if (retval < 0)
848  {
849  //mCodecContext->codec = cachedCodec;
850  throw std::runtime_error("could not open codec");
851  }
852  }
853 
854  if (mDirection == ENCODING && mStream) {
855  avcodec_parameters_from_context(mStream->getAVStream()->codecpar, mCodecContext);
856  }
857 
858  mOpened = true;
859 
860  mNumDroppedFrames = 0;
861  mSamplesCoded = mSamplesForEncoding = mLastExternallySetTimeStamp = 0;
862  mFakeCurrPts = mFakeNextPts = mLastPtsEncoded = Global::NO_PTS;
863  for(uint32_t i = 0; i < sizeof(mPtsBuffer)/sizeof(mPtsBuffer[0]); i++)
864  {
865  mPtsBuffer[i] = Global::NO_PTS;
866  }
867 
868  // Do any post open initialization here.
869  if (this->getCodecType() == ICodec::CODEC_TYPE_AUDIO)
870  {
871  int32_t frame_bytes = getAudioFrameSize() * getChannels()
873  (IAudioSamples::Format) mCodecContext->sample_fmt) / 8;
874  if (frame_bytes <= 0)
875  frame_bytes = 192000; //AVCODEC_MAX_AUDIO_FRAME_SIZE disappear
876 
877  if (!mAudioFrameBuffer || mAudioFrameBuffer->getBufferSize()
878  < frame_bytes)
879  // Re-create it.
880  mAudioFrameBuffer = IBuffer::make(this, frame_bytes);
881  mBytesInFrameBuffer = 0;
882  }
883  if (aUnsetOptions)
884  {
885  MetaData* unsetOptions = static_cast<MetaData*>(aUnsetOptions);
886  if (!unsetOptions)
887  throw std::runtime_error("really... seriously?");
888  unsetOptions->copy(tmp);
889  }
890  }
891  catch (std::bad_alloc & e)
892  {
893  throw e;
894  }
895  catch (std::exception & e)
896  {
897  VS_LOG_WARN("Error: %s", e.what());
898  retval = -1;
899  }
900  if (tmp)
901  av_dict_free(&tmp);
902  return retval;
903 }
@ FLAG_GLOBAL_HEADER
Place global headers in extradata instead of every keyframe.
Definition: IStreamCoder.h:82
virtual void setFlag(Flags flag, bool value)
Set the flag.
virtual Codec * getCodec()
The Codec this StreamCoder will use.
virtual IContainer * getContainer()
Get the underlying container for this stream, or null if AVPKit doesn't know.
Definition: Stream.cpp:269
static IBuffer * make(RefCounted *requestor, void *bufToWrap, int32_t bufferSize, FreeFunc freeFunc, void *closure)
Allocate a new buffer by wrapping a native buffer.
Definition: IBuffer.cpp:48

References com::avpkit::core::MetaData::copy(), and com::avpkit::core::MetaData::getDictionary().

◆ release()

int32_t com::avpkit::core::StreamCoder::release ( )
virtual

Internal Only.

DO NOT USE FROM JAVA.

This decrements the native internal ref count by -1; the object is destroyed if its ref count reaches zero.

This method is called internally by Ferry in Java, and you should not call it without knowing what you are doing. But if you do call it, make sure you had previously called acquire() once for each call to release() you make.

Returns
The ref count after the release. Note due to multi-threaded issues, you should not rely on this value, as it may change before the method returns to you.

Reimplemented from com::avpkit::ferry::RefCounted.

Definition at line 2076 of file StreamCoder.cpp.

2077 {
2078  int32_t retval = 0;
2079  retval = RefCounted::release();
2080  VS_LOG_TRACE("Released %p: %d", this, retval);
2081  return retval;
2082 }
virtual int32_t release()
Internal Only.
Definition: RefCounted.cpp:70

◆ setAutomaticallyStampPacketsForStream()

void com::avpkit::core::StreamCoder::setAutomaticallyStampPacketsForStream ( bool  value)
virtual

Should the IStreamCoder automatically adjust time stamps on output packets for the IStream it is ultimately destined for.

If this IStreamCoder does not know which IStream it is destined for, or this IStreamCoder isn't used with an IStream at all, then this setting is ignored.

Parameters
valuetrue to automatically adjust.
Since
3.2

Implements com::avpkit::core::IStreamCoder.

Definition at line 2233 of file StreamCoder.cpp.

2234 {
2235  // VS_LOG_DEBUG("setAutomaticallyStampPacketsForStream: %d", value);
2236  mAutomaticallyStampPacketsForStream = value;
2237 }

◆ setBitRate()

void com::avpkit::core::StreamCoder::setBitRate ( int32_t  rate)
virtual

When ENCODING, sets the bit rate to use.

No-op when DECODING.

See also
getBitRate()
Parameters
rateThe bit rate to use.

Implements com::avpkit::core::IStreamCoder.

Definition at line 516 of file StreamCoder.cpp.

517 {
518  if (mCodecContext && !mOpened)
519  mCodecContext->bit_rate = val;
520 }

◆ setBitRateTolerance()

void com::avpkit::core::StreamCoder::setBitRateTolerance ( int32_t  tolerance)
virtual

When ENCODING set the bit rate tolerance.

No-op when DECODING.

Parameters
toleranceThe bit rate tolerance

Implements com::avpkit::core::IStreamCoder.

Definition at line 527 of file StreamCoder.cpp.

528 {
529  if (mCodecContext && !mOpened)
530  mCodecContext->bit_rate_tolerance = val;
531 }

◆ setChannels()

void com::avpkit::core::StreamCoder::setChannels ( int32_t  channels)
virtual

Set the number of channels to use when ENCODING.

Ignored if a non audio stream, or if DECODING.

Parameters
channelsThe number of channels we'll encode with.

Implements com::avpkit::core::IStreamCoder.

Definition at line 696 of file StreamCoder.cpp.

697 {
698  if (mCodecContext && !mOpened && val > 0)
699  mCodecContext->channels = val;
700 }

◆ setCodec() [1/2]

void com::avpkit::core::StreamCoder::setCodec ( ICodec codec)
virtual

Set the Codec to the passed in Codec, discarding the old Codec if set.

Once you call setCodec, all settings on the IStreamCoder are reset to default values. So you probably want to call this first.

Parameters
codecCodec to set.

Implements com::avpkit::core::IStreamCoder.

Definition at line 207 of file StreamCoder.cpp.

208 {
209  Codec* codec = static_cast<Codec*>(aCodec);
210  const AVCodec* avCodec = NULL;
211 
212  if (!codec) {
213  VS_LOG_INFO("Cannot set codec to null codec");
214  return;
215  }
216  avCodec = codec->getAVCodec();
217 
218  if (!mCodecContext) {
219  VS_LOG_ERROR("No codec context");
220  return;
221  }
222 
223  if (mCodecContext->codec_id != AV_CODEC_ID_NONE || mCodecContext->codec) {
224  VS_LOG_INFO("Codec already set to codec: %d. Ignoring setCodec call",
225  mCodecContext->codec_id);
226  return;
227  }
228 
229  if (mCodec.value() == aCodec) {
230  // setting to the same value; don't reset anything
231  return;
232  }
233 
234  if (mCodecContext) {
235  // avcodec_get_context_defaults3 does not clear these out if already allocated
236  // so we do.
237  resetOptions(mCodecContext);
238  av_freep(&mCodecContext->extradata);
239  av_freep(&mCodecContext->subtitle_header);
240  avcodec_free_context(&mCodecContext);
241  }
242 
243  mCodecContext = avcodec_alloc_context3(avCodec);
244 
245  if (mCodecContext)
246  readyAVContexts(mDirection,
247  this,
248  mStream,
249  codec,
250  mCodecContext,
251  NULL);
252 }

Referenced by setCodecID().

◆ setCodec() [2/2]

void com::avpkit::core::StreamCoder::setCodec ( ICodec::ID  id)
virtual

Look up a Codec based on the passed in ID, and then set it.

To see if you actually set the correct ID, call getCodec() and check for 0 (null).

Once you call setCodec, all settings on the IStreamCoder are reset to default values. So you probably want to call this first.

Parameters
idID of codec to set.

Implements com::avpkit::core::IStreamCoder.

Definition at line 255 of file StreamCoder.cpp.

256 {
257  setCodec((int32_t) id);
258 }
virtual void setCodec(ICodec *)
Set the Codec to the passed in Codec, discarding the old Codec if set.

◆ setCodecID()

virtual void com::avpkit::core::StreamCoder::setCodecID ( ICodec::ID  id)
inlinevirtual

Look up a Codec based on the passed in ID, and then set it.

Forwards to setCodecID(com.avpkit.core.ICodec.ID)

To see if you actually set the correct ID, call getCodec() and check for 0 (null).

Once you call setCodec, all settings on the IStreamCoder are reset to default values. So you probably want to call this first.

Parameters
idID of codec to set.
Since
3.2

Implements com::avpkit::core::IStreamCoder.

Definition at line 53 of file StreamCoder.h.

53 { setCodec(id); }

References setCodec().

◆ setCodecTag()

void com::avpkit::core::StreamCoder::setCodecTag ( int32_t  fourcc)
virtual

Set the 4-byte FOURCC tag for this coder.

Parameters
fourccThe FOURCC to set, with Least Significant Byte first.

Implements com::avpkit::core::IStreamCoder.

Definition at line 2091 of file StreamCoder.cpp.

2092 {
2093  if (mCodecContext)
2094  mCodecContext->codec_tag = tag;
2095 }

◆ setDefaultAudioFrameSize()

void com::avpkit::core::StreamCoder::setDefaultAudioFrameSize ( int32_t  aNewSize)
virtual

Set the default audio frame size.

Parameters
aNewSizeThe new number of samples to use to encode samples into a packet. This setting is ignored if <= 0 or if the codec requires it's own frame size (e.g. Nellymoser).
See also
getDefaultAudioFrameSize()
Since
1.21

Implements com::avpkit::core::IStreamCoder.

Definition at line 2195 of file StreamCoder.cpp.

2196 {
2197  if (aNewSize > 0)
2198  mDefaultAudioFrameSize = aNewSize;
2199 }

◆ setExtraData()

int32_t com::avpkit::core::StreamCoder::setExtraData ( com::avpkit::ferry::IBuffer src,
int32_t  offset,
int32_t  length,
bool  allocNew 
)
virtual

Copies data from the given buffer into the extra-data area maintained by encoders.

This is an extremely advanced method, and incorrect usage can result in Java crashes so take care. In general people should not need to use this.

For some codecs (e.g. for H264, this is global header information and for rv10 it is additional flags), AVPKit maintains extra information about the codec in a extra data buffer. In general AVPKit will allocate this data as needed and you never need to set it (or get it). But if you know what you're doing, you can ask AVPKit to replace the existing extra data for the given codec with a copy of the data in the given buffer.

You should call this method after you call open() but before you encode or decode any media.

Parameters
srcThe data to copy
offsetThe position, in bytes, to start copying data from src
lengthThe number of bytes to copy from data
allocNewIf true, and there is not enough space in the existing extra data buffer, then AVPKit will discard the old buffer and allocate a new buffer. If false, then AVPKit will attempt to copy the data into the existing buffer and if there is not enough space in the existing buffer, no bytes will be copied and an error will be returned. In general, you should set this to false if that works for you.
Returns
The number of bytes copied, or < 0 on error.
Since
3.3

Implements com::avpkit::core::IStreamCoder.

Definition at line 2246 of file StreamCoder.cpp.

2248 {
2249  if (!mCodecContext || !src)
2250  return -1;
2251 
2252  void* bytes = src->getBytes(offset, numBytes);
2253  if (!bytes)
2254  return -1;
2255 
2256  if (mCodecContext->extradata_size < numBytes || !mCodecContext->extradata)
2257  {
2258  if (allocNew)
2259  {
2260  av_free(mCodecContext->extradata);
2261  mCodecContext->extradata_size = 0;
2262  mCodecContext->extradata = (uint8_t*) av_malloc(numBytes
2263  + AV_INPUT_BUFFER_MIN_SIZE);
2264  if (!mCodecContext->extradata)
2265  {
2266  return -1;
2267  }
2268  mCodecContext->extradata_size = numBytes;
2269  }
2270  else
2271  return -1;
2272  }
2273  memcpy(mCodecContext->extradata, bytes, numBytes);
2274 
2275  if (mStream) {
2276  avcodec_parameters_from_context(mStream->getAVStream()->codecpar, mCodecContext);
2277  }
2278  return numBytes;
2279 }

References com::avpkit::ferry::IBuffer::getBytes().

◆ setFlag()

void com::avpkit::core::StreamCoder::setFlag ( Flags  flag,
bool  value 
)
virtual

Set the flag.

Parameters
flagThe flag to set
valueThe value to set it to (true or false)

Implements com::avpkit::core::IStreamCoder.

Definition at line 740 of file StreamCoder.cpp.

741 {
742  if (mCodecContext)
743  {
744  if (value)
745  {
746  mCodecContext->flags |= flag;
747  }
748  else
749  {
750  mCodecContext->flags &= (~flag);
751  }
752  }
753 
754 }

◆ setFlags()

void com::avpkit::core::StreamCoder::setFlags ( int32_t  newFlags)
virtual

Set the FFMPEG flags to use with this codec.

All values must be ORed (|) together.

See also
Flags
Parameters
newFlagsThe new set flags for this codec.

Implements com::avpkit::core::IStreamCoder.

Definition at line 724 of file StreamCoder.cpp.

725 {
726  if (mCodecContext)
727  mCodecContext->flags = newFlags;
728 }

◆ setFrameRate()

void com::avpkit::core::StreamCoder::setFrameRate ( IRational newFrameRate)
virtual

Set the frame rate we'll set in the headers of this stream while ENCODING.

Note that you can set whatever frame-rate you'd like, but the TimeBase and the PTS you set on the encoded audio and video frames can override this.

As a convenience, we forward this call to the Stream::setFrameRate() method.

See also
getFrameRate()
Parameters
newFrameRateThe new frame rate to use.

Implements com::avpkit::core::IStreamCoder.

Definition at line 610 of file StreamCoder.cpp.

611 {
612  if (mStream && !mOpened)
613  mStream->setFrameRate(src);
614  if (mCodecContext && !mOpened && src){
615  mCodecContext->framerate.den = src->getDenominator();
616  mCodecContext->framerate.num = src->getNumerator();
617  }
618 
619 }

References com::avpkit::core::IRational::getDenominator(), and com::avpkit::core::IRational::getNumerator().

◆ setGlobalQuality()

void com::avpkit::core::StreamCoder::setGlobalQuality ( int32_t  newQuality)
virtual

Set the Global Quality to a new value.

Parameters
newQualityThe new global quality.

Implements com::avpkit::core::IStreamCoder.

Definition at line 709 of file StreamCoder.cpp.

710 {
711  if (newQuality < 0 || newQuality > FF_LAMBDA_MAX)
712  newQuality = FF_LAMBDA_MAX;
713  if (mCodecContext)
714  mCodecContext->global_quality = newQuality;
715 }

◆ setHardwareDecoding()

int32_t com::avpkit::core::StreamCoder::setHardwareDecoding ( IPixelFormat::Type  type,
void *  surface = NULL 
)
virtual

Try to change current decoder to an HW decoder compatible with pixel format.

Parameters
typean HW accelerated pixel format
Returns
0 on success; non-zero on failure

Implements com::avpkit::core::IStreamCoder.

Definition at line 2325 of file StreamCoder.cpp.

2326 {
2327  if (!(av_pix_fmt_desc_get((AVPixelFormat)type)->flags & AV_PIX_FMT_FLAG_HWACCEL)) {
2328  VS_LOG_WARN("Requested type is not hardware accelerated, default decoder will be used instead %d %d", av_pix_fmt_desc_get((AVPixelFormat)type)->flags, AV_PIX_FMT_FLAG_HWACCEL);
2329  return 0;
2330  }
2331 
2332  if (mCodecContext && mStream) {
2333  AVBufferRef* device_ctx = NULL;
2334  Codec* codec = Codec::findDecodingCodec(mCodec->getID(), type);
2335  if (!codec) {
2336  VS_LOG_WARN("No hardware decoder found for requested type, looking for hwaccel");
2337  for (int i = 0;; i++) {
2338  const AVCodecHWConfig *config = avcodec_get_hw_config(mCodec->getAVCodec(), i);
2339  if (!config) {
2340  VS_LOG_WARN("Decoder %s does not support any device type",
2341  mCodec->getAVCodec()->name);
2342  break;
2343  }
2344  if (config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX &&
2345  config->pix_fmt == (AVPixelFormat)type) {
2346  if (av_hwdevice_ctx_create(&device_ctx, config->device_type, NULL, NULL, 0) < 0) {
2347  VS_LOG_WARN("Unable to create device for type %s", av_hwdevice_get_type_name(config->device_type));
2348  return -1;
2349  }
2350  mCodecContext->hw_device_ctx = av_buffer_ref(device_ctx);
2351  return 0;
2352  }
2353  }
2354  if (!device_ctx) {
2355  VS_LOG_WARN("No hardware decoder found for requested type, default decoder will be used instead");
2356  return 0;
2357  }
2358  }
2359 
2360  avcodec_free_context(&mCodecContext);
2361  mCodecContext = avcodec_alloc_context3(codec->getAVCodec());
2362  if (mCodecContext){
2363  if (avcodec_parameters_to_context(mCodecContext, mStream->getAVStream()->codecpar) < 0)
2364  throw std::runtime_error("could not initialize codec");
2365  }
2366 
2367  readyAVContexts(mDirection,
2368  this,
2369  mStream,
2370  codec,
2371  mCodecContext,
2372  NULL);
2373 
2374  if (type == IPixelFormat::MEDIACODEC) {
2375  #ifdef __ANDROID__
2376  if (!mCodecContext->hwaccel_context && surface){
2377  jobject jSurface = static_cast<jobject>(surface);
2378  if (jSurface){
2379  mediacodec_alloc_context(mCodecContext, JNIHelper::sGetEnv(), jSurface);
2380  }
2381  }
2382  #elif __APPLE__
2383  #else
2384  VS_LOG_WARN("Try to use MediaCodec Android hardware type on non Android platform");
2385  #endif
2386  } else {
2387  VS_LOG_WARN("Hardware context not yet supported %s", mCodecContext->hwaccel->name);
2388  }
2389  } else {
2390  VS_LOG_WARN("try to set HW decoding on uninitialized AVContext or AVStream");
2391  }
2392  return 0;
2393 }
@ MEDIACODEC
HW decoding through Android MediaCodec
Definition: IPixelFormat.h:288

◆ setHeight()

void com::avpkit::core::StreamCoder::setHeight ( int32_t  height)
virtual

Set the height, in pixels.

See also
getHeight()
Parameters
heightSets the height of video frames we'll encode. No-op when DECODING.

Implements com::avpkit::core::IStreamCoder.

Definition at line 539 of file StreamCoder.cpp.

540 {
541  if (mCodecContext && !mOpened)
542  mCodecContext->height = val;
543 }

◆ setNumPicturesInGroupOfPictures()

void com::avpkit::core::StreamCoder::setNumPicturesInGroupOfPictures ( int32_t  gops)
virtual

Set the GOPS on this stream.

Ignored if DECODING.

See also
getNumPicturesInGroupOfPictures()
Parameters
gopsThe new GOPS for the stream we're encoding.

Implements com::avpkit::core::IStreamCoder.

Definition at line 628 of file StreamCoder.cpp.

629 {
630  if (mCodecContext && !mOpened)
631  mCodecContext->gop_size = val;
632 }

◆ setPixelType()

void com::avpkit::core::StreamCoder::setPixelType ( IPixelFormat::Type  pixelFmt)
virtual

Set the pixel format to ENCODE with.

Ignored if audio or DECODING.

Parameters
pixelFmtPixel format to use.

Implements com::avpkit::core::IStreamCoder.

Definition at line 654 of file StreamCoder.cpp.

655 {
656  if (mCodecContext && !mOpened)
657  {
658  mCodecContext->pix_fmt = (AVPixelFormat) type;
659  }
660 }

◆ setProperty() [1/5]

int32_t com::avpkit::core::StreamCoder::setProperty ( const char *  name,
bool  value 
)
virtual

Looks up the property 'name' and sets the value of the property to 'value'.

Parameters
namename of option
valueValue of option
Returns
>= 0 on success; <0 on error.

Implements com::avpkit::core::IStreamCoder.

Definition at line 2141 of file StreamCoder.cpp.

2142 {
2143  return Property::setProperty(mCodecContext, aName, aValue);
2144 }
static int32_t setProperty(void *context, const char *name, const char *value)
Looks up the property 'name' in 'context' and sets the value of the property to 'value'.
Definition: Property.cpp:201

◆ setProperty() [2/5]

int32_t com::avpkit::core::StreamCoder::setProperty ( const char *  name,
const char *  value 
)
virtual

Sets a property on this Object.

All AVOptions supported by the underlying AVClass are supported.

Parameters
nameThe property name. For example "b" for bit-rate.
valueThe value of the property.
Returns
>= 0 if the property was successfully set; <0 on error

Implements com::avpkit::core::IStreamCoder.

Definition at line 2123 of file StreamCoder.cpp.

2124 {
2125  return Property::setProperty(mCodecContext, aName, aValue);
2126 }

◆ setProperty() [3/5]

int32_t com::avpkit::core::StreamCoder::setProperty ( const char *  name,
double  value 
)
virtual

Looks up the property 'name' and sets the value of the property to 'value'.

Parameters
namename of option
valueValue of option
Returns
>= 0 on success; <0 on error.

Implements com::avpkit::core::IStreamCoder.

Definition at line 2129 of file StreamCoder.cpp.

2130 {
2131  return Property::setProperty(mCodecContext, aName, aValue);
2132 }

◆ setProperty() [4/5]

int32_t com::avpkit::core::StreamCoder::setProperty ( const char *  name,
int64_t  value 
)
virtual

Looks up the property 'name' and sets the value of the property to 'value'.

Parameters
namename of option
valueValue of option
Returns
>= 0 on success; <0 on error.

Implements com::avpkit::core::IStreamCoder.

Definition at line 2135 of file StreamCoder.cpp.

2136 {
2137  return Property::setProperty(mCodecContext, aName, aValue);
2138 }

◆ setProperty() [5/5]

int32_t com::avpkit::core::StreamCoder::setProperty ( const char *  name,
IRational value 
)
virtual

Looks up the property 'name' and sets the value of the property to 'value'.

Parameters
namename of option
valueValue of option
Returns
>= 0 on success; <0 on error.

Implements com::avpkit::core::IStreamCoder.

Definition at line 2147 of file StreamCoder.cpp.

2148 {
2149  return Property::setProperty(mCodecContext, aName, aValue);
2150 }

◆ setSampleFormat()

void com::avpkit::core::StreamCoder::setSampleFormat ( IAudioSamples::Format  aFormat)
virtual

Set the sample format when ENCODING.

Ignored if DECODING or if the coder is already open.

Parameters
aFormatThe sample format.

Implements com::avpkit::core::IStreamCoder.

Definition at line 683 of file StreamCoder.cpp.

684 {
685  if (mCodecContext && !mOpened && val > 0)
686  mCodecContext->sample_fmt = (enum AVSampleFormat) val;
687 }

◆ setSampleRate()

void com::avpkit::core::StreamCoder::setSampleRate ( int32_t  sampleRate)
virtual

Set the sample rate to use when ENCODING.

Ignored if DECODING or a non-audio stream.

Parameters
sampleRateNew sample rate (in Hz) to use.

Implements com::avpkit::core::IStreamCoder.

Definition at line 669 of file StreamCoder.cpp.

670 {
671  if (mCodecContext && !mOpened && val > 0)
672  mCodecContext->sample_rate = val;
673 }

◆ setStandardsCompliance()

int32_t com::avpkit::core::StreamCoder::setStandardsCompliance ( CodecStandardsCompliance  compliance)
virtual

Set the level of standards compliance.

Only paid attention to before the code is opened.

Parameters
complianceThe desired compliance level to set
Returns
0 on success; non-zero on failure
See also
CodecStandardsCompliance
Since
5.0

Implements com::avpkit::core::IStreamCoder.

Definition at line 2316 of file StreamCoder.cpp.

2317 {
2318  if (!mCodecContext)
2319  return -1;
2320  mCodecContext->strict_std_compliance = compliance;
2321  return 0;
2322 }

◆ setTimeBase()

void com::avpkit::core::StreamCoder::setTimeBase ( IRational newTimeBase)
virtual

Set the time base we'll use to ENCODE with.

A no-op when DECODING.

As a convenience, we forward this call to the Stream::setTimeBase() method.

See also
getTimeBase()
Parameters
newTimeBaseThe new time base to use.

Implements com::avpkit::core::IStreamCoder.

Definition at line 581 of file StreamCoder.cpp.

582 {
583  if (mCodecContext && src && !mOpened)
584  {
585  mCodecContext->time_base.num = src->getNumerator();
586  mCodecContext->time_base.den = src->getDenominator();
587  }
588  else
589  {
590  VS_LOG_INFO("Failed to setTimeBase on StreamCoder");
591  }
592 }

References com::avpkit::core::IRational::getDenominator(), and com::avpkit::core::IRational::getNumerator().

◆ setWidth()

void com::avpkit::core::StreamCoder::setWidth ( int32_t  width)
virtual

Set the width, in pixels.

See also
getWidth()
Parameters
widthSets the width of video frames we'll encode. No-op when DECODING.

Implements com::avpkit::core::IStreamCoder.

Definition at line 552 of file StreamCoder.cpp.

553 {
554  if (mCodecContext && !mOpened)
555  mCodecContext->width = val;
556 }

The documentation for this class was generated from the following files: