diff --git a/src/media/libav_deps.h b/src/media/libav_deps.h index c3dd6d69b52985e8c50e9a0c13627cdbef036206..8983445855fcdfb40186da9dc16c40d5e9b7eea7 100644 --- a/src/media/libav_deps.h +++ b/src/media/libav_deps.h @@ -100,5 +100,9 @@ static inline const AVPixFmtDescriptor *av_pix_fmt_desc_get(enum AVPixelFormat p (x)->width, (x)->height) #endif +#if LIBAVCODEC_VERSION_CHECK(57, 25, 0, 24, 102) +#define av_free_packet av_packet_unref +#endif + #endif // __LIBAV_DEPS_H__ diff --git a/src/media/media_buffer.cpp b/src/media/media_buffer.cpp index 8f182f973880eb60113144a59725e08b9464eee3..8d116f49c5cf48b285d91d5a839a68301e0d2461 100644 --- a/src/media/media_buffer.cpp +++ b/src/media/media_buffer.cpp @@ -125,8 +125,13 @@ VideoFrame::setFromMemory(uint8_t* ptr, int format, int width, int height) noexc setGeometry(format, width, height); if (not ptr) return; +#if LIBAVCODEC_VERSION_CHECK(57, 25, 0, 24, 102) + av_image_fill_arrays(frame_->data, frame_->linesize, (uint8_t*)ptr, + (AVPixelFormat)frame_->format, width, height, 1); +#else avpicture_fill((AVPicture*)frame_.get(), (uint8_t*)ptr, (AVPixelFormat)frame_->format, width, height); +#endif } void @@ -155,9 +160,16 @@ VideoFrame& VideoFrame::operator =(const VideoFrame& src) { reserve(src.format(), src.width(), src.height()); +#if LIBAVCODEC_VERSION_CHECK(57, 25, 0, 24, 102) + auto source = src.pointer(); + av_image_copy(frame_->data, frame_->linesize, (const uint8_t **)source->data, + source->linesize, (AVPixelFormat)frame_->format, + frame_->width, frame_->height); +#else av_picture_copy((AVPicture *)frame_.get(), (AVPicture *)src.pointer(), (AVPixelFormat)frame_->format, frame_->width, frame_->height); +#endif return *this; } @@ -166,8 +178,13 @@ VideoFrame::operator =(const VideoFrame& src) std::size_t videoFrameSize(int format, int width, int height) { +#if LIBAVCODEC_VERSION_CHECK(57, 25, 0, 24, 102) + return av_image_get_buffer_size((AVPixelFormat)libav_utils::libav_pixel_format(format), + width, height, 1); +#else return avpicture_get_size((AVPixelFormat)libav_utils::libav_pixel_format(format), width, height); +#endif } void diff --git a/src/media/media_decoder.cpp b/src/media/media_decoder.cpp index 6f137cd3b75e024c55430761747b5ab1b86cc51e..055bb4a17f3ac09b124520327c0ed26f9ffa7e7a 100644 --- a/src/media/media_decoder.cpp +++ b/src/media/media_decoder.cpp @@ -170,7 +170,11 @@ int MediaDecoder::setupFromAudioData(const AudioFormat format) // find the first audio stream from the input for (size_t i = 0; streamIndex_ == -1 && i < inputCtx_->nb_streams; ++i) +#if LIBAVFORMAT_VERSION_CHECK(57, 7, 2, 40, 101) && !defined(_WIN32) + if (inputCtx_->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) +#else if (inputCtx_->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) +#endif streamIndex_ = i; if (streamIndex_ == -1) { @@ -180,6 +184,16 @@ int MediaDecoder::setupFromAudioData(const AudioFormat format) // Get a pointer to the codec context for the video stream avStream_ = inputCtx_->streams[streamIndex_]; +#if LIBAVFORMAT_VERSION_CHECK(57, 7, 2, 40, 101) && !defined(_WIN32) + inputDecoder_ = avcodec_find_decoder(avStream_->codecpar->codec_id); + if (!inputDecoder_) { + RING_ERR("Unsupported codec"); + return -1; + } + + decoderCtx_ = avcodec_alloc_context3(inputDecoder_); + avcodec_parameters_to_context(decoderCtx_, avStream_->codecpar); +#else decoderCtx_ = avStream_->codec; if (decoderCtx_ == 0) { RING_ERR("Decoder context is NULL"); @@ -192,6 +206,7 @@ int MediaDecoder::setupFromAudioData(const AudioFormat format) RING_ERR("Unsupported codec"); return -1; } +#endif decoderCtx_->thread_count = std::thread::hardware_concurrency(); decoderCtx_->channels = format.nb_channels; @@ -253,7 +268,11 @@ int MediaDecoder::setupFromVideoData() // find the first video stream from the input for (size_t i = 0; streamIndex_ == -1 && i < inputCtx_->nb_streams; ++i) +#if LIBAVFORMAT_VERSION_CHECK(57, 7, 2, 40, 101) && !defined(_WIN32) + if (inputCtx_->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) +#else if (inputCtx_->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) +#endif streamIndex_ = i; if (streamIndex_ == -1) { @@ -263,12 +282,30 @@ int MediaDecoder::setupFromVideoData() // Get a pointer to the codec context for the video stream avStream_ = inputCtx_->streams[streamIndex_]; +#if LIBAVFORMAT_VERSION_CHECK(57, 7, 2, 40, 101) && !defined(_WIN32) + inputDecoder_ = avcodec_find_decoder(avStream_->codecpar->codec_id); + if (!inputDecoder_) { + RING_ERR("Unsupported codec"); + return -1; + } + + decoderCtx_ = avcodec_alloc_context3(inputDecoder_); + avcodec_parameters_to_context(decoderCtx_, avStream_->codecpar); +#else decoderCtx_ = avStream_->codec; if (decoderCtx_ == 0) { RING_ERR("Decoder context is NULL"); return -1; } + // find the decoder for the video stream + inputDecoder_ = avcodec_find_decoder(decoderCtx_->codec_id); + if (!inputDecoder_) { + RING_ERR("Unsupported codec"); + return -1; + } +#endif + decoderCtx_->thread_count = std::thread::hardware_concurrency(); #ifdef RING_ACCEL @@ -278,13 +315,6 @@ int MediaDecoder::setupFromVideoData() } #endif // RING_ACCEL - // find the decoder for the video stream - inputDecoder_ = avcodec_find_decoder(decoderCtx_->codec_id); - if (!inputDecoder_) { - RING_ERR("Unsupported codec"); - return -1; - } - if (emulateRate_) { RING_DBG("Using framerate emulation"); startTime_ = av_gettime(); @@ -331,12 +361,24 @@ MediaDecoder::decode(VideoFrame& result) auto frame = result.pointer(); int frameFinished = 0; - int len = avcodec_decode_video2(decoderCtx_, frame, - &frameFinished, &inpacket); - av_packet_unref(&inpacket); +#if LIBAVCODEC_VERSION_CHECK(57, 25, 0, 48, 101) + ret = avcodec_send_packet(decoderCtx_, &inpacket); + if (ret < 0) + return ret == AVERROR_EOF ? Status::Success : Status::DecodeError; - if (len <= 0) + ret = avcodec_receive_frame(decoderCtx_, frame); + if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) + return Status::DecodeError; + if (ret >= 0) + frameFinished = 1; +#else + ret = avcodec_decode_video2(decoderCtx_, frame, + &frameFinished, &inpacket); + if (ret <= 0) return Status::DecodeError; +#endif + + av_packet_unref(&inpacket); if (frameFinished) { frame->format = (AVPixelFormat) correctPixFmt(frame->format); @@ -348,8 +390,13 @@ MediaDecoder::decode(VideoFrame& result) return Status::RestartRequired; } #endif // RING_ACCEL +#if LIBAVUTIL_VERSION_CHECK(55, 20, 0, 34, 100) + if (emulateRate_ and frame->pts != AV_NOPTS_VALUE) { + auto frame_time = getTimeBase()*(frame->pts - avStream_->start_time); +#else if (emulateRate_ and frame->pkt_pts != AV_NOPTS_VALUE) { auto frame_time = getTimeBase()*(frame->pkt_pts - avStream_->start_time); +#endif auto target = startTime_ + static_cast<std::int64_t>(frame_time.real() * 1e6); auto now = av_gettime(); if (target > now) { @@ -390,17 +437,34 @@ MediaDecoder::decode(const AudioFrame& decodedFrame) } int frameFinished = 0; - int len = avcodec_decode_audio4(decoderCtx_, frame, +#if LIBAVCODEC_VERSION_CHECK(57, 25, 0, 48, 101) + ret = avcodec_send_packet(decoderCtx_, &inpacket); + if (ret < 0) + return ret == AVERROR_EOF ? Status::Success : Status::DecodeError; + + ret = avcodec_receive_frame(decoderCtx_, frame); + if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) + return Status::DecodeError; + if (ret >= 0) + frameFinished = 1; +#else + ret = avcodec_decode_audio4(decoderCtx_, frame, &frameFinished, &inpacket); av_packet_unref(&inpacket); - if (len <= 0) { + if (ret <= 0) return Status::DecodeError; - } +#endif if (frameFinished) { + av_packet_unref(&inpacket); +#if LIBAVUTIL_VERSION_CHECK(55, 20, 0, 34, 100) + if (emulateRate_ and frame->pts != AV_NOPTS_VALUE) { + auto frame_time = getTimeBase()*(frame->pts - avStream_->start_time); +#else if (emulateRate_ and frame->pkt_pts != AV_NOPTS_VALUE) { auto frame_time = getTimeBase()*(frame->pkt_pts - avStream_->start_time); +#endif auto target = startTime_ + static_cast<std::int64_t>(frame_time.real() * 1e6); auto now = av_gettime(); if (target > now) { @@ -421,15 +485,28 @@ MediaDecoder::flush(VideoFrame& result) av_init_packet(&inpacket); int frameFinished = 0; - auto len = avcodec_decode_video2(decoderCtx_, result.pointer(), + int ret = 0; +#if LIBAVCODEC_VERSION_CHECK(57, 25, 0, 48, 101) + ret = avcodec_send_packet(decoderCtx_, &inpacket); + if (ret < 0) + return ret == AVERROR_EOF ? Status::Success : Status::DecodeError; + + ret = avcodec_receive_frame(decoderCtx_, result.pointer()); + if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) + return Status::DecodeError; + if (ret >= 0) + frameFinished = 1; +#else + ret = avcodec_decode_video2(decoderCtx_, result.pointer(), &frameFinished, &inpacket); - av_packet_unref(&inpacket); - if (len <= 0) + if (ret <= 0) return Status::DecodeError; +#endif if (frameFinished) { + av_packet_unref(&inpacket); #ifdef RING_ACCEL // flush is called when closing the stream // so don't restart the media decoder diff --git a/src/media/media_encoder.cpp b/src/media/media_encoder.cpp index b229bc814d741f6a233ade2b78dab09534406f28..e79e5090933678c0a4f657afe9e24fd7bdee1b8b 100644 --- a/src/media/media_encoder.cpp +++ b/src/media/media_encoder.cpp @@ -228,7 +228,13 @@ MediaEncoder::openOutput(const char *filename, if (!stream_) throw MediaEncoderException("Could not allocate stream"); +#if LIBAVFORMAT_VERSION_CHECK(57, 7, 2, 40, 101) && !defined(_WIN32) + auto par = std::unique_ptr<AVCodecParameters>(new AVCodecParameters()); + avcodec_parameters_from_context(par.get(), encoderCtx_); + stream_->codecpar = par.release(); +#else stream_->codec = encoderCtx_; +#endif #ifdef RING_VIDEO if (args.codec->systemCodecInfo.mediaType == MEDIA_VIDEO) { // allocate buffers for both scaled (pre-encoder) and encoded frames @@ -315,10 +321,41 @@ MediaEncoder::encode(VideoFrame& input, bool is_keyframe, memset(&pkt, 0, sizeof(pkt)); av_init_packet(&pkt); -#if LIBAVCODEC_VERSION_MAJOR >= 54 + int ret = 0; +#if LIBAVCODEC_VERSION_CHECK(57, 25, 0, 48, 101) + ret = avcodec_send_frame(encoderCtx_, frame); + if (ret < 0) + return -1; + + while (1) { + ret = avcodec_receive_packet(encoderCtx_, &pkt); + if (ret == AVERROR(EAGAIN)) + break; + if (ret < 0) + return -1; + + if (pkt.size) { + if (pkt.pts != AV_NOPTS_VALUE) + pkt.pts = av_rescale_q(pkt.pts, encoderCtx_->time_base, + stream_->time_base); + if (pkt.dts != AV_NOPTS_VALUE) + pkt.dts = av_rescale_q(pkt.dts, encoderCtx_->time_base, + stream_->time_base); + + pkt.stream_index = stream_->index; + + // write the compressed frame + ret = av_write_frame(outputCtx_, &pkt); + if (ret < 0) + print_averror("av_write_frame", ret); + else + break; + } + } +#elif LIBAVCODEC_VERSION_MAJOR >= 54 int got_packet; - int ret = avcodec_encode_video2(encoderCtx_, &pkt, frame, &got_packet); + ret = avcodec_encode_video2(encoderCtx_, &pkt, frame, &got_packet); if (ret < 0) { print_averror("avcodec_encode_video2", ret); av_free_packet(&pkt); @@ -342,8 +379,7 @@ MediaEncoder::encode(VideoFrame& input, bool is_keyframe, } #else - - int ret = avcodec_encode_video(encoderCtx_, encoderBuffer_.data(), + ret = avcodec_encode_video(encoderCtx_, encoderBuffer_.data(), encoderBufferSize_, frame); if (ret < 0) { print_averror("avcodec_encode_video", ret); @@ -448,9 +484,41 @@ int MediaEncoder::encode_audio(const AudioBuffer &buffer) av_init_packet(&pkt); pkt.data = NULL; // packet data will be allocated by the encoder pkt.size = 0; + int ret = 0; +#if LIBAVCODEC_VERSION_CHECK(57, 25, 0, 48, 101) + ret = avcodec_send_frame(encoderCtx_, frame); + if (ret < 0) + return -1; + + while (1) { + ret = avcodec_receive_packet(encoderCtx_, &pkt); + if (ret == AVERROR(EAGAIN)) + break; + if (ret < 0) + return -1; + + if (pkt.size) { + if (pkt.pts != AV_NOPTS_VALUE) + pkt.pts = av_rescale_q(pkt.pts, encoderCtx_->time_base, + stream_->time_base); + if (pkt.dts != AV_NOPTS_VALUE) + pkt.dts = av_rescale_q(pkt.dts, encoderCtx_->time_base, + stream_->time_base); + + pkt.stream_index = stream_->index; + + // write the compressed frame + ret = av_write_frame(outputCtx_, &pkt); + if (ret < 0) + print_averror("av_write_frame", ret); + else + break; + } + } +#else int got_packet; - int ret = avcodec_encode_audio2(encoderCtx_, &pkt, frame, &got_packet); + ret = avcodec_encode_audio2(encoderCtx_, &pkt, frame, &got_packet); if (ret < 0) { print_averror("avcodec_encode_audio2", ret); av_free_packet(&pkt); @@ -473,6 +541,7 @@ int MediaEncoder::encode_audio(const AudioBuffer &buffer) if (ret < 0) print_averror("av_write_frame", ret); } +#endif av_free_packet(&pkt); av_frame_free(&frame); @@ -487,8 +556,38 @@ int MediaEncoder::flush() memset(&pkt, 0, sizeof(pkt)); av_init_packet(&pkt); - int ret; -#if (LIBAVCODEC_VERSION_MAJOR >= 54) + int ret = 0; +#if LIBAVCODEC_VERSION_CHECK(57, 25, 0, 48, 101) + ret = avcodec_send_frame(encoderCtx_, nullptr); + if (ret < 0) + return -1; + + while (1) { + ret = avcodec_receive_packet(encoderCtx_, &pkt); + if (ret == AVERROR(EAGAIN)) + break; + if (ret < 0) + return -1; + + if (pkt.size) { + if (pkt.pts != AV_NOPTS_VALUE) + pkt.pts = av_rescale_q(pkt.pts, encoderCtx_->time_base, + stream_->time_base); + if (pkt.dts != AV_NOPTS_VALUE) + pkt.dts = av_rescale_q(pkt.dts, encoderCtx_->time_base, + stream_->time_base); + + pkt.stream_index = stream_->index; + + // write the compressed frame + ret = av_write_frame(outputCtx_, &pkt); + if (ret < 0) + print_averror("av_write_frame", ret); + else + break; + } + } +#elif (LIBAVCODEC_VERSION_MAJOR >= 54) int got_packet; @@ -531,7 +630,11 @@ std::string MediaEncoder::print_sdp() { /* theora sdp can be huge */ +#if LIBAVFORMAT_VERSION_CHECK(57, 7, 2, 40, 101) && !defined(_WIN32) + const auto sdp_size = outputCtx_->streams[0]->codecpar->extradata_size + 2048; +#else const auto sdp_size = outputCtx_->streams[0]->codec->extradata_size + 2048; +#endif std::string result; std::string sdp(sdp_size, '\0'); av_sdp_create(&outputCtx_, 1, &(*sdp.begin()), sdp_size); diff --git a/src/media/video/video_scaler.cpp b/src/media/video/video_scaler.cpp index c575893b7ed4edf3d39fa6d6df212f42aff990c1..4123e700f091ab06884be17c89268469a65d3465 100644 --- a/src/media/video/video_scaler.cpp +++ b/src/media/video/video_scaler.cpp @@ -124,10 +124,10 @@ VideoScaler::scale_and_pad(const VideoFrame& input, VideoFrame& output, x_shift = -((-x_shift) >> out_desc->log2_chroma_w); y_shift = -((-y_shift) >> out_desc->log2_chroma_h); } -#if LIBAVUTIL_VERSION_MAJOR < 56 - auto x_step = out_desc->comp[i].step_minus1 + 1; // using deprecated api -#else +#if LIBAVUTIL_VERSION_CHECK(55, 20, 0, 17, 103) auto x_step = out_desc->comp[i].step; +#else + auto x_step = out_desc->comp[i].step_minus1 + 1; #endif tmp_data_[i] = output_frame->data[i] + y_shift * output_frame->linesize[i] + x_shift * x_step; }