27 #include <com/avpkit/ferry/JNIHelper.h>
28 #include <com/avpkit/ferry/Logger.h>
29 #include <com/avpkit/core/Container.h>
30 #include <com/avpkit/core/ContainerFormat.h>
31 #include <com/avpkit/core/Stream.h>
32 #include <com/avpkit/core/Packet.h>
33 #include <com/avpkit/core/Global.h>
34 #include <com/avpkit/core/Property.h>
35 #include <com/avpkit/core/MetaData.h>
36 #include <com/avpkit/ferry/IBuffer.h>
37 #include <com/avpkit/core/io/URLProtocolManager.h>
38 VS_LOG_SETUP(VS_CPP_PACKAGE);
40 #define AVPKIT_CHECK_INTERRUPT(retval) do { \
42 JNIHelper* helper = JNIHelper::getHelper(); \
43 if (helper && helper->isInterrupted()) \
44 (retval) = AVERROR(EINTR); \
54 Container_url_read(
void*h,
unsigned char* buf,
int size)
60 retval = handler->url_read(buf,size);
65 VS_LOG_TRACE(
"URLProtocolHandler[%p]->url_read(%p, %d) ==> %d", h, buf, size, retval);
69 Container_url_write(
void*h,
unsigned char* buf,
int size)
75 retval = handler->url_write(buf,size);
80 VS_LOG_TRACE(
"URLProtocolHandler[%p]->url_write(%p, %d) ==> %d", h, buf, size, retval);
84 Container_url_seek(
void*h, int64_t position,
int whence)
90 retval = handler->url_seek(position,whence);
95 VS_LOG_TRACE(
"URLProtocolHandler[%p]->url_seek(%p, %lld) ==> %d", h, position, whence, retval);
100 Container_io_open(
struct AVFormatContext *s, AVIOContext **pb,
const char *url,
int flags, AVDictionary **options)
109 handler->url_open(url, flags);
111 int bufferLength = 4096;
112 uint8_t* buffer = (uint8_t*) av_malloc(bufferLength);
114 throw std::bad_alloc();
117 *pb = avio_alloc_context(
124 handler->url_seekflags(url, 0) == URLProtocolHandler::SK_NOT_SEEKABLE ? NULL : Container_url_seek);
127 return AVERROR(ENOMEM);
139 Container_io_close(
struct AVFormatContext *s, AVIOContext *pb)
145 handler->url_close();
152 av_freep(&pb->buffer);
153 avio_context_free(&pb);
156 namespace com {
namespace avpkit {
namespace core
159 Container :: Container()
161 VS_LOG_TRACE(
"Making container: %p",
this);
162 mPacket = av_packet_alloc();
163 mBsfPacket = av_packet_alloc();
164 mFormatContext = avformat_alloc_context();
166 throw std::bad_alloc();
168 mFormatContext->interrupt_callback.callback = Global::avioInterruptCB;
169 mFormatContext->interrupt_callback.opaque =
this;
171 mIsMetaDataQueried=
false;
172 mNeedTrailerWrite =
false;
174 mInputBufferLength = 0;
176 mCustomIOHandler = 0;
179 Container :: ~Container()
184 av_packet_free(&mPacket);
187 av_packet_free(&mBsfPacket);
189 VS_LOG_TRACE(
"Destroyed container: %p",
this);
193 Container :: resetContext()
195 if (mFormatContext) {
196 if (mCustomIOHandler) {
197 if (mFormatContext->pb)
198 av_freep(&mFormatContext->pb->buffer);
199 av_freep(&mFormatContext->pb);
201 if (mFormatContext->opaque) {
202 delete mFormatContext->opaque;
203 mFormatContext->opaque = NULL;
205 avformat_free_context(mFormatContext);
215 VS_LOG_DEBUG(
"Closing dangling Container");
216 (void) this->close(
true);
218 if (mCustomIOHandler) {
219 if (mFormatContext) {
220 if(mFormatContext->pb)
221 av_freep(&mFormatContext->pb->buffer);
222 av_freep(&mFormatContext->pb);
224 delete mCustomIOHandler;
226 mCustomIOHandler = 0;
230 Container :: getFormatContext()
232 return mFormatContext;
236 Container :: setInputBufferLength(int32_t size)
241 VS_LOG_WARN(
"Attempting to set input buffer length while file is opened; ignoring");
245 mInputBufferLength = size;
252 Container :: getInputBufferLength()
254 return mInputBufferLength;
258 Container :: isOpened()
264 Container :: isHeaderWritten()
266 return (mIsOpened && mNeedTrailerWrite);
270 Container :: open(
const char *url,
Type type,
273 return open(url, type, pContainerFormat,
false,
true);
277 Container :: open(
const char *url,
Type type,
279 bool aStreamsCanBeAddedDynamically,
280 bool aLookForAllStreams)
282 return open(url, type, pContainerFormat,
283 aStreamsCanBeAddedDynamically, aLookForAllStreams,
287 Container :: open(
const char *url,
Type type,
289 bool aStreamsCanBeAddedDynamically,
290 bool aLookForAllStreams,
294 AVDictionary *tmp= NULL;
303 mFormatContext = avformat_alloc_context();
305 throw std::bad_alloc();
308 if (pContainerFormat)
309 setFormat(pContainerFormat);
312 mFormatContext->interrupt_callback.callback = Global::avioInterruptCB;
313 mFormatContext->interrupt_callback.opaque =
this;
316 mCustomIOHandler = URLProtocolManager::findHandler(
318 type == WRITE ? URLProtocolHandler::URL_WRONLY_MODE : URLProtocolHandler::URL_RDONLY_MODE,
320 if (mCustomIOHandler) {
321 if (mInputBufferLength <= 0)
323 mInputBufferLength = 4096;
325 uint8_t* buffer = (uint8_t*)av_malloc(mInputBufferLength);
327 throw std::bad_alloc();
330 mFormatContext->pb = avio_alloc_context(
333 type == WRITE ? 1 : 0,
337 mCustomIOHandler->url_seekflags(url,0) == URLProtocolHandler::SK_NOT_SEEKABLE ? NULL : Container_url_seek);
338 if (!mFormatContext->pb)
345 throw std::runtime_error(
"um, this shouldn't ever happen");
353 retval = openOutputURL(url,
354 aStreamsCanBeAddedDynamically, &tmp);
355 }
else if (type == READ)
357 retval = openInputURL(url,
358 aStreamsCanBeAddedDynamically, aLookForAllStreams, &tmp);
362 VS_ASSERT(
false,
"Invalid type for open");
366 AVPKIT_CHECK_INTERRUPT(retval);
370 throw std::runtime_error(
"a little part of me just died inside");
371 unsetOptions->
copy(tmp);
381 mFormatContext->opaque = (
void*)factory;
382 mFormatContext->io_open = ::Container_io_open;
383 mFormatContext->io_close = ::Container_io_close;
397 mFormatContext->strict_std_compliance = compliance;
405 Container :: getContainerFormat()
412 if (mFormatContext->iformat)
414 if (mFormatContext->oformat)
422 Container:: setupAllInputStreams()
425 if (mNumStreams == mFormatContext->nb_streams)
430 AVRational *goodTimebase = 0;
431 for(uint32_t i = 0;i < mFormatContext->nb_streams;i++){
432 AVStream *avStream = mFormatContext->streams[i];
433 if(avStream && avStream->time_base.num && avStream->time_base.den){
434 goodTimebase = &avStream->time_base;
440 for (uint32_t i =mNumStreams ; i < mFormatContext->nb_streams; i++)
442 AVStream *avStream = mFormatContext->streams[i];
445 if (goodTimebase && (!avStream->time_base.num || !avStream->time_base.den))
447 avStream->time_base = *goodTimebase;
451 Stream::make(
this, avStream,
452 (this->getType() == READ ?
453 IStream::INBOUND : IStream::OUTBOUND
461 mStreams.push_back(stream);
464 VS_LOG_ERROR(
"Couldn't make a stream %d", i);
471 VS_LOG_ERROR(
"Could not make Stream %d", i);
475 VS_LOG_ERROR(
"no FFMPEG allocated stream: %d", i);
483 Container :: openInputURL(
const char *url,
484 bool aStreamsCanBeAddedDynamically,
485 bool aLookForAllStreams,
486 AVDictionary** options)
489 AVInputFormat *inputFormat = NULL;
495 inputFormat = mFormat->getInputFormat();
498 if (mCustomIOHandler) {
499 retval = mCustomIOHandler->url_open(url, URLProtocolHandler::URL_RDONLY_MODE);
506 retval = avformat_open_input(
513 if (!mFormatContext && mFormatContext->iformat) {
519 format->setInputFormat(mFormatContext->iformat);
520 setFormat(format.
value());
524 if (aStreamsCanBeAddedDynamically)
526 mFormatContext->ctx_flags |= AVFMTCTX_NOHEADER;
529 if (aLookForAllStreams)
531 retval = queryStreamMetaData();
534 VS_LOG_DEBUG(
"Could not open input url: %s", url);
536 }
catch (std::exception &e) {
544 Container :: openOutputURL(
const char* url,
545 bool aStreamsCanBeAddedDynamically,
546 AVDictionary** options)
549 AVOutputFormat *outputFormat = NULL;
554 outputFormat = mFormat->getOutputFormat();
558 outputFormat = av_guess_format(NULL, url, NULL);
561 throw std::bad_alloc();
563 format->setOutputFormat(outputFormat);
564 setFormat(format.
value());
568 throw std::runtime_error(
"could not find output format");
570 if (aStreamsCanBeAddedDynamically)
572 mFormatContext->ctx_flags |= AVFMTCTX_NOHEADER;
574 mFormatContext->oformat = outputFormat;
578 AVFormatContext *s = mFormatContext;
579 if (!s->priv_data && s->oformat->priv_data_size > 0) {
580 s->priv_data = av_mallocz(s->oformat->priv_data_size);
582 throw std::bad_alloc();
583 if (s->oformat->priv_class) {
584 *(
const AVClass**)s->priv_data= s->oformat->priv_class;
585 av_opt_set_defaults(s->priv_data);
591 retval = av_opt_set_dict(mFormatContext, options);
593 throw std::runtime_error(
"could not set options");
595 if (!(mFormatContext->oformat->flags & AVFMT_NOFILE)) {
596 if (mCustomIOHandler) {
597 retval = mCustomIOHandler->url_open(url, URLProtocolHandler::URL_WRONLY_MODE);
599 retval = avio_open2(&mFormatContext->pb,
600 url, AVIO_FLAG_READ_WRITE,
601 &mFormatContext->interrupt_callback,
607 throw std::runtime_error(
"could not open file");
610 strncpy(mFormatContext->filename, url,
sizeof(mFormatContext->filename)-1);
612 mFormatContext->filename[
sizeof(mFormatContext->filename)-1] = 0;
613 }
catch (std::exception & e) {
614 VS_LOG_ERROR(
"URL: %s; Error: %s", url, e.what());
622 Container :: getType()
624 return (!mFormatContext ? READ :
625 (mFormatContext->oformat ? WRITE: READ));
629 Container :: getNumStreams()
634 if (mFormatContext->nb_streams != mNumStreams)
635 setupAllInputStreams();
636 retval = mFormatContext->nb_streams;
638 AVPKIT_CHECK_INTERRUPT(retval);
649 Container :: close(
bool dangling)
654 if (mFormatContext && mIsOpened)
656 VS_ASSERT(mNumStreams == mStreams.size(),
657 "unexpected number of streams");
659 if (mNeedTrailerWrite)
665 VS_LOG_ERROR(
"Disposing of dangling container but could not write trailer");
667 VS_LOG_DEBUG(
"Writing dangling trailer");
668 (void) this->writeTrailer();
670 mNeedTrailerWrite =
false;
674 while(mStreams.size() > 0)
678 VS_ASSERT(stream && *stream,
"no stream?");
679 if (stream && *stream) {
680 (*stream)->containerClosed(
this);
688 AVIOContext* pb = mFormatContext->pb;
690 if (this->getType() == READ)
691 avformat_close_input(&mFormatContext);
693 if (mCustomIOHandler) {
694 retval = mCustomIOHandler->url_close();
695 if (!mFormatContext) {
697 av_freep(&pb->buffer);
700 }
else if (this->getType() != READ)
701 retval = avio_close(pb);
707 mIsMetaDataQueried=
false;
709 AVPKIT_CHECK_INTERRUPT(retval);
714 Container :: getStream(int32_t position)
719 if (mFormatContext->nb_streams != mNumStreams)
720 setupAllInputStreams();
722 if (position < mNumStreams)
725 retval = (*mStreams.at(position)).get();
736 if (mFormatContext && pkt)
745 retval = av_read_frame(mFormatContext,
750 Stream* stream = this->getStream(mPacket->stream_index);
751 AVBSFContext* bsfContext = stream->getAVBsfContext();
752 VS_REF_RELEASE(stream);
755 if (retval = av_bsf_send_packet(bsfContext, mPacket) == 0) {
756 retval = av_bsf_receive_packet(bsfContext, mBsfPacket);
761 while (retval == AVERROR(EAGAIN) &&
762 (mReadRetryCount < 0 || numReads <= mReadRetryCount));
766 pkt->wrapAVPacket(mPacket);
768 pkt->wrapAVPacket(mBsfPacket);
770 av_packet_unref(mPacket);
771 av_packet_unref(mBsfPacket);
776 VS_LOG_TRACE(
"read-packet: %lld, %lld, %d, %d, %d, %lld, %lld: %p",
784 pkt->getAVPacket()->data);
800 AVPKIT_CHECK_INTERRUPT(retval);
806 return writePacket(ipkt,
true);
809 Container :: writePacket(
IPacket *ipkt,
bool forceInterleave)
815 if (this->getType() != WRITE)
816 throw std::runtime_error(
"cannot write packet to read only container");
819 throw std::logic_error(
"no format context");
822 throw std::runtime_error(
"cannot write missing packet");
825 throw std::runtime_error(
"cannot write incomplete packet");
830 if (!mNeedTrailerWrite)
831 throw std::runtime_error(
"container has not written header yet");
835 if ((uint32_t)pktIndex >= mNumStreams)
836 throw std::runtime_error(
"packet being written to stream that doesn't exist");
839 if (!streamPtr || !*streamPtr)
840 throw std::runtime_error(
"no stream set up for this packet");
849 throw std::runtime_error(
"could not stamp output packet");
851 AVPacket *packet = 0;
852 packet = outPacket->getAVPacket();
853 if (!packet || !packet->data)
854 throw std::runtime_error(
"no data in packet");
869 retval = av_interleaved_write_frame(mFormatContext, packet);
871 retval = av_write_frame(mFormatContext, packet);
873 catch (std::exception & e)
875 VS_LOG_ERROR(
"Error: %s", e.what());
878 AVPKIT_CHECK_INTERRUPT(retval);
883 Container :: writeHeader()
887 if (this->getType() != WRITE)
888 throw std::runtime_error(
"cannot write packet to read only container");
891 throw std::runtime_error(
"no format context allocated");
901 int numStreams = getNumStreams();
902 if (numStreams < 0 &&
903 !(mFormatContext->ctx_flags & AVFMTCTX_NOHEADER))
904 throw std::runtime_error(
"no streams added to container");
911 const char *shortName = format->getOutputFormatShortName();
912 if (shortName && !strcmp(shortName,
"mp3"))
913 throw std::runtime_error(
"no streams added to mp3 container");
916 for(
int i = 0; i < numStreams; i++)
926 mOpenCoders.push_back(coder);
928 VS_LOG_TRACE(
"writing Header for container, but at least one codec (%d) is not opened first", i);
932 retval = avformat_write_header(mFormatContext,0);
934 throw std::runtime_error(
"could not write header for container");
937 if (!(mFormatContext->oformat->flags & AVFMT_NOFILE)) {
938 avio_flush(mFormatContext->pb);
941 mNeedTrailerWrite =
true;
943 catch (std::exception & e)
945 VS_LOG_ERROR(
"Error: %s", e.what());
948 AVPKIT_CHECK_INTERRUPT(retval);
952 Container :: writeTrailer()
957 if (this->getType() != WRITE)
958 throw std::runtime_error(
"cannot write packet to read only container");
961 throw std::runtime_error(
"no format context allocated");
963 if (mNeedTrailerWrite)
965 while(mOpenCoders.size()>0)
968 mOpenCoders.pop_front();
969 if (!coder->isOpen())
972 throw std::runtime_error(
"attempt to write trailer, but at least one used codec already closed");
975 retval = av_write_trailer(mFormatContext);
978 if (!(mFormatContext->oformat->flags & AVFMT_NOFILE)) {
979 avio_flush(mFormatContext->pb);
983 VS_LOG_WARN(
"writeTrailer() with no matching call to writeHeader()");
986 catch (std::exception & e)
988 VS_LOG_ERROR(
"Error: %s", e.what());
993 mNeedTrailerWrite =
false;
994 AVPKIT_CHECK_INTERRUPT(retval);
999 Container :: queryStreamMetaData()
1004 if (!mIsMetaDataQueried)
1006 retval = avformat_find_stream_info(mFormatContext, NULL);
1009 mIsMetaDataQueried =
true;
1014 if (retval >= 0 && mFormatContext->nb_streams > 0)
1016 setupAllInputStreams();
1018 VS_LOG_WARN(
"Could not find streams in input container");
1023 VS_LOG_WARN(
"Attempt to queryStreamMetaData but container is not open");
1025 AVPKIT_CHECK_INTERRUPT(retval);
1030 Container :: seekKeyFrame(int32_t streamIndex, int64_t timestamp, int32_t flags)
1032 int32_t retval = -1;
1036 if (streamIndex >= (int32_t)mNumStreams)
1037 VS_LOG_WARN(
"Attempt to seek on streamIndex %d but only %d streams known about in container",
1038 streamIndex, mNumStreams);
1040 retval = av_seek_frame(mFormatContext, streamIndex, timestamp, flags);
1044 VS_LOG_WARN(
"Attempt to seekKeyFrame but container is not open");
1046 AVPKIT_CHECK_INTERRUPT(retval);
1051 Container :: seekKeyFrame(int32_t streamIndex, int64_t minTimeStamp,
1052 int64_t targetTimeStamp, int64_t maxTimeStamp, int32_t flags)
1054 int32_t retval = -1;
1058 if (streamIndex >= (int32_t)mNumStreams)
1059 VS_LOG_WARN(
"Attempt to seek on streamIndex %d but only %d streams known about in container",
1060 streamIndex, mNumStreams);
1062 retval = avformat_seek_file(mFormatContext, streamIndex,
1070 VS_LOG_WARN(
"Attempt to seekKeyFrame but container is not open");
1072 AVPKIT_CHECK_INTERRUPT(retval);
1077 Container :: getDuration()
1079 int64_t retval = Global::NO_PTS;
1080 queryStreamMetaData();
1082 retval = mFormatContext->duration;
1087 Container :: getStartTime()
1089 int64_t retval = Global::NO_PTS;
1090 queryStreamMetaData();
1092 retval = mFormatContext->start_time;
1097 Container :: getFileSize()
1099 int64_t retval = -1;
1100 queryStreamMetaData();
1101 if (mFormatContext) {
1102 if (mFormatContext->iformat && mFormatContext->iformat->flags & AVFMT_NOFILE)
1105 retval = avio_size(mFormatContext->pb);
1106 retval = FFMAX(0, retval);
1113 Container :: getBitRate()
1115 int32_t retval = -1;
1116 queryStreamMetaData();
1118 retval = mFormatContext->bit_rate;
1123 Container :: setPreload(int32_t)
1125 VS_LOG_WARN(
"Deprecated and will be removed; does nothing now.");
1130 Container :: getPreload()
1132 VS_LOG_WARN(
"Deprecated and will be removed; does nothing now.");
1137 Container :: setMaxDelay(int32_t maxdelay)
1139 int32_t retval = -1;
1140 if (mIsOpened || !mFormatContext)
1142 VS_LOG_WARN(
"Attempting to set max delay while file is opened; ignoring");
1146 mFormatContext->max_delay = maxdelay;
1153 Container :: getMaxDelay()
1155 int32_t retval = -1;
1157 retval = mFormatContext->max_delay;
1162 Container :: getNumProperties()
1164 return Property::getNumProperties(mFormatContext);
1168 Container :: getPropertyMetaData(int32_t propertyNo)
1170 return Property::getPropertyMetaData(mFormatContext, propertyNo);
1174 Container :: getPropertyMetaData(
const char *name)
1176 return Property::getPropertyMetaData(mFormatContext, name);
1182 return Property::setProperty(mFormatContext, valuesToSet, valuesNotFound);
1186 Container :: setProperty(
const char* aName,
const char *aValue)
1188 return Property::setProperty(mFormatContext, aName, aValue);
1192 Container :: setProperty(
const char* aName,
double aValue)
1194 return Property::setProperty(mFormatContext, aName, aValue);
1198 Container :: setProperty(
const char* aName, int64_t aValue)
1200 return Property::setProperty(mFormatContext, aName, aValue);
1204 Container :: setProperty(
const char* aName,
bool aValue)
1206 return Property::setProperty(mFormatContext, aName, aValue);
1211 Container :: setProperty(
const char* aName,
IRational *aValue)
1213 return Property::setProperty(mFormatContext, aName, aValue);
1218 Container :: getPropertyAsString(
const char *aName)
1220 return Property::getPropertyAsString(mFormatContext, aName);
1224 Container :: getPropertyAsDouble(
const char *aName)
1226 return Property::getPropertyAsDouble(mFormatContext, aName);
1230 Container :: getPropertyAsLong(
const char *aName)
1232 return Property::getPropertyAsLong(mFormatContext, aName);
1236 Container :: getPropertyAsRational(
const char *aName)
1238 return Property::getPropertyAsRational(mFormatContext, aName);
1242 Container :: getPropertyAsBoolean(
const char *aName)
1244 return Property::getPropertyAsBoolean(mFormatContext, aName);
1248 Container :: getFlags()
1250 int32_t flags = (mFormatContext ? mFormatContext->flags : 0);
1252 flags &= ~(AVFMT_FLAG_CUSTOM_IO);
1257 Container :: setFlags(int32_t newFlags)
1259 if (mFormatContext) {
1260 mFormatContext->flags = newFlags;
1262 mFormatContext->flags |= AVFMT_FLAG_CUSTOM_IO;
1267 Container :: getFlag(IContainer::Flags flag)
1269 bool result =
false;
1271 result = mFormatContext->flags& flag;
1276 Container :: setFlag(IContainer::Flags flag,
bool value)
1282 mFormatContext->flags |= flag;
1286 mFormatContext->flags &= (~flag);
1293 Container :: getURL()
1295 return mFormatContext && *mFormatContext->filename ? mFormatContext->filename : 0;
1299 Container :: flushPackets()
1301 int32_t retval = -1;
1304 if (this->getType() != WRITE)
1305 throw std::runtime_error(
"cannot write packet to read only container");
1307 if (!mFormatContext)
1308 throw std::runtime_error(
"no format context allocated");
1311 if (!(mFormatContext->oformat->flags & AVFMT_NOFILE)) {
1312 avio_flush(mFormatContext->pb);
1316 catch (std::exception & e)
1318 VS_LOG_ERROR(
"Error: %s", e.what());
1321 AVPKIT_CHECK_INTERRUPT(retval);
1326 Container :: getReadRetryCount()
1328 return mReadRetryCount;
1332 Container :: setReadRetryCount(int32_t aCount)
1334 mReadRetryCount = aCount;
1340 int32_t retval = -1;
1344 throw std::runtime_error(
"no format set");
1346 if (!mFormatContext)
1347 throw std::runtime_error(
"no underlying AVFormatContext");
1348 if (mFormatContext->iformat || mFormatContext->oformat)
1349 throw std::runtime_error(
"format already set on this IContainer; cannot be reset");
1351 throw std::runtime_error(
"container already opened");
1353 AVOutputFormat* oformat = format->getOutputFormat();
1354 AVInputFormat* iformat = format->getInputFormat();
1356 if (!iformat && !oformat)
1357 throw std::runtime_error(
"no input or output format set");
1361 mFormatContext->iformat = iformat;
1362 mFormatContext->oformat = 0;
1367 if (avformat_alloc_output_context2(&mFormatContext, oformat, 0, 0)<0)
1368 throw std::runtime_error(
"could not allocate output context");
1370 mFormat.reset(format,
true);
1372 }
catch (std::exception &e)
1379 Container :: canStreamsBeAddedDynamically()
1382 return mFormatContext->ctx_flags & AVFMTCTX_NOHEADER;
1387 Container :: getMetaData()
1389 if (!mMetaData && mFormatContext)
1391 if (this->getType() == WRITE)
1392 mMetaData = MetaData::make(&mFormatContext->metadata);
1396 mMetaData = MetaData::make(mFormatContext->metadata);
1398 return mMetaData.get();
1415 if (!mFormatContext)
1424 char* bytes =
static_cast<char*
>(buffer->
getBytes(0, bufSize));
1432 int32_t ret = av_sdp_create(&mFormatContext, 1, bytes, bufSize-1);
1436 VS_LOG_INFO(
"Could not create SDP file: %d", ret);
1441 ret = strlen(bytes)+1;
1449 if (mFormatContext &&
id != ICodec::AV_CODEC_ID_NONE)
1452 if (codec && codec->getType() == ICodec::CODEC_TYPE_AUDIO)
1453 mFormatContext->audio_codec_id = (
enum AVCodecID)
id;
1462 if (mFormatContext &&
id != ICodec::AV_CODEC_ID_NONE)
1465 if (codec && codec->getType() == ICodec::CODEC_TYPE_VIDEO)
1466 mFormatContext->video_codec_id = (
enum AVCodecID)
id;
1475 if (mFormatContext &&
id != ICodec::AV_CODEC_ID_NONE)
1478 if (codec && codec->getType() == ICodec::CODEC_TYPE_SUBTITLE)
1479 mFormatContext->subtitle_codec_id = (
enum AVCodecID)
id;
1491 codec = ICodec::findEncodingCodec(
id);
1494 VS_LOG_ERROR(
"Could not find encoding codec: %d",
id);
1495 throw std::runtime_error(
"Could not find encoding codec");
1497 retval = addNewStream(codec.
value());
1499 catch (std::exception & e)
1501 VS_LOG_DEBUG(
"Error: %s", e.what());
1502 VS_REF_RELEASE(retval);
1514 const AVCodec* avCodec = codec ? codec->getAVCodec() : 0;
1516 if (!mFormatContext)
1517 throw std::runtime_error(
"no format context");
1520 throw std::runtime_error(
"attempted to add stream to "
1521 " unopened container");
1523 if (isHeaderWritten())
1524 throw std::runtime_error(
"cannot add stream after header is written"
1527 AVStream * stream=0;
1528 stream = avformat_new_stream(mFormatContext, avCodec);
1532 throw std::runtime_error(
"could not allocate stream");
1535 Stream::make(
this, stream, IStream::OUTBOUND, avCodec)
1537 if (!p)
throw std::bad_alloc();
1540 mStreams.push_back(p);
1547 throw std::bad_alloc();
1549 }
catch (std::exception & e)
1551 VS_LOG_DEBUG(
"Error: %s", e.what());
1552 VS_REF_RELEASE(retval);
1566 throw std::runtime_error(
"must pass non-null coder");
1569 throw std::runtime_error(
"StreamCoder has no attached Codec");
1571 retval = this->addNewStream(codec.
value());
1575 throw std::runtime_error(
"Could not set StreamCoder on stream");
1578 }
catch (std::exception & e)
1580 VS_LOG_DEBUG(
"addNewStream Error: %s", e.what());
1581 VS_REF_RELEASE(retval);
1587 Container :: addNewStream(int32_t
id)
1590 retval = addNewStream((
ICodec*)0);
1600 retval = Container::make();
1603 VS_REF_RELEASE(retval);
virtual int32_t setFormat(IContainerFormat *format)
Set the IContainerFormat to use with this IContainer.
A "key" to an IStreamCoder that tells it how to encode or decode data.
ID
These are the codecs this library currently supports.
Type
The different types of Containers AVPKit supports.
Represents an encoded piece of data that can be placed in an IContainer for a given IStream of data.
Represents settable properties that effect how AVPKit objects operate.
This class wraps represents a Rational number for the AVPKit.
The work horse of the AVPKit: Takes IPacket data from an IContainer (representing an IStream) and an ...
CodecStandardsCompliance
An enumeration of how strictly Codecs may follow the spec.
virtual int64_t getPts()
Get the Presentation Time Stamp (PTS) for this packet.
virtual int32_t getSize()
Get the size in bytes of the payload currently in this packet.
virtual int32_t getFlags()
Get any flags set on this packet, as a 4-byte binary-ORed bit-mask.
virtual bool isComplete()
Is this packet complete.
virtual int32_t getStreamIndex()
Get the container-specific index for the stream this packet is part of.
virtual void setTimeBase(IRational *aBase)
Set the time base that time stamps of this object are represented in.
virtual int64_t getPosition()
Return the position (in bytes) of this packet in the stream.
virtual int64_t getDts()
Get the Decompression Time Stamp (DTS) for this packet.
virtual int64_t getDuration()
Return the duration of this packet, in units of getTimeBase().
virtual Codec * getCodec()
The Codec this StreamCoder will use.
virtual int32_t stampOutputPacket(IPacket *packet)
Takes a packet destined for this stream, and stamps the stream index, and converts the time stamp to ...
virtual int32_t setStreamCoder(IStreamCoder *coder)
Sets the stream coder to use for this stream.
void setId(int32_t id)
Set the format-specific stream id.
A class for managing custom io protocols.
virtual URLProtocolHandler * getHandler(const char *url, int flags)=0
Returns a URLProtocol handler for the given url and flags.
Allows Java code to get data from a native buffers, and optionally modify native memory directly.
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.
virtual int32_t release()
Internal Only.
This class is only useful from C++.
T * get()
Call RefCounted::acquire() on the managed pointer and return it.
T * value()
Return the managed pointer without calling RefCounted::acquire() on it.
This package contains the AVPKIT IO library which is used to register callbacks for FFMPEG to get and...
This library contains routines used by AVPKit libraries for "ferry"ing Java objects to and from nativ...
WARNING: Do not use logging in this class, and do not set any static file variables to values other t...