Victor Akhlynin
Victor Akhlynin

Reputation: 51

c++ avformat_open_input returns empty codec, width and height

I haven't ever used ffmpeg on my own laptop. All's ok at work, but here I met an ugly problem: library works but helpless:) Ubuntu 18.04, ffmpeg 4.1 (downloaded sources, ./configure, make, sudo make install), it seems to be ok.

Application returns: File /home/ahlininv/Desktop/video_example.mp4 is encodec with '' codec, w = 0, h = 0

I ran it under debugger. If I set format to zero, pointer changes after calling avformat_open_input(&format, file, 0, &dict), so it works and maybe works correct.

Maybe it plays any role that compiler says that av_register_all, avcodec_register_all are deprecated, but I thought it's not significant problem.

I tried to change version of ffmpeg (tried to install it with apt-get, version 3.somenumber is available), nothing changed.

I tried to run another video file (.avi), nothing changed, too.

Guys, help=) How to this file's info correctly?

main.cpp:

#include "filereader.h"

int main(int argc, char** argv) {

    std::string filename = "/home/ahlininv/Desktop/video_example.mp4";

    std::string codec;
    int w, h;
    bool open_ok = get_file_info(filename.c_str(), codec, w, h);
    if (!open_ok) {
        std::cout << "Failed to open file" << "\n";
        return 1;
    }

    std::cout << "File " << filename << " is encoded with '" << codec << "' codec, w = " << w << ", h = " << h << "\n";

    return 0;
}

filereader.h:

#ifndef FILEREADER_H
#define FILEREADER_H

#include <string>
#include <iostream>

extern "C" {
#ifndef __STDC_CONSTANT_MACROS
#define __STDC_CONSTANT_MACROS
#endif
#include "libavcodec/avcodec.h"
#include <libavformat/avformat.h>
#include <libavutil/avutil.h>
}

bool get_file_info(const char* file, std::string& codec, int& w, int& h);

#endif // FILEREADER_H

filereader.cpp

#include "filereader.h"


bool get_file_info(const char* file, std::string& codec, int& w, int& h)
{
    codec = "";
    w = h = 0;

    av_register_all();
    avcodec_register_all();

    AVDictionary* dict = 0;
    AVFormatContext* format = avformat_alloc_context();

    char errbuf[256];
    int r = avformat_open_input(&format, file, 0, &dict);
    if (r!=0){
        av_strerror(r, errbuf, sizeof(errbuf));
        std::cout << "avformat_open_input error: " << errbuf << "\n";
    }

    if (r == AVERROR(EIO) || r == AVERROR(ENOEXEC) || !format)
        return false;

    for (size_t c = 0; c < format->nb_streams; ++c)
    {
        if (format->streams[c]->codecpar && format->streams[c]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
        {
            if (format->streams[c]->codecpar->codec_id != AV_CODEC_ID_NONE &&
                    format->streams[c]->codecpar->codec_id != AV_CODEC_ID_RAWVIDEO)
            {
                w = format->streams[c]->codecpar->width;
                h = format->streams[c]->codecpar->height;
                codec = avcodec_get_name(format->streams[c]->codecpar->codec_id);
            }
        }
    }
    avformat_close_input(&format);
    return true;
}

Compile:

g++ -o filereader main.cpp filereader.cpp -lavutil -lavformat -lavcodec -lavdevice -lz -lm -pthread -lswresample -lm -lz -I /usr/local/include/ -Wl,-rpath /usr/lib/x86_64-linux-gnu/

Upvotes: 2

Views: 1220

Answers (1)

the kamilz
the kamilz

Reputation: 1988

Can you add these lines Before for loop on filereader.cpp to see if it makes any difference.

if (avformat_find_stream_info(format, NULL) < 0)
{
    //handle error
}

Upvotes: 2

Related Questions