FFmpeg doesn't use GPU - windows

I got the latest version binaries of ffmpeg from here. When I examine CPU and GPU usages when I play a video by its ffplay, I see that GPU is used during play. Not much using of CPU also indicates it. But when I get the latest version sources from the original site, I can't use GPU. To clarify, I include a player test program I wrote until now. When I uncomment the line which includes avcodec_find_decoder_by_name("h264_cuvid"), I get error -1. The error happens in avcodec_open2 with the description of Operation not permitted.
CString format(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
char buf[512];
vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
return buf;
}
int CplayerDlg::play()
{
FILE *fp = fopen("video_files/1010.brf", "rb");
if (!fp)
{
AfxMessageBox("can't open video file");
return -1;
}
RecordFrame frame;
RecordHeader hdr;
fread(&frame, sizeof(frame), 1, fp);
if (frame.frameType != FRAME_TYPE_HEADER)
{
AfxMessageBox("record file doesn't begin with header");
return -1;
}
fread(&hdr, sizeof(hdr), 1, fp);
GetDlgItem(IDC_DIM)->SetWindowText(format("%dx%d", hdr.width, hdr.height));
GetDlgItem(IDC_CODEC_ID)->SetWindowText(format("%d", hdr.codecId));
GetDlgItem(IDC_PIXEL_FORMAT)->SetWindowText(format("%d", hdr.pixelFormat));
GetDlgItem(IDC_TIMEBASE)->SetWindowText(format("%d/%d", hdr.timebaseNum, hdr.timebaseDen));
AVCodec *pCodec;
#if 0
#define CHECK(decoder)\
pCodec = avcodec_find_decoder_by_name(#decoder);\
AfxMessageBox(pCodec ? #decoder " found" : "can't find " #decoder);
CHECK(h264_cuvid);
#undef CHECK
#endif
pCodec = avcodec_find_decoder(AV_CODEC_ID_H264);
//pCodec = avcodec_find_decoder_by_name("h264_cuvid");
if (!pCodec)
{
AfxMessageBox("can't find h264 decoder");
return -1;
}
AVCodecContext *pCodecContext = avcodec_alloc_context3(pCodec);
if (!pCodecContext)
{
AfxMessageBox("can't allocate codec context");
return -1;
}
#if 0
// enumerating available codecs
//av_register_all();
avcodec_register_all();
AVCodec *current_codec = av_codec_next(NULL);
while (current_codec != NULL)
{
TRACE("%s\n", current_codec->name);
current_codec = av_codec_next(current_codec);
}
#endif
int err = avcodec_open2(pCodecContext, pCodec, NULL);
if (err != 0)
{
char buf[AV_ERROR_MAX_STRING_SIZE];
av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, err);
char buf2[AV_ERROR_MAX_STRING_SIZE];
sprintf(buf2, "%d (%x): %s\n", err, err, buf);
AfxMessageBox(buf2);
return -1;
}
AfxMessageBox("operation completed successfully");
fclose(fp);
return 0;
}

Related

Saving frames as JPG with FFMPEG (Visual Studio / C++)

I am trying to save all frames from a mp4 video in separate JPG files, I have a code that runs and actually saves something to JPG files but files are not recognized as images and nothing is showing.
Below my full code, I am using Visual Studio 2022 in Windows 11 and FFMPEG 5.1. The function that saves the images is save_frame_as_jpeg which is actually an adaption from the code provided here but changing the use of avcodec_encode_video2 for avcodec_send_frame/avcodec_receive_packet as indicated in the documentation.
I am obiously doing something wrong but cannot quite find it, BTW, I know that a simple command (ffmpeg -i input.mp4 -vf fps=1 vid_%d.png) will do this but I am requiring to do it by code.
Any help is appreciated, thanks in advance!
// FfmpegTests.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#pragma warning(disable : 4996)
extern "C"
{
#include "libavformat/avformat.h"
#include "libavcodec/avcodec.h"
#include "libavfilter/avfilter.h"
#include "libavutil/opt.h"
#include "libavutil/avutil.h"
#include "libavutil/error.h"
#include "libavfilter/buffersrc.h"
#include "libavfilter/buffersink.h"
#include "libswscale/swscale.h"
}
#pragma comment(lib, "avcodec.lib")
#pragma comment(lib, "avformat.lib")
#pragma comment(lib, "avfilter.lib")
#pragma comment(lib, "avutil.lib")
#pragma comment(lib, "swscale.lib")
#include <cstdio>
#include <iostream>
#include <chrono>
#include <thread>
static AVFormatContext* fmt_ctx;
static AVCodecContext* dec_ctx;
AVFilterGraph* filter_graph;
AVFilterContext* buffersrc_ctx;
AVFilterContext* buffersink_ctx;
static int video_stream_index = -1;
const char* filter_descr = "scale=78:24,transpose=cclock";
static int64_t last_pts = AV_NOPTS_VALUE;
static int open_input_file(const char* filename)
{
const AVCodec* dec;
int ret;
if ((ret = avformat_open_input(&fmt_ctx, filename, NULL, NULL)) < 0) {
av_log(NULL, AV_LOG_ERROR, "Cannot open input file\n");
return ret;
}
if ((ret = avformat_find_stream_info(fmt_ctx, NULL)) < 0) {
av_log(NULL, AV_LOG_ERROR, "Cannot find stream information\n");
return ret;
}
/* select the video stream */
ret = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &dec, 0);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Cannot find a video stream in the input file\n");
return ret;
}
video_stream_index = ret;
/* create decoding context */
dec_ctx = avcodec_alloc_context3(dec);
if (!dec_ctx)
return AVERROR(ENOMEM);
avcodec_parameters_to_context(dec_ctx, fmt_ctx->streams[video_stream_index]->codecpar);
/* init the video decoder */
if ((ret = avcodec_open2(dec_ctx, dec, NULL)) < 0) {
av_log(NULL, AV_LOG_ERROR, "Cannot open video decoder\n");
return ret;
}
return 0;
}
static int init_filters(const char* filters_descr)
{
char args[512];
int ret = 0;
const AVFilter* buffersrc = avfilter_get_by_name("buffer");
const AVFilter* buffersink = avfilter_get_by_name("buffersink");
AVFilterInOut* outputs = avfilter_inout_alloc();
AVFilterInOut* inputs = avfilter_inout_alloc();
AVRational time_base = fmt_ctx->streams[video_stream_index]->time_base;
enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE };
filter_graph = avfilter_graph_alloc();
if (!outputs || !inputs || !filter_graph) {
ret = AVERROR(ENOMEM);
goto end;
}
/* buffer video source: the decoded frames from the decoder will be inserted here. */
snprintf(args, sizeof(args),
"video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
dec_ctx->width, dec_ctx->height, dec_ctx->pix_fmt,
time_base.num, time_base.den,
dec_ctx->sample_aspect_ratio.num, dec_ctx->sample_aspect_ratio.den);
ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in",
args, NULL, filter_graph);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Cannot create buffer source\n");
goto end;
}
/* buffer video sink: to terminate the filter chain. */
ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out",
NULL, NULL, filter_graph);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Cannot create buffer sink\n");
goto end;
}
ret = av_opt_set_int_list(buffersink_ctx, "pix_fmts", pix_fmts, AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Cannot set output pixel format\n");
goto end;
}
outputs->name = av_strdup("in");
outputs->filter_ctx = buffersrc_ctx;
outputs->pad_idx = 0;
outputs->next = NULL;
inputs->name = av_strdup("out");
inputs->filter_ctx = buffersink_ctx;
inputs->pad_idx = 0;
inputs->next = NULL;
if ((ret = avfilter_graph_parse_ptr(filter_graph, filters_descr,
&inputs, &outputs, NULL)) < 0)
goto end;
if ((ret = avfilter_graph_config(filter_graph, NULL)) < 0)
goto end;
end:
avfilter_inout_free(&inputs);
avfilter_inout_free(&outputs);
return ret;
}
static void display_frame(const AVFrame* frame, AVRational time_base)
{
int x, y;
uint8_t* p0, * p;
int64_t delay;
if (frame->pts != AV_NOPTS_VALUE) {
if (last_pts != AV_NOPTS_VALUE) {
/* sleep roughly the right amount of time;
* usleep is in microseconds, just like AV_TIME_BASE. */
AVRational timeBaseQ;
timeBaseQ.num = 1;
timeBaseQ.den = AV_TIME_BASE;
delay = av_rescale_q(frame->pts - last_pts, time_base, timeBaseQ);
if (delay > 0 && delay < 1000000)
std::this_thread::sleep_for(std::chrono::microseconds(delay));
}
last_pts = frame->pts;
}
/* Trivial ASCII grayscale display. */
p0 = frame->data[0];
puts("\033c");
for (y = 0; y < frame->height; y++) {
p = p0;
for (x = 0; x < frame->width; x++)
putchar(" .-+#"[*(p++) / 52]);
putchar('\n');
p0 += frame->linesize[0];
}
fflush(stdout);
}
int save_frame_as_jpeg(AVCodecContext* pCodecCtx, AVFrame* pFrame, int FrameNo) {
int ret = 0;
const AVCodec* jpegCodec = avcodec_find_encoder(AV_CODEC_ID_JPEG2000);
if (!jpegCodec) {
return -1;
}
AVCodecContext* jpegContext = avcodec_alloc_context3(jpegCodec);
if (!jpegContext) {
return -1;
}
jpegContext->pix_fmt = pCodecCtx->pix_fmt;
jpegContext->height = pFrame->height;
jpegContext->width = pFrame->width;
jpegContext->time_base = AVRational{ 1,10 };
ret = avcodec_open2(jpegContext, jpegCodec, NULL);
if (ret < 0) {
return ret;
}
FILE* JPEGFile;
char JPEGFName[256];
AVPacket packet;
packet.data = NULL;
packet.size = 0;
av_init_packet(&packet);
int gotFrame;
ret = avcodec_send_frame(jpegContext, pFrame);
if (ret < 0) {
return ret;
}
ret = avcodec_receive_packet(jpegContext, &packet);
if (ret < 0) {
return ret;
}
sprintf(JPEGFName, "c:\\folder\\dvr-%06d.jpg", FrameNo);
JPEGFile = fopen(JPEGFName, "wb");
fwrite(packet.data, 1, packet.size, JPEGFile);
fclose(JPEGFile);
av_packet_unref(&packet);
avcodec_close(jpegContext);
return 0;
}
int main(int argc, char** argv)
{
AVFrame* frame;
AVFrame* filt_frame;
AVPacket* packet;
int ret;
if (argc != 2) {
fprintf(stderr, "Usage: %s file\n", argv[0]);
exit(1);
}
frame = av_frame_alloc();
filt_frame = av_frame_alloc();
packet = av_packet_alloc();
if (!frame || !filt_frame || !packet) {
fprintf(stderr, "Could not allocate frame or packet\n");
exit(1);
}
if ((ret = open_input_file(argv[1])) < 0)
goto end;
if ((ret = init_filters(filter_descr)) < 0)
goto end;
while (true)
{
if ((ret = av_read_frame(fmt_ctx, packet)) < 0)
break;
if (packet->stream_index == video_stream_index) {
ret = avcodec_send_packet(dec_ctx, packet);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Error while sending a packet to the decoder\n");
break;
}
while (ret >= 0)
{
ret = avcodec_receive_frame(dec_ctx, frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
break;
}
else if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Error while receiving a frame from the decoder\n");
goto end;
}
frame->pts = frame->best_effort_timestamp;
/* push the decoded frame into the filtergraph */
if (av_buffersrc_add_frame_flags(buffersrc_ctx, frame, AV_BUFFERSRC_FLAG_KEEP_REF) < 0) {
av_log(NULL, AV_LOG_ERROR, "Error while feeding the filtergraph\n");
break;
}
/* pull filtered frames from the filtergraph */
while (1) {
ret = av_buffersink_get_frame(buffersink_ctx, filt_frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
break;
if (ret < 0)
goto end;
display_frame(filt_frame, buffersink_ctx->inputs[0]->time_base);
av_frame_unref(filt_frame);
ret = save_frame_as_jpeg(dec_ctx, frame, dec_ctx->frame_number);
if (ret < 0)
goto end;
}
av_frame_unref(frame);
}
}
av_packet_unref(packet);
}
end:
avfilter_graph_free(&filter_graph);
avcodec_free_context(&dec_ctx);
avformat_close_input(&fmt_ctx);
av_frame_free(&frame);
av_frame_free(&filt_frame);
av_packet_free(&packet);
if (ret < 0 && ret != AVERROR_EOF) {
char errBuf[AV_ERROR_MAX_STRING_SIZE]{0};
int res = av_strerror(ret, errBuf, AV_ERROR_MAX_STRING_SIZE);
fprintf(stderr, "Error: %s\n", errBuf);
exit(1);
}
exit(0);
}
Well nevermind, I just realized I had an error with the specified codec for JPEG decoding, if somenone's facing this issue you have to use:
*const AVCodec* jpegCodec = avcodec_find_encoder(AV_CODEC_ID_MJPEG);*
instead of:
*const AVCodec* jpegCodec = avcodec_find_encoder(AV_CODEC_ID_JPEG2000);*
and also add this line:
*jpegContext->strict_std_compliance = FF_COMPLIANCE_UNOFFICIAL;*
before the call to avcodec_open2

FFMPEG transcoder producing broken video

I have the following code to transcode video which is closely related to the FFMPEG transcoding example.
However it produced broken video as shown:
It seems like the i-frames are decoded correctly, but the p and b frames are out of order? I thought av_interleaved_write_frame() would rectify that for me. It also seems like the libx264 is not creating any extradata which I thought it would.
Could someone please help me work out why?
Many thanks
#include <stdbool.h>
#include <stdio.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/avutil.h>
#include <libavutil/mathematics.h>
#include <libavutil/opt.h>
#define DEBUG(level, format, ...) fprintf(stderr, format "\n", ##__VA_ARGS__)
#define stringify2(var) #var
#define stringify(var) stringify2(var)
#define RASSERT(cond, ...) do { \
if (!(cond)) { \
DEBUG(LOG_FATAL, __FILE__ ":" stringify(__LINE__) " " "Assertion failed! " #cond ". " __VA_ARGS__); \
abort(); \
} \
} while (0)
#define FFCHECK(ret, func) RASSERT(ret == 0, #func " failed: %s (%d)", av_err2str(ret), ret)
typedef struct decode_context {
AVFormatContext *format;
AVCodecContext *videoCodec;
AVCodecContext *audioCodec;
AVStream *videoStream;
AVStream *audioStream;
} decode_context_t;
typedef struct encode_context {
AVFormatContext *format;
AVCodecContext *videoCodec;
AVCodecContext *audioCodec;
AVStream *videoStream;
AVStream *audioStream;
} encode_context_t;
void open_input(decode_context_t *dec, const char *file) {
int ret;
ret = avformat_open_input(&dec->format, file, NULL, NULL);
FFCHECK(ret, "avformat_open_input()");
ret = avformat_find_stream_info(dec->format, NULL);
FFCHECK(ret, "avformat_find_stream_info()");
for (unsigned int i = 0; i < dec->format->nb_streams; ++i) {
AVStream * stream = dec->format->streams[i];
enum AVMediaType type = stream->codecpar->codec_type;
switch (type) {
case AVMEDIA_TYPE_VIDEO:
if (dec->videoStream)
break;
dec->videoStream = stream;
break;
case AVMEDIA_TYPE_AUDIO:
dec->audioStream = stream;
if (dec->audioStream)
break;
break;
default:
break;
}
}
RASSERT(dec->videoStream != NULL, "Didn't find video stream");
const AVCodec * codec = avcodec_find_decoder(dec->videoStream->codecpar->codec_id);
RASSERT(codec, "Failed to find decoder");
dec->videoCodec = avcodec_alloc_context3(codec);
RASSERT(dec->videoCodec, "avcodec_alloc_context3() failed");
ret = avcodec_parameters_to_context(dec->videoCodec, dec->videoStream->codecpar);
FFCHECK(ret, "avcodec_parameters_to_context()");
dec->videoCodec->framerate = av_guess_frame_rate(dec->format, dec->videoStream, NULL);
ret = avcodec_open2(dec->videoCodec, codec, NULL);
FFCHECK(ret, "avcodec_open2()");
}
void open_output(encode_context_t *enc, const char *file, decode_context_t *dec) {
int ret;
ret = avformat_alloc_output_context2(&enc->format, NULL, NULL, file);
FFCHECK(ret, "avformat_alloc_output_context2()");
enc->videoStream = avformat_new_stream(enc->format, NULL);
RASSERT(enc->videoStream, "avformat_new_stream() failed");
enc->videoStream->id = enc->format->nb_streams - 1;
const AVCodec *codec = avcodec_find_encoder_by_name("libx264");
RASSERT(codec, "Failed to find encoder");
enc->videoCodec = avcodec_alloc_context3(codec);
RASSERT(enc->videoCodec, "avcodec_alloc_context3() failed");
enc->videoCodec->bit_rate = 400000;
enc->videoCodec->width = dec->videoCodec->width;
enc->videoCodec->height = dec->videoCodec->height;
enc->videoCodec->sample_aspect_ratio = dec->videoCodec->sample_aspect_ratio;
enc->videoCodec->time_base = av_inv_q(dec->videoCodec->framerate);
//enc->videoCodec->gop_size = 12;
//enc->videoCodec->max_b_frames = 2;
enc->videoCodec->pix_fmt = dec->videoCodec->pix_fmt;
enc->videoCodec->framerate = dec->videoCodec->framerate;
if (codec->id == AV_CODEC_ID_H264) {
av_opt_set(enc->videoCodec->priv_data, "preset", "slow", 0);
av_opt_set(enc->videoCodec->priv_data, "profile", "high", 0);
av_opt_set(enc->videoCodec->priv_data, "level", "4.1", 0);
}
if (enc->format->flags & AVFMT_GLOBALHEADER)
enc->videoCodec->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
ret = avcodec_open2(enc->videoCodec, codec, NULL);
FFCHECK(ret, "avcodec_open2()");
ret = avcodec_parameters_from_context(enc->videoStream->codecpar, enc->videoCodec);
FFCHECK(ret, "avcodec_parameters_from_context()");
//enc->videoStream->time_base = enc->videoCodec->time_base;
//enc->videoStream->codecpar->extradata = enc->videoCodec->extradata;
//enc->videoStream->codecpar->extradata_size = enc->videoCodec->extradata_size;
av_dump_format(enc->format, 0, file, 1);
ret = avio_open(&enc->format->pb, file, AVIO_FLAG_WRITE);
FFCHECK(ret, "avio_open()");
ret = avformat_write_header(enc->format, NULL);
FFCHECK(ret, "avformat_write_header()");
}
int main(int argc, const char * argv[]) {
int ret;
if (argc < 3) {
fprintf(stderr, "%s input output\n", argv[0]);
return 1;
}
decode_context_t dec_ctx = {};
decode_context_t *dec = &dec_ctx;
encode_context_t enc_ctx = {};
encode_context_t *enc = &enc_ctx;
open_input(dec, argv[1]);
open_output(enc, argv[2], dec);
while (true) {
AVPacket *packet = av_packet_alloc();
ret = av_read_frame(dec->format, packet);
if (ret < 0)
break;
if (packet->stream_index == dec->videoStream->index) {
ret = avcodec_send_packet(dec->videoCodec, packet);
if (ret == AVERROR(EAGAIN)) {
AVFrame * frame = av_frame_alloc();
while (true) {
ret = avcodec_receive_frame(dec->videoCodec, frame);
if (ret == AVERROR(EAGAIN))
break;
FFCHECK(ret, "avcodec_receive_frame()");
ret = avcodec_send_frame(enc->videoCodec, frame);
if (ret == AVERROR(EAGAIN)) {
AVPacket *pkt = av_packet_alloc();
while (true) {
ret = avcodec_receive_packet(enc->videoCodec, pkt);
if (ret == AVERROR(EAGAIN))
break;
FFCHECK(ret, "avcodec_receive_packet()");
pkt->stream_index = enc->videoStream->id;
av_packet_rescale_ts(pkt, dec->videoStream->time_base, enc->videoStream->time_base);
ret = av_interleaved_write_frame(enc->format, pkt);
FFCHECK(ret, "av_interleaved_write_frame()");
}
av_packet_free(&pkt);
}
}
av_frame_free(&frame);
} else {
FFCHECK(ret, "avcodec_send_packet()");
}
} else if (packet->stream_index == dec->audioStream->index) {
// Deal with audio
}
av_packet_free(&packet);
}
ret = av_write_trailer(enc->format);
FFCHECK(ret, "av_write_trailer()");
ret = avio_close(enc->format->pb);
FFCHECK(ret, "avio_close()");
// Close some more stuff
return 0;
}
After thinking about this some more, I realised that I wasn't even sure if my decoder was correct. And another thorough inspection of the transcoding example revealed a small difference in behaviour.
Effectively, I was doing this:
while (true) {
ret = avcodec_send_packet(dec->videoCodec, packet);
if (ret != AVERROR(EAGAIN)) {
continue;
}
ret = avcodec_receive_frame(dec->videoCodec, frame);
}
Removing the continue and immediately trying to receive frames from the decoder works much better, and fixed my issue.
while (true) {
ret = avcodec_send_packet(dec->videoCodec, packet);
if (ret != 0)
abort();
ret = avcodec_receive_frame(dec->videoCodec, frame);
}
I also had the same error in the encoding side so I've fixed it there too.

OpenSSL cannot connect to free.currencyconverterapi.com

Recently I've migrated my program to OpenSSL due to multiple problems with built-in SSL support in the older versions of Windows. Everything works perfectly despite the site specified in the title, I constantly get error:00000001:lib(0):func(0):reason(1).
If I uncomment lines that set non-blocking mode for a socket, I just get another error message. Any help is desperately appreciated. I tested that issue using OpenSSL 1.1.1j under Windows 10 64-bits (but it seems not to be dependent on the OS version)
I thought that the problem may be caused by missing certificates, so I added Microsoft.pem to the context - nothing changed (you can grab this file from https://github.com/drwetter/testssl.sh/blob/3.1dev/etc/Microsoft.pem
That is the code that emulates my program:
#include <winsock2.h>
#include <ws2tcpip.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#define HOST "free.currencyconverterapi.com"
int main()
{
WSADATA wsadata;
WSAStartup(MAKEWORD(2, 2), &wsadata);
SSL_library_init();
SSL_load_error_strings();
const SSL_METHOD *meth = TLS_client_method();
if (!meth) {
fprintf(stderr, "SSL setup failure: client method");
return 1;
}
SSL_CTX *g_ctx = SSL_CTX_new(meth);
if (!g_ctx) {
fprintf(stderr, "SSL setup failure: context");
return 2;
}
SSL_CTX_load_verify_locations(g_ctx, "microsoft.pem", NULL);
SSL_CTX_ctrl(g_ctx, SSL_CTRL_MODE, SSL_MODE_AUTO_RETRY, nullptr);
RAND_screen();
addrinfo *air = nullptr, hints = { 0 };
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
if (GetAddrInfoA(HOST, "443", &hints, &air)) {
fprintf(stderr, "AddrInfo for host %s failed (%u)", HOST, WSAGetLastError());
return 3;
}
int rc = 1;
SOCKET s = INVALID_SOCKET;
for (auto *ai = air; ai; ai = ai->ai_next) {
s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (s == INVALID_SOCKET) {
FreeAddrInfoA(air);
return 4;
}
if (connect(s, ai->ai_addr, (int)ai->ai_addrlen) == 0) {
rc = 0;
break;
}
if (WSAGetLastError() != WSAEWOULDBLOCK) {
rc = WSAGetLastError();
closesocket(s);
s = INVALID_SOCKET;
continue;
}
}
if (rc) {
fprintf(stderr, "connection failed: %d", rc);
return 6;
}
FreeAddrInfoA(air);
// uncomment that lines to obtain another error code
// u_long notblocking = 0;
// if (ioctlsocket(s, FIONBIO, &notblocking) != 0) {
// FreeAddrInfoA(air);
// return 5;
// }
SSL *session = SSL_new(g_ctx);
if (!session) {
fprintf(stderr, "SSL setup failure: session");
return 7;
}
SSL_set_fd(session, s);
int err = SSL_connect(session);
if (err != 1) {
err = SSL_get_error(session, err);
char buf[100];
ERR_error_string_n(err, buf, sizeof(buf));
fprintf(stderr, "SSL negotiation failure: %s (%d)", buf, err);
return 8;
}
fprintf(stderr, "Connection succeeded");
return 0;
}
--
WMBR, George Hazan

Decoding of 16bit gray image encoded with FFV1

I have a problem with decoding of gray images encoded with FFV1 codec.
I successfully encode 16 bit gray image (with avcodec_receive_packet(...) function) and save AvPacket data to file. Then I read this data from file and try to decode (with avcodec_decode_video2 or avcodec_send_packet/avcodec_receive_frame) with no success:
when I try to decode packet with avcodec_decode_video2 function I get an error "Access violation occurred, unable to write location 0x0000000000000000".
when I try to decode packet with avcodec_send_packet/avcodec_receive_frame functions I get an error "chroma shift parameters 7 0 are invalid".
I compared packets after encoding and before decoding and all fields and values seems to be the same. I even try to decode packet just after avcodec_receive_packet (encoding function), however with the same error.
I use the 4.0 version of ffmpeg and the program is based on decode_video.c and encode_video.c examples.
When I use containers (eg. avi) to support read/write encoded images from file (based on demuxing_decoding.c and muxing.c examples) I successfully encode and decode frames with FFV1. However I cannot use containers, because I want to encode frames with different resolutions and mix few video sources together. Additionally the compression level is significantly lower (falls from 2.9 to 2.2) for few hundred of images, what is also very surprising.
So my question is how to correctly save/read (from binary file not container) and prepare AVPacker for decoding with FFV1.
Any help is greatly appreciated.
The decoding code:
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavutil/opt.h>
#include <libavutil/imgutils.h>
}
#pragma warning(disable: 4996)
#define INBUF_SIZE 4096
#define FF_INPUT_BUFFER_PADDING_SIZE 64
uint8_t endcode[4];
AVCodecContext *c, c2;
AVCodec *codec;
int i, ret, x, y;
AVFrame *frame;
AVPacket *pkt, *pkt_temp;
FILE *encodedVideoFile;
AVDictionary *opts = NULL;
uint8_t *video_dst_data[4] = { NULL };
int video_dst_linesize[4];
int imageSize;
uint8_t inbuf[INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
/* flush the encoder */
frame = NULL;
encode();
/* add sequence end code to have a real MPEG file */
//fwrite(endcode, 1, sizeof(endcode), encodedVideoFile);
fclose(encodedVideoFile);
avcodec_free_context(&c);
av_frame_free(&frame);
av_packet_free(&pkt);
}
void initDecoding(const char *filename)
{
/* set end of buffer to 0 (this ensures that no overreading happens for damaged MPEG streams) */
memset(inbuf + INBUF_SIZE, 0, AV_INPUT_BUFFER_PADDING_SIZE);
/* find the MPEG-1 video decoder */
codec = avcodec_find_decoder(AV_CODEC_ID_FFV1);
if (!codec) {
fprintf(stderr, "Codec not found\n");
exit(1);
}
c = avcodec_alloc_context3(codec);
if (!c) {
fprintf(stderr, "Could not allocate video codec context\n");
exit(1);
}
/* resolution must be a multiple of two */
c->width = 1280;
c->height = 484;
/* frames per second */
c->time_base.den = 1;
c->time_base.num = 10;
c->bits_per_raw_sample = 16;
c->framerate.den = 10;
c->framerate.num = 1;
c->pix_fmt = AV_PIX_FMT_GRAY16;
//Version of FFV1 codec
c->level = 3;
/* Init the decoders, with or without reference counting */
av_dict_set(&opts, "refcounted_frames", 0 ? "1" : "0", 0);
if ((ret = avcodec_open2(c, codec, &opts)) < 0) {
return;
}
if (avcodec_open2(c, codec, NULL) < 0) {
fprintf(stderr, "Could not open codec\n");
exit(1);
}
ret = av_image_alloc(video_dst_data, video_dst_linesize,
c->width, c->height, c->pix_fmt, 4);
if (ret < 0) {
fprintf(stderr, "Could not allocate raw video buffer\n");
}
encodedVideoFile = fopen(filename, "rb");
if (!encodedVideoFile) {
fprintf(stderr, "Could not open %s\n", filename);
exit(1);
}
frame = av_frame_alloc();
if (!frame) {
fprintf(stderr, "Could not allocate video frame\n");
exit(1);
}
frame->format = c->pix_fmt;
frame->width = c->width;
frame->height = c->height;
ret = av_frame_get_buffer(frame, 32);
if (ret < 0) {
fprintf(stderr, "Could not allocate the video frame data\n");
exit(1);
}
/* make sure the frame data is writable */
ret = av_frame_make_writable(frame);
if (ret < 0)
exit(1);
}
void closeDecoding()
{
fclose(encodedVideoFile);
av_parser_close(parser);
avcodec_free_context(&c);
av_frame_free(&frame);
av_packet_free(&pkt);
}
void decodePacket()
{
size_t data_size;
int *got_frame = 0;
read_packt_from_file(pkt, encodedVideoFile);
ret = av_frame_is_writable(frame);
//First decoding function
/*ret = avcodec_decode_video2(c, frame, got_frame, pkt);
if (ret < 0) {
fprintf(stderr, "Error decoding video frame (%s)\n");
}*/
ret = avcodec_send_packet(c, pkt);
if (ret < 0) {
fprintf(stderr, "Error sending a packet for decoding\n");
exit(1);
}
while (ret >= 0) {
ret = avcodec_receive_frame(c, frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
return;
else if (ret < 0) {
fprintf(stderr, "Error during decoding\n");
exit(1);
}
printf("saving frame %3d\n", c->frame_number);
fflush(stdout);
}
}
size_t read_packt_from_file(AVPacket *packet, FILE *file)
{
size_t ret = 0;
int size;
uint8_t * data;
//av_packet_from_data
ret = fread(packet, sizeof(AVPacket), 1, file);
size = packet->size;
data = new uint8_t[size];
ret = fread(data, size, 1, file);
av_new_packet(packet, size);
av_packet_from_data(packet, data, size);
return ret;
}
//To write encoded AVPacket
size_t write_packt_to_file(AVPacket *packet, FILE *file)
{
size_t ret = 0;
ret = fwrite(packet, sizeof(AVPacket), 1, file);
ret = fwrite(packet->data, packet->size, 1, file);
if (packet->buf) {
fwrite(packet->buf->data, packet->buf->size, 1, file);
}
fflush(file);
return ret;
}

Why there is no AVFrame->data[2] data when decode h264 by ffmpeg use "h264_cuvid"

env: ubuntu 16.04 64 bit; ffmpeg 3.3.2 build whih cuda cuvid libnpp...
use ffmpeg cmd: ffmpeg -vsync 0 -c:v h264_cuvid -i test.264 -f rawvideo test.yuv works fine, the generated yuv file is ok.
BUT When I decode this 264 file by my code use 'h264_cuvid' decoder, something problem happens, this is my code:
#include <stdio.h>
#define __STDC_CONSTANT_MACROS
#ifdef _WIN32
//Windows
extern "C"
{
#include "libavcodec/avcodec.h"
};
#else
//Linux...
#ifdef __cplusplus
extern "C"
{
#endif
#include <libavcodec/avcodec.h>
#ifdef __cplusplus
};
#endif
#endif
//test different codec
#define TEST_H264 1
#define TEST_HEVC 0
int main(int argc, char* argv[])
{
AVCodec *pCodec;
AVCodecContext *pCodecCtx= NULL;
AVCodecParserContext *pCodecParserCtx=NULL;
FILE *fp_in;
FILE *fp_out;
AVFrame *pFrame;
const int in_buffer_size=4096;
unsigned char in_buffer[in_buffer_size + FF_INPUT_BUFFER_PADDING_SIZE]= {0};
unsigned char *cur_ptr;
int cur_size;
AVPacket packet;
int ret, got_picture;
#if TEST_HEVC
enum AVCodecID codec_id=AV_CODEC_ID_HEVC;
char filepath_in[]="bigbuckbunny_480x272.hevc";
#elif TEST_H264
AVCodecID codec_id=AV_CODEC_ID_H264;
char filepath_in[]="2_60_265to264.264";
#else
AVCodecID codec_id=AV_CODEC_ID_MPEG2VIDEO;
char filepath_in[]="bigbuckbunny_480x272.m2v";
#endif
char filepath_out[]="mainSend.yuv";
int first_time=1;
//av_log_set_level(AV_LOG_DEBUG);
avcodec_register_all();
// pCodec = avcodec_find_decoder(codec_id);
pCodec = avcodec_find_decoder_by_name("h264_cuvid");
if (!pCodec)
{
printf("Codec not found\n");
return -1;
}
pCodecCtx = avcodec_alloc_context3(pCodec);
if (!pCodecCtx)
{
printf("Could not allocate video codec context\n");
return -1;
}
pCodecParserCtx=av_parser_init(pCodec->id);
if (!pCodecParserCtx)
{
printf("Could not allocate video parser context\n");
return -1;
}
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
{
printf("Could not open codec\n");
return -1;
}
//Input File
fp_in = fopen(filepath_in, "rb");
if (!fp_in)
{
printf("Could not open input stream\n");
return -1;
}
//Output File
fp_out = fopen(filepath_out, "wb");
if (!fp_out)
{
printf("Could not open output YUV file\n");
return -1;
}
pFrame = av_frame_alloc();
av_init_packet(&packet);
while (1)
{
cur_size = fread(in_buffer, 1, in_buffer_size, fp_in);
if (cur_size == 0)
break;
cur_ptr=in_buffer;
while (cur_size>0)
{
int len = av_parser_parse2(
pCodecParserCtx, pCodecCtx,
&packet.data, &packet.size,
cur_ptr, cur_size,
AV_NOPTS_VALUE, AV_NOPTS_VALUE, AV_NOPTS_VALUE);
cur_ptr += len;
cur_size -= len;
if(packet.size==0)
continue;
//Some Info from AVCodecParserContext
printf("[Packet]Size:%6d\t",packet.size);
switch(pCodecParserCtx->pict_type)
{
case AV_PICTURE_TYPE_I:
printf("Type:I\tNumber:%4d\n",pCodecParserCtx->output_picture_number);
break;
case AV_PICTURE_TYPE_P:
printf("Type:P\t");
break;
case AV_PICTURE_TYPE_B:
printf("Type:B\t");
break;
default:
printf("Type:Other\t");
break;
}
printf("Number:%4d\n",pCodecParserCtx->output_picture_number);
AVFrame* myFrame = av_frame_alloc();
ret = avcodec_decode_video2(pCodecCtx, myFrame, &got_picture, &packet);
if (ret < 0)
{
printf("Decode Error.\n");
return ret;
}
if (got_picture)
{
if(first_time)
{
printf("\nCodec Full Name:%s\n",pCodecCtx->codec->long_name);
printf("width:%d\nheight:%d\n\n",pCodecCtx->width,pCodecCtx->height);
first_time=0;
}
//Y, U, V
for(int i=0; i<myFrame->height; i++)
{
fwrite(myFrame->data[0]+myFrame->linesize[0]*i,1,myFrame->width,fp_out);
}
for(int i=0; i<myFrame->height/2; i++)
{
fwrite(myFrame->data[1]+myFrame->linesize[1]*i,1,myFrame->width/2,fp_out);
}
for(int i=0; i<myFrame->height/2; i++)
{
fwrite(myFrame->data[2]+myFrame->linesize[2]*i,1,myFrame->width/2,fp_out);
}
// printf("pframe's width height %d %d\t key frame %d\n",myFrame->width,myFrame->height,myFrame->key_frame);
printf("Succeed to decode 1 frame!\n");
av_frame_free(&myFrame);
}
}
}
fclose(fp_in);
fclose(fp_out);
av_parser_close(pCodecParserCtx);
av_frame_free(&pFrame);
avcodec_close(pCodecCtx);
av_free(pCodecCtx);
return 0;
}
In this demo code, I call h264_cuvid by vcodec_find_decoder_by_name("h264_cuvid");
BUT the code crash at fwrite(myFrame->data[2]+myFrame->linesize[2]*i,1,myFrame->width/2,fp_out);
So after debug with codeblocks, I found that there is no data in myFrame->data[2] codeblocks watching window
Any suggestion? thanks!
"h264" decoder's frame pix format is AV_PIX_FMT_YUV420P
BUT "h264_cuvid" decoder's frame pix format is AV_PIX_FMT_NV12
so, edit code to
for(int i=0; i<myFrame->height; i++)
{
fwrite(myFrame->data[0]+myFrame->linesize[0]*i,1,myFrame->width,fp_out);
}
for(int i=0; i<myFrame->height/2; i++)
{
fwrite(myFrame->data[1]+myFrame->linesize[1]*i,1,myFrame->width,fp_out);
}
Works fine

Resources