@@ -69,7 +69,7 @@ void set_uri(AVFormatContext *ctx, string_view uri)
6969#if AVCPP_API_AVFORMAT_URL
7070 if (ctx->url )
7171 av_free (ctx->url );
72- ctx->url = av_strdup (uri.data ());
72+ ctx->url = av_strndup (uri.data (), uri. size ());
7373#else
7474 av_strlcpy (ctx->filename , uri.data (), std::min<size_t >(sizeof (ctx->filename ), uri.size () + 1 ));
7575 ctx->filename [uri.size ()] = ' \0 ' ;
@@ -606,29 +606,42 @@ Packet FormatContext::readPacket(OptionalErrorCode ec)
606606
607607void FormatContext::openOutput (const string &uri, OptionalErrorCode ec)
608608{
609- return openOutput (uri, OutputFormat (), nullptr , ec);
609+ openOutput (uri, OutputFormat (), nullptr , ec);
610610}
611611
612612void FormatContext::openOutput (const string &uri, Dictionary &options, OptionalErrorCode ec)
613613{
614614 auto ptr = options.release ();
615- try
616- {
617- openOutput (uri, OutputFormat (), &ptr, ec);
618- options.assign (ptr);
619- }
620- catch (const Exception&)
621- {
615+ ScopeOutAction onScopeExit{[ptr, &options] {
622616 options.assign (ptr);
623- throw ;
624- }
617+ }} ;
618+ openOutput (uri, OutputFormat (), &ptr, ec);
625619}
626620
627621void FormatContext::openOutput (const string &uri, Dictionary &&options, OptionalErrorCode ec)
628622{
629623 return openOutput (uri, options, ec);
630624}
631625
626+ void FormatContext::openOutput (const std::string &uri, OutputFormat format, OptionalErrorCode ec)
627+ {
628+ openOutput (uri, format, nullptr , ec);
629+ }
630+
631+ void FormatContext::openOutput (const std::string &uri, Dictionary &options, OutputFormat format, OptionalErrorCode ec)
632+ {
633+ auto ptr = options.release ();
634+ ScopeOutAction onScopeExit{[ptr, &options] {
635+ options.assign (ptr);
636+ }};
637+ openOutput (uri, format, &ptr, ec);
638+ }
639+
640+ void FormatContext::openOutput (const std::string &uri, Dictionary &&options, OutputFormat format, OptionalErrorCode ec)
641+ {
642+ openOutput (uri, options, format, ec);
643+ }
644+
632645void FormatContext::openOutput (const string &uri, OutputFormat format, AVDictionary **options, OptionalErrorCode ec)
633646{
634647 clear_if (ec);
@@ -693,6 +706,57 @@ void FormatContext::openOutput(const string &uri, OutputFormat format, AVDiction
693706 m_isOpened = true ;
694707}
695708
709+ bool FormatContext::initOutput (Dictionary &options, bool closeOnError, OptionalErrorCode ec)
710+ {
711+ auto dict = options.release ();
712+ ScopeOutAction onScopeExit ([this , &dict, &options, ec, closeOnError](){
713+ options.assign (dict);
714+ // fflog(AV_LOG_ERROR, "init output.... done with %s\n", (is_error(ec) || std::uncaught_exceptions() > 0) ? "error" : "no error");
715+ if (closeOnError && (is_error (ec) || std::uncaught_exceptions () > 0 )) {
716+ close ();
717+ }
718+ });
719+ return initOutput (&dict, ec);
720+ }
721+
722+ bool FormatContext::initOutput (AVDictionary **options, OptionalErrorCode ec)
723+ {
724+ clear_if (ec);
725+
726+ if (!isOpened ()) {
727+ throws_if (ec, Errors::FormatNotOpened);
728+ return false ;
729+ }
730+
731+ if (!isOutput ()) {
732+ throws_if (ec, Errors::FormatInvalidDirection);
733+ return false ;
734+ }
735+
736+ // just silent it???
737+ if (m_headerWriten) {
738+ return true ;
739+ }
740+
741+ resetSocketAccess ();
742+ int ret = avformat_init_output (m_raw, options);
743+ ret = checkPbError (ret);
744+ if (ret < 0 ) {
745+ throws_if (ec, ret, ffmpeg_category ());
746+ return false ;
747+ }
748+
749+ fflog (AV_LOG_ERROR , " avformat_init_output: ret = %d\n " , ret);
750+
751+ switch (ret) {
752+ case AVSTREAM_INIT_IN_INIT_OUTPUT :
753+ return true ;
754+ case AVSTREAM_INIT_IN_WRITE_HEADER :
755+ default :
756+ return false ;
757+ }
758+ }
759+
696760void FormatContext::openOutput (CustomIO *io, OptionalErrorCode ec, size_t internalBufferSize)
697761{
698762 openCustomIOOutput (io, internalBufferSize, ec);
@@ -702,6 +766,66 @@ void FormatContext::openOutput(CustomIO *io, OptionalErrorCode ec, size_t intern
702766 }
703767}
704768
769+ bool FormatContext::openOutput (CustomIO *io, Dictionary &options, OptionalErrorCode ec, size_t internalBufferSize)
770+ {
771+ openOutput (io, ec, internalBufferSize);
772+ if (!is_error (ec)) {
773+ return initOutput (options, true , ec);
774+ }
775+ return false ;
776+ }
777+
778+ bool FormatContext::openOutput (CustomIO *io, Dictionary &&formatOptions, OptionalErrorCode ec, size_t internalBufferSize)
779+ {
780+ openOutput (io, ec, internalBufferSize);
781+ if (!is_error (ec)) {
782+ return initOutput (formatOptions, true , ec);
783+ }
784+ return false ;
785+ }
786+
787+ void FormatContext::openOutput (CustomIO *io, OutputFormat format, OptionalErrorCode ec, size_t internalBufferSize)
788+ {
789+ if (format.isNull ())
790+ format = outputFormat ();
791+ else
792+ setFormat (format);
793+ openOutput (io, ec, internalBufferSize);
794+ }
795+
796+ bool FormatContext::openOutput (CustomIO *io, Dictionary &formatOptions, OutputFormat format, OptionalErrorCode ec, size_t internalBufferSize)
797+ {
798+ openOutput (io, format, ec, internalBufferSize);
799+ if (!is_error (ec)) {
800+ return initOutput (formatOptions, true , ec);
801+ }
802+ return false ;
803+ }
804+
805+ bool FormatContext::openOutput (CustomIO *io, Dictionary &&formatOptions, OutputFormat format, OptionalErrorCode ec, size_t internalBufferSize)
806+ {
807+ openOutput (io, format, ec, internalBufferSize);
808+ if (!is_error (ec)) {
809+ return initOutput (formatOptions, true , ec);
810+ }
811+ return false ;
812+ }
813+
814+ bool FormatContext::initOutput (OptionalErrorCode ec)
815+ {
816+ return initOutput (nullptr , ec);
817+ }
818+
819+ bool FormatContext::initOutput (Dictionary &options, OptionalErrorCode ec)
820+ {
821+ return initOutput (options, false , ec);
822+ }
823+
824+ bool FormatContext::initOutput (Dictionary &&options, OptionalErrorCode ec)
825+ {
826+ return initOutput (options, false , ec);
827+ }
828+
705829void FormatContext::writeHeader (OptionalErrorCode ec)
706830{
707831 writeHeader (nullptr , ec);
@@ -729,6 +853,11 @@ void FormatContext::writeHeader(AVDictionary **options, OptionalErrorCode ec)
729853{
730854 clear_if (ec);
731855
856+ if (m_headerWriten) {
857+ // TBD: just silent it?
858+ return ;
859+ }
860+
732861 if (!isOpened ())
733862 {
734863 throws_if (ec, Errors::FormatNotOpened);
@@ -1051,6 +1180,12 @@ void FormatContext::openCustomIO(CustomIO *io, size_t internalBufferSize, bool i
10511180{
10521181 clear_if (ec);
10531182
1183+ if (!io) {
1184+ fflog (AV_LOG_ERROR , " Open CustomIO with null io context" );
1185+ throws_if (ec, Errors::InvalidArgument);
1186+ return ;
1187+ }
1188+
10541189 if (!m_raw)
10551190 {
10561191 throws_if (ec, Errors::Unallocated);
0 commit comments