h4tr3d / avcpp

C++ wrapper for FFmpeg
Other
459 stars 80 forks source link

How to decode a buffer of h264 data? #138

Open jinjun opened 6 months ago

jinjun commented 6 months ago

The following code works perfectly with native ffmpeg api. I'm wondering how to use avcpp to do the same? Thank you!

#include <iostream>
#include <stdexcept>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/avutil.h>

void decode_h264_packet(const uint8_t* data, int data_size) {
    AVCodec* codec = nullptr;
    AVCodecContext* codec_context = nullptr;
    AVPacket* packet = nullptr;
    AVFrame* frame = nullptr;

    try {
        // Initialize FFmpeg libraries (optional in newer FFmpeg versions)
        av_register_all();

        // Find the H.264 decoder
        codec = avcodec_find_decoder(AV_CODEC_ID_H264);
        if (!codec) {
            throw std::runtime_error("Codec not found");
        }

        // Allocate codec context
        codec_context = avcodec_alloc_context3(codec);
        if (!codec_context) {
            throw std::runtime_error("Could not allocate video codec context");
        }

        // Open codec
        if (avcodec_open2(codec_context, codec, nullptr) < 0) {
            throw std::runtime_error("Could not open codec");
        }

        // Allocate packet
        packet = av_packet_alloc();
        if (!packet) {
            throw std::runtime_error("Could not allocate AVPacket");
        }

        // Allocate frame
        frame = av_frame_alloc();
        if (!frame) {
            throw std::runtime_error("Could not allocate AVFrame");
        }

        // Fill packet with data
        packet->data = const_cast<uint8_t*>(data);
        packet->size = data_size;

        // Debug print to ensure packet data is correct
        std::cout << "Packet data size: " << packet->size << std::endl;

        // Send packet to decoder
        int response = avcodec_send_packet(codec_context, packet);
        if (response < 0) {
            throw std::runtime_error("Error sending packet to decoder: " + std::string(av_err2str(response)));
        }

        // Receive frame from decoder
        response = avcodec_receive_frame(codec_context, frame);
        if (response == AVERROR(EAGAIN) || response == AVERROR_EOF) {
            std::cout << "Decoder needs more packets or end of file reached." << std::endl;
            return;
        } else if (response < 0) {
            throw std::runtime_error("Error receiving frame from decoder: " + std::string(av_err2str(response)));
        }

        // Process the frame (for example, save or display it)
        std::cout << "Frame decoded successfully!" << std::endl;
    }
    catch (const std::runtime_error& e) {
        std::cerr << "Exception caught: " << e.what() << std::endl;
    }
    catch (...) {
        std::cerr << "Unknown exception caught" << std::endl;
    }

    // Free resources
    if (frame) av_frame_free(&frame);
    if (packet) av_packet_free(&packet);
    if (codec_context) avcodec_free_context(&codec_context);
}

int main() {
    // Sample H.264 packet data (replace with actual data)
    const uint8_t h264_packet_data[] = { /* H.264 data */ };
    int h264_packet_size = sizeof(h264_packet_data);

    // Decode the H.264 packet
    decode_h264_packet(h264_packet_data, h264_packet_size);

    return 0;
}