2017-06-13 3 views
-2

私はlibvlcライブラリを使用してh264ストリームからビデオフレームを取得するソリューションを開発することに興味があります。私はlibvlc_video_set_format_callbacksにコールバックを設定して、私のコールバック関数(format_callback)パラメータから、以下の情報を受け取っている:クロマ:「J420」、幅:1088、高さ:1922正しくlibvlc(C++)を使ってh264ビデオストリームからフレームを取得するには?

私はそれをプリント

Player p; 
p.play("rtsp://path/to/camera?videocodec=h264"); 
メイン

で呼び出す場合エラー後に出てきます

chroma "J420" width: 1088 , height: 1922 
[00007fddfc001268] core vout display error: Failed to change zoom 
[00007fddfc001268] core vout display error: Failed to set on top 
[00007fddfc001268] core vout display error: Failed to change source AR 
[h264 @ 0x7fde1c06cea0] error while decoding MB 24 111, bytestream -15 
[swscaler @ 0x7fddfc002ca0] bad dst image pointers 
[swscaler @ 0x7fddfc002ca0] bad dst image pointers 

私の推測では、バッファとそのサイズに問題があります。どこで、フレームごとにビデオを取得するためにどの種類のバッファを使用するのですか?後でフレームデータをQImageに転送する予定です。

const int ResoHeight = 1922; 
const int ResoWidth = 1088; 
const int BytesPerPixel = 3; // not sure about this 

struct ImageData 
{ 
    QVector<unsigned char> raw; 
    QVector<unsigned char> picture; 

    ImageData() 
    { 
    raw.resize(BytesPerPixel * ResoHeight * ResoWidth); 
    picture.resize(BytesPerPixel * ResoHeight * ResoWidth); 
    } 
}; 

class Player : public QObject 
{ 
    Q_OBJECT 
public: 
    explicit Player(QObject *parent = nullptr); 
    ~Player(); 

    void play(const std::string& path); 

signals: 
    void newImage(const QImage& image); 

private: 
    libvlc_instance_t* vlcInstance; 
    libvlc_media_player_t* player; 
    libvlc_media_t* media; 
    ImageData buffer; 
}; 

Player.cppは以下の通りです::以下はPlayer.hファイルがある

namespace { 
void* lock_frame(void *opaque, void **planes) 
{ 
    ImageData* buf = (ImageData*)(opaque); 
    *planes = buf->raw.data(); 
    return buf->picture.data(); 
} 

void unlock_frame(void *opaque, void *picture, void *const *planes) 
{ 
    // will be logic to announce new image 
} 

unsigned format_callback(void** opaque, char* chroma, unsigned *width, unsigned *height, unsigned *pitches, unsigned *lines) 
{ 
    qDebug() << "chroma:" << QString(chroma) << "width:" << *width << ", height:" << *height; 

    *pitches= (*width) * BytesPerPixel; 
    *lines= *height; 

    return 1; 
} 

} // namespace 

Player::Player(QObject* parent) 
    : QObject(parent) 
    , vlcInstance(libvlc_new(0, nullptr)) 
    , player(libvlc_media_player_new(vlcInstance)) 
    , media(nullptr) 
{ 
} 

Player::~Player() 
{ 
    libvlc_media_player_stop(player); 
    libvlc_media_player_release(player); 
    libvlc_release(vlcInstance); 
} 

void Player::play(const std::string& path) 
{ 
    media = libvlc_media_new_location(vlcInstance, path.c_str()); 
    libvlc_media_player_set_media(player, media); 
    libvlc_media_release(media); 

    libvlc_video_set_callbacks(player, lock_frame, unlock_frame, nullptr, &buffer); 
    libvlc_video_set_format_callbacks(player, format_callback, nullptr); 

    libvlc_media_player_play(player); 
} 
+0

'バッファ'は初期化されていません。 format_callback関数で初期化する必要があります。 – seleciii44

+0

'buffer'はImageDataの型であり、そのコンストラクタで初期化されます。もちろん、 'format_callback'関数で初期化するのは正しいでしょうが、それが問題の原因であってはいけません。バッファのサイズ変更メソッドを 'format_callback'に移動して試しました。同じエラー。申し訳ありませんが、それを認識していませんでした。 – psalong

+0

J420クロマは、平面YUV形式のhttps://wiki.videolan.org/YUV/です。つまり、lock_frameに3つのイメージポインタを指定する必要があります。 RGB(RV24)画像が必要な場合は、この質問をご覧くださいhttps://stackoverflow.com/q/40365353/1632887 – seleciii44

答えて

0

J420の彩度がplanar YUV形式です。つまり、pitcheslinesformat_callbackに、planesのポインタをlock_frameの3つの異なるポインタ(各プレーン)に提供する必要があります。 RGB(RV24)イメージだけが必要な場合は、this questionを参照してください。

関連する問題