working hwdecode
This commit is contained in:
parent
529f0b55ef
commit
246b4cb9d1
|
@ -284,6 +284,17 @@ static void zm_log_fps(double d, const char *postfix) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void zm_dump_video_frame(const AVFrame *frame, const char *text) {
|
||||||
|
Debug(1, "%s: format %d %s %dx%d linesize:%d pts: %" PRId64,
|
||||||
|
text,
|
||||||
|
frame->format,
|
||||||
|
av_get_pix_fmt_name((AVPixelFormat)frame->format),
|
||||||
|
frame->width,
|
||||||
|
frame->height,
|
||||||
|
frame->linesize,
|
||||||
|
frame->pts
|
||||||
|
);
|
||||||
|
}
|
||||||
void zm_dump_frame(const AVFrame *frame,const char *text) {
|
void zm_dump_frame(const AVFrame *frame,const char *text) {
|
||||||
Debug(1, "%s: format %d %s sample_rate %" PRIu32 " nb_samples %d channels %d"
|
Debug(1, "%s: format %d %s sample_rate %" PRIu32 " nb_samples %d channels %d"
|
||||||
" duration %" PRId64
|
" duration %" PRId64
|
||||||
|
|
|
@ -300,6 +300,7 @@ void zm_dump_codec(const AVCodecContext *codec);
|
||||||
void zm_dump_codecpar(const AVCodecParameters *par);
|
void zm_dump_codecpar(const AVCodecParameters *par);
|
||||||
#endif
|
#endif
|
||||||
void zm_dump_frame(const AVFrame *frame, const char *text="Frame");
|
void zm_dump_frame(const AVFrame *frame, const char *text="Frame");
|
||||||
|
void zm_dump_video_frame(const AVFrame *frame, const char *text="Frame");
|
||||||
|
|
||||||
#if LIBAVCODEC_VERSION_CHECK(56, 8, 0, 60, 100)
|
#if LIBAVCODEC_VERSION_CHECK(56, 8, 0, 60, 100)
|
||||||
#define zm_av_packet_unref( packet ) av_packet_unref( packet )
|
#define zm_av_packet_unref( packet ) av_packet_unref( packet )
|
||||||
|
|
|
@ -42,6 +42,22 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static enum AVPixelFormat hw_pix_fmt;
|
||||||
|
static enum AVPixelFormat get_hw_format(
|
||||||
|
AVCodecContext *ctx,
|
||||||
|
const enum AVPixelFormat *pix_fmts
|
||||||
|
) {
|
||||||
|
const enum AVPixelFormat *p;
|
||||||
|
|
||||||
|
for ( p = pix_fmts; *p != -1; p++ ) {
|
||||||
|
if ( *p == hw_pix_fmt )
|
||||||
|
return *p;
|
||||||
|
}
|
||||||
|
|
||||||
|
Error("Failed to get HW surface format.");
|
||||||
|
return AV_PIX_FMT_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
#if HAVE_AVUTIL_HWCONTEXT_H
|
#if HAVE_AVUTIL_HWCONTEXT_H
|
||||||
static AVPixelFormat get_format(AVCodecContext *avctx, const enum AVPixelFormat *pix_fmts) {
|
static AVPixelFormat get_format(AVCodecContext *avctx, const enum AVPixelFormat *pix_fmts) {
|
||||||
while (*pix_fmts != AV_PIX_FMT_NONE) {
|
while (*pix_fmts != AV_PIX_FMT_NONE) {
|
||||||
|
@ -76,7 +92,7 @@ static AVPixelFormat get_format(AVCodecContext *avctx, const enum AVPixelFormat
|
||||||
pix_fmts++;
|
pix_fmts++;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error( "The QSV pixel format not offered in get_format()");
|
Error("The QSV pixel format not offered in get_format()");
|
||||||
|
|
||||||
return AV_PIX_FMT_NONE;
|
return AV_PIX_FMT_NONE;
|
||||||
}
|
}
|
||||||
|
@ -122,8 +138,8 @@ FfmpegCamera::FfmpegCamera(
|
||||||
hwaccel = false;
|
hwaccel = false;
|
||||||
#if HAVE_AVUTIL_HWCONTEXT_H
|
#if HAVE_AVUTIL_HWCONTEXT_H
|
||||||
decode = { NULL };
|
decode = { NULL };
|
||||||
hwFrame = NULL;
|
|
||||||
#endif
|
#endif
|
||||||
|
hwFrame = NULL;
|
||||||
|
|
||||||
mFormatContext = NULL;
|
mFormatContext = NULL;
|
||||||
mVideoStreamId = -1;
|
mVideoStreamId = -1;
|
||||||
|
@ -250,6 +266,7 @@ int FfmpegCamera::Capture( Image &image ) {
|
||||||
zm_av_packet_unref( &packet );
|
zm_av_packet_unref( &packet );
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
Debug(1, "transfering from hardware");
|
||||||
ret = av_hwframe_transfer_data(mRawFrame, hwFrame, 0);
|
ret = av_hwframe_transfer_data(mRawFrame, hwFrame, 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
|
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
|
||||||
|
@ -259,6 +276,8 @@ int FfmpegCamera::Capture( Image &image ) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
ret = avcodec_receive_frame( mVideoCodecContext, mRawFrame );
|
ret = avcodec_receive_frame( mVideoCodecContext, mRawFrame );
|
||||||
if ( ret < 0 ) {
|
if ( ret < 0 ) {
|
||||||
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
|
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
|
||||||
|
@ -305,7 +324,7 @@ int FfmpegCamera::Capture( Image &image ) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if HAVE_LIBSWSCALE
|
#if HAVE_LIBSWSCALE
|
||||||
if ( sws_scale(mConvertContext, mRawFrame->data, mRawFrame->linesize, 0, mVideoCodecContext->height, mFrame->data, mFrame->linesize) < 0 ) {
|
if ( sws_scale(mConvertContext, mRawFrame->data, mRawFrame->linesize, 0, mVideoCodecContext->height, mFrame->data, mFrame->linesize) <= 0 ) {
|
||||||
Error("Unable to convert raw format %u to target format %u at frame %d", mVideoCodecContext->pix_fmt, imagePixFormat, frameCount);
|
Error("Unable to convert raw format %u to target format %u at frame %d", mVideoCodecContext->pix_fmt, imagePixFormat, frameCount);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -331,7 +350,6 @@ int FfmpegCamera::PostCapture() {
|
||||||
|
|
||||||
int FfmpegCamera::OpenFfmpeg() {
|
int FfmpegCamera::OpenFfmpeg() {
|
||||||
|
|
||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
have_video_keyframe = false;
|
have_video_keyframe = false;
|
||||||
|
@ -339,7 +357,6 @@ int FfmpegCamera::OpenFfmpeg() {
|
||||||
|
|
||||||
// Open the input, not necessarily a file
|
// Open the input, not necessarily a file
|
||||||
#if !LIBAVFORMAT_VERSION_CHECK(53, 2, 0, 4, 0)
|
#if !LIBAVFORMAT_VERSION_CHECK(53, 2, 0, 4, 0)
|
||||||
Debug ( 1, "Calling av_open_input_file" );
|
|
||||||
if ( av_open_input_file( &mFormatContext, mPath.c_str(), NULL, 0, NULL ) != 0 )
|
if ( av_open_input_file( &mFormatContext, mPath.c_str(), NULL, 0, NULL ) != 0 )
|
||||||
#else
|
#else
|
||||||
// Handle options
|
// Handle options
|
||||||
|
@ -360,7 +377,7 @@ int FfmpegCamera::OpenFfmpeg() {
|
||||||
} else if ( method == "rtpUni" ) {
|
} else if ( method == "rtpUni" ) {
|
||||||
ret = av_dict_set(&opts, "rtsp_transport", "udp", 0);
|
ret = av_dict_set(&opts, "rtsp_transport", "udp", 0);
|
||||||
} else {
|
} else {
|
||||||
Warning("Unknown method (%s)", method.c_str() );
|
Warning("Unknown method (%s)", method.c_str());
|
||||||
}
|
}
|
||||||
//#av_dict_set(&opts, "timeout", "10000000", 0); // in microseconds.
|
//#av_dict_set(&opts, "timeout", "10000000", 0); // in microseconds.
|
||||||
|
|
||||||
|
@ -518,6 +535,23 @@ int FfmpegCamera::OpenFfmpeg() {
|
||||||
}
|
}
|
||||||
} // end if h264
|
} // end if h264
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
AVHWAccel *first_hwaccel = av_hwaccel_next(NULL);
|
||||||
|
AVHWAccel *temp_hwaccel = first_hwaccel;
|
||||||
|
AVHWAccel *h264 = NULL;
|
||||||
|
const char * h264_name = "h264_vaapi";
|
||||||
|
while ( temp_hwaccel != NULL ) {
|
||||||
|
Debug(1,"%s ", temp_hwaccel->name);
|
||||||
|
if ( strcmp(temp_hwaccel->name, h264_name) == 0 ) {
|
||||||
|
h264=temp_hwaccel;
|
||||||
|
}
|
||||||
|
temp_hwaccel = av_hwaccel_next(temp_hwaccel);
|
||||||
|
|
||||||
|
if ( temp_hwaccel == first_hwaccel ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ( mVideoCodecContext->codec_id == AV_CODEC_ID_H264 ) {
|
if ( mVideoCodecContext->codec_id == AV_CODEC_ID_H264 ) {
|
||||||
if ( (mVideoCodec = avcodec_find_decoder_by_name("h264_mmal")) == NULL ) {
|
if ( (mVideoCodec = avcodec_find_decoder_by_name("h264_mmal")) == NULL ) {
|
||||||
Debug(1, "Failed to find decoder (h264_mmal)" );
|
Debug(1, "Failed to find decoder (h264_mmal)" );
|
||||||
|
@ -530,32 +564,75 @@ int FfmpegCamera::OpenFfmpeg() {
|
||||||
// Try and get the codec from the codec context
|
// Try and get the codec from the codec context
|
||||||
Error("Can't find codec for video stream from %s", mPath.c_str());
|
Error("Can't find codec for video stream from %s", mPath.c_str());
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug(1, "Video Found decoder %s", mVideoCodec->name);
|
||||||
|
zm_dump_stream_format(mFormatContext, mVideoStreamId, 0, 0);
|
||||||
|
|
||||||
|
enum AVHWDeviceType type = AV_HWDEVICE_TYPE_NONE;
|
||||||
|
while ( (type = av_hwdevice_iterate_types(type)) != AV_HWDEVICE_TYPE_NONE )
|
||||||
|
Debug(1, "%s", av_hwdevice_get_type_name(type));
|
||||||
|
|
||||||
|
const char *hw_name = "vaapi";
|
||||||
|
type = av_hwdevice_find_type_by_name(hw_name);
|
||||||
|
if ( type == AV_HWDEVICE_TYPE_NONE ) {
|
||||||
|
Debug(1,"Device type %s is not supported.", hw_name);
|
||||||
} else {
|
} else {
|
||||||
Debug(1, "Video Found decoder %s", mVideoCodec->name);
|
Debug(1, "Found hwdevice %s", av_hwdevice_get_type_name(type));
|
||||||
zm_dump_stream_format(mFormatContext, mVideoStreamId, 0, 0);
|
}
|
||||||
// Open the codec
|
|
||||||
#if !LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 8, 0)
|
// Get h_pix_fmt
|
||||||
ret = avcodec_open(mVideoCodecContext, mVideoCodec);
|
for ( int i = 0;; i++ ) {
|
||||||
#else
|
const AVCodecHWConfig *config = avcodec_get_hw_config(mVideoCodec, i);
|
||||||
ret = avcodec_open2(mVideoCodecContext, mVideoCodec, &opts);
|
if ( !config ) {
|
||||||
#endif
|
Debug(1, "Decoder %s does not support device type %s.",
|
||||||
AVDictionaryEntry *e = NULL;
|
mVideoCodec->name, av_hwdevice_get_type_name(type));
|
||||||
while ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL ) {
|
|
||||||
Warning( "Option %s not recognized by ffmpeg", e->key);
|
|
||||||
}
|
|
||||||
if ( ret < 0 ) {
|
|
||||||
Error("Unable to open codec for video stream from %s", mPath.c_str());
|
|
||||||
av_dict_free(&opts);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
zm_dump_codec(mVideoCodecContext);
|
if ( (config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX )
|
||||||
|
&& (config->device_type == type)
|
||||||
|
) {
|
||||||
|
hw_pix_fmt = config->pix_fmt;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} // end foreach hwconfig
|
||||||
|
|
||||||
|
mVideoCodecContext->get_format = get_hw_format;
|
||||||
|
|
||||||
|
Debug(1, "Creating hwdevice");
|
||||||
|
if ((ret = av_hwdevice_ctx_create(&hw_device_ctx, type, NULL, NULL, 0)) < 0) {
|
||||||
|
Error("Failed to create specified HW device.");
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
Debug(1, "Created hwdevice");
|
||||||
|
mVideoCodecContext->hw_device_ctx = av_buffer_ref(hw_device_ctx);
|
||||||
|
hwaccel = true;
|
||||||
|
hwFrame = zm_av_frame_alloc();
|
||||||
|
|
||||||
|
// Open the codec
|
||||||
|
#if !LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 8, 0)
|
||||||
|
ret = avcodec_open(mVideoCodecContext, mVideoCodec);
|
||||||
|
#else
|
||||||
|
ret = avcodec_open2(mVideoCodecContext, mVideoCodec, &opts);
|
||||||
|
#endif
|
||||||
|
e = NULL;
|
||||||
|
while ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL ) {
|
||||||
|
Warning( "Option %s not recognized by ffmpeg", e->key);
|
||||||
|
}
|
||||||
|
if ( ret < 0 ) {
|
||||||
|
Error("Unable to open codec for video stream from %s", mPath.c_str());
|
||||||
|
av_dict_free(&opts);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
zm_dump_codec(mVideoCodecContext);
|
||||||
|
|
||||||
if ( mVideoCodecContext->hwaccel != NULL ) {
|
if ( mVideoCodecContext->hwaccel != NULL ) {
|
||||||
Debug(1, "HWACCEL in use");
|
Debug(1, "HWACCEL in use");
|
||||||
} else {
|
} else {
|
||||||
Debug(1, "HWACCEL not in use");
|
Debug(1, "HWACCEL not in use");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ( mAudioStreamId >= 0 ) {
|
if ( mAudioStreamId >= 0 ) {
|
||||||
if ( (mAudioCodec = avcodec_find_decoder(
|
if ( (mAudioCodec = avcodec_find_decoder(
|
||||||
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
|
||||||
|
@ -578,13 +655,13 @@ int FfmpegCamera::OpenFfmpeg() {
|
||||||
zm_dump_stream_format(mFormatContext, mAudioStreamId, 0, 0);
|
zm_dump_stream_format(mFormatContext, mAudioStreamId, 0, 0);
|
||||||
// Open the codec
|
// Open the codec
|
||||||
#if !LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 8, 0)
|
#if !LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 8, 0)
|
||||||
Debug ( 1, "Calling avcodec_open" );
|
Debug(1, "Calling avcodec_open");
|
||||||
if ( avcodec_open(mAudioCodecContext, mAudioCodec) < 0 ) {
|
if ( avcodec_open(mAudioCodecContext, mAudioCodec) < 0 ) {
|
||||||
#else
|
#else
|
||||||
Debug ( 1, "Calling avcodec_open2" );
|
Debug(1, "Calling avcodec_open2" );
|
||||||
if ( avcodec_open2(mAudioCodecContext, mAudioCodec, 0) < 0 ) {
|
if ( avcodec_open2(mAudioCodecContext, mAudioCodec, 0) < 0 ) {
|
||||||
#endif
|
#endif
|
||||||
Error( "Unable to open codec for audio stream from %s", mPath.c_str() );
|
Error("Unable to open codec for audio stream from %s", mPath.c_str() );
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
zm_dump_codec(mAudioCodecContext);
|
zm_dump_codec(mAudioCodecContext);
|
||||||
|
@ -629,6 +706,7 @@ int FfmpegCamera::OpenFfmpeg() {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# if 0
|
||||||
mConvertContext = sws_getContext(
|
mConvertContext = sws_getContext(
|
||||||
mVideoCodecContext->width,
|
mVideoCodecContext->width,
|
||||||
mVideoCodecContext->height,
|
mVideoCodecContext->height,
|
||||||
|
@ -640,6 +718,7 @@ int FfmpegCamera::OpenFfmpeg() {
|
||||||
Error( "Unable to create conversion context for %s", mPath.c_str() );
|
Error( "Unable to create conversion context for %s", mPath.c_str() );
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#else // HAVE_LIBSWSCALE
|
#else // HAVE_LIBSWSCALE
|
||||||
Fatal( "You must compile ffmpeg with the --enable-swscale option to use ffmpeg cameras" );
|
Fatal( "You must compile ffmpeg with the --enable-swscale option to use ffmpeg cameras" );
|
||||||
#endif // HAVE_LIBSWSCALE
|
#endif // HAVE_LIBSWSCALE
|
||||||
|
@ -885,7 +964,8 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event
|
||||||
if ( packetqueue->packet_count(mVideoStreamId) >= monitor->GetImageBufferCount() ) {
|
if ( packetqueue->packet_count(mVideoStreamId) >= monitor->GetImageBufferCount() ) {
|
||||||
Warning("ImageBufferCount %d is too small. Needs to be at least %d. Either increase it or decrease time between keyframes",
|
Warning("ImageBufferCount %d is too small. Needs to be at least %d. Either increase it or decrease time between keyframes",
|
||||||
monitor->GetImageBufferCount(),
|
monitor->GetImageBufferCount(),
|
||||||
packetqueue->packet_count(mVideoStreamId)+1 );
|
packetqueue->packet_count(mVideoStreamId)+1
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
packetqueue->clearQueue(monitor->GetPreEventCount(), mVideoStreamId);
|
packetqueue->clearQueue(monitor->GetPreEventCount(), mVideoStreamId);
|
||||||
|
@ -931,6 +1011,7 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event
|
||||||
}
|
}
|
||||||
#if HAVE_AVUTIL_HWCONTEXT_H
|
#if HAVE_AVUTIL_HWCONTEXT_H
|
||||||
if ( hwaccel ) {
|
if ( hwaccel ) {
|
||||||
|
Debug(1, "Using hwaccel to decode");
|
||||||
ret = avcodec_receive_frame(mVideoCodecContext, hwFrame);
|
ret = avcodec_receive_frame(mVideoCodecContext, hwFrame);
|
||||||
if ( ret < 0 ) {
|
if ( ret < 0 ) {
|
||||||
av_strerror(ret, errbuf, AV_ERROR_MAX_STRING_SIZE);
|
av_strerror(ret, errbuf, AV_ERROR_MAX_STRING_SIZE);
|
||||||
|
@ -939,7 +1020,7 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ret = av_hwframe_transfer_data(mRawFrame, hwFrame, 0);
|
ret = av_hwframe_transfer_data(mRawFrame, hwFrame, 0);
|
||||||
if (ret < 0) {
|
if ( ret < 0 ) {
|
||||||
av_strerror(ret, errbuf, AV_ERROR_MAX_STRING_SIZE);
|
av_strerror(ret, errbuf, AV_ERROR_MAX_STRING_SIZE);
|
||||||
Error("Unable to transfer frame at frame %d: %s, continuing", frameCount, errbuf);
|
Error("Unable to transfer frame at frame %d: %s, continuing", frameCount, errbuf);
|
||||||
zm_av_packet_unref(&packet);
|
zm_av_packet_unref(&packet);
|
||||||
|
@ -947,6 +1028,8 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
#endif
|
#endif
|
||||||
|
Debug(1, "Decodingaccel to decode");
|
||||||
|
|
||||||
ret = avcodec_receive_frame(mVideoCodecContext, mRawFrame);
|
ret = avcodec_receive_frame(mVideoCodecContext, mRawFrame);
|
||||||
if ( ret < 0 ) {
|
if ( ret < 0 ) {
|
||||||
av_strerror(ret, errbuf, AV_ERROR_MAX_STRING_SIZE);
|
av_strerror(ret, errbuf, AV_ERROR_MAX_STRING_SIZE);
|
||||||
|
@ -961,6 +1044,24 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ( error_count > 0 ) error_count --;
|
if ( error_count > 0 ) error_count --;
|
||||||
|
zm_dump_video_frame(mRawFrame);
|
||||||
|
if ( mRawFrame->format == hw_pix_fmt ) {
|
||||||
|
/* retrieve data from GPU to CPU */
|
||||||
|
ret = av_hwframe_transfer_data(hwFrame, mRawFrame, 0);
|
||||||
|
if ( ret < 0 ) {
|
||||||
|
av_strerror(ret, errbuf, AV_ERROR_MAX_STRING_SIZE);
|
||||||
|
Error("Unable to transfer frame at frame %d: %s, continuing", frameCount, errbuf);
|
||||||
|
zm_av_packet_unref(&packet);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Debug(1,"Success transfering");
|
||||||
|
zm_dump_video_frame(hwFrame);
|
||||||
|
|
||||||
|
hwFrame->pts = mRawFrame->pts;
|
||||||
|
input_frame = hwFrame;
|
||||||
|
} else {
|
||||||
|
input_frame = mRawFrame;
|
||||||
|
}
|
||||||
|
|
||||||
#if HAVE_AVUTIL_HWCONTEXT_H
|
#if HAVE_AVUTIL_HWCONTEXT_H
|
||||||
}
|
}
|
||||||
|
@ -968,7 +1069,7 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event
|
||||||
|
|
||||||
frameComplete = 1;
|
frameComplete = 1;
|
||||||
# else
|
# else
|
||||||
ret = zm_avcodec_decode_video(mVideoCodecContext, mRawFrame, &frameComplete, &packet);
|
ret = zm_avcodec_decode_video(mVideoCodecContext, input_frame, &frameComplete, &packet);
|
||||||
if ( ret < 0 ) {
|
if ( ret < 0 ) {
|
||||||
av_strerror(ret, errbuf, AV_ERROR_MAX_STRING_SIZE);
|
av_strerror(ret, errbuf, AV_ERROR_MAX_STRING_SIZE);
|
||||||
Error("Unable to decode frame at frame %d: %s, continuing", frameCount, errbuf);
|
Error("Unable to decode frame at frame %d: %s, continuing", frameCount, errbuf);
|
||||||
|
@ -978,7 +1079,7 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ( frameComplete ) {
|
if ( frameComplete ) {
|
||||||
Debug( 4, "Got frame %d", frameCount );
|
Debug(4, "Got frame %d", frameCount);
|
||||||
|
|
||||||
uint8_t* directbuffer;
|
uint8_t* directbuffer;
|
||||||
|
|
||||||
|
@ -986,7 +1087,7 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event
|
||||||
directbuffer = image.WriteBuffer(width, height, colours, subpixelorder);
|
directbuffer = image.WriteBuffer(width, height, colours, subpixelorder);
|
||||||
if ( directbuffer == NULL ) {
|
if ( directbuffer == NULL ) {
|
||||||
Error("Failed requesting writeable buffer for the captured image.");
|
Error("Failed requesting writeable buffer for the captured image.");
|
||||||
zm_av_packet_unref( &packet );
|
zm_av_packet_unref(&packet);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
||||||
|
@ -994,10 +1095,34 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event
|
||||||
#else
|
#else
|
||||||
avpicture_fill( (AVPicture *)mFrame, directbuffer, imagePixFormat, width, height);
|
avpicture_fill( (AVPicture *)mFrame, directbuffer, imagePixFormat, width, height);
|
||||||
#endif
|
#endif
|
||||||
if (sws_scale(mConvertContext, mRawFrame->data, mRawFrame->linesize,
|
Debug(1,"swscale target format: %c%c%c%c %c%c%c%c",
|
||||||
0, mVideoCodecContext->height, mFrame->data, mFrame->linesize) < 0) {
|
(imagePixFormat)&0xff,((imagePixFormat>>8)&0xff),((imagePixFormat>>16)&0xff),((imagePixFormat>>24)&0xff),
|
||||||
Error("Unable to convert raw format %u to target format %u at frame %d",
|
(mVideoCodecContext->pix_fmt)&0xff,
|
||||||
mVideoCodecContext->pix_fmt, imagePixFormat, frameCount);
|
((mVideoCodecContext->pix_fmt>>8)&0xff),
|
||||||
|
((mVideoCodecContext->pix_fmt>>16)&0xff),
|
||||||
|
((mVideoCodecContext->pix_fmt>>24)&0xff)
|
||||||
|
);
|
||||||
|
if ( ! mConvertContext ) {
|
||||||
|
mConvertContext = sws_getContext(
|
||||||
|
input_frame->width,
|
||||||
|
input_frame->height,
|
||||||
|
(AVPixelFormat)input_frame->format,
|
||||||
|
width, height,
|
||||||
|
imagePixFormat, SWS_BICUBIC, NULL,
|
||||||
|
NULL, NULL);
|
||||||
|
if ( mConvertContext == NULL ) {
|
||||||
|
Error( "Unable to create conversion context for %s", mPath.c_str() );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( sws_scale(mConvertContext, input_frame->data, input_frame->linesize,
|
||||||
|
0, mVideoCodecContext->height, mFrame->data, mFrame->linesize) <= 0 ) {
|
||||||
|
Error("Unable to convert raw format %u to target format %u at frame %d codec %u ",
|
||||||
|
input_frame->format,
|
||||||
|
imagePixFormat, frameCount,
|
||||||
|
mVideoCodecContext->pix_fmt
|
||||||
|
);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,12 +55,14 @@ class FfmpegCamera : public Camera {
|
||||||
AVFrame *mRawFrame;
|
AVFrame *mRawFrame;
|
||||||
AVFrame *mFrame;
|
AVFrame *mFrame;
|
||||||
_AVPIXELFORMAT imagePixFormat;
|
_AVPIXELFORMAT imagePixFormat;
|
||||||
|
AVFrame *input_frame; // Use to point to mRawFrame or hwFrame;
|
||||||
|
|
||||||
bool hwaccel;
|
bool hwaccel;
|
||||||
#if HAVE_AVUTIL_HWCONTEXT_H
|
|
||||||
AVFrame *hwFrame;
|
AVFrame *hwFrame;
|
||||||
|
#if HAVE_AVUTIL_HWCONTEXT_H
|
||||||
DecodeContext decode;
|
DecodeContext decode;
|
||||||
#endif
|
#endif
|
||||||
|
AVBufferRef *hw_device_ctx = NULL;
|
||||||
|
|
||||||
// Need to keep track of these because apparently the stream can start with values for pts/dts and then subsequent packets start at zero.
|
// Need to keep track of these because apparently the stream can start with values for pts/dts and then subsequent packets start at zero.
|
||||||
int64_t audio_last_pts;
|
int64_t audio_last_pts;
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
#cmakedefine HAVE_LIBAVUTIL 1
|
#cmakedefine HAVE_LIBAVUTIL 1
|
||||||
#cmakedefine HAVE_LIBAVUTIL_AVUTIL_H 1
|
#cmakedefine HAVE_LIBAVUTIL_AVUTIL_H 1
|
||||||
#cmakedefine HAVE_LIBAVUTIL_MATHEMATICS_H 1
|
#cmakedefine HAVE_LIBAVUTIL_MATHEMATICS_H 1
|
||||||
#cmakedefine HAVE_LIBAVUTIL_HWCONTEXT_H 0
|
#cmakedefine HAVE_LIBAVUTIL_HWCONTEXT_H 1
|
||||||
#cmakedefine HAVE_LIBSWSCALE 1
|
#cmakedefine HAVE_LIBSWSCALE 1
|
||||||
#cmakedefine HAVE_LIBSWSCALE_SWSCALE_H 1
|
#cmakedefine HAVE_LIBSWSCALE_SWSCALE_H 1
|
||||||
#cmakedefine HAVE_LIBSWRESAMPLE 1
|
#cmakedefine HAVE_LIBSWRESAMPLE 1
|
||||||
|
|
Loading…
Reference in New Issue