Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
149 views
in Technique[技术] by (71.8m points)

c++ - FFmpeg: Decoding AVPackets received from TCP socket

I have a TCP socket that receives video stream from client and i need to decode to cv::Mat, for decoding i used ffmpeg library but avcodec_send_packet() always return negative value. Anyone know what is wrong?

Error message: [cyuv @ 0x1c8e660] got a buffer with 6 bytes when 48 were expected. Error sending a packet for decoding

socket server code: sserver.hpp*

#pragma once

#include <iostream>
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <vector>

    class sserver {
    public:
        sserver() = default;
        sserver(size_t port) {
            port_ = port;
        }
        void start() {
            socket();

            int opt = 1;
            setsockopt(opt);

            struct timeval tv;
            tv.tv_sec = 5;
            tv.tv_usec = 0;
            setsockopt(tv);

            bind();
            listen();
            accept();
            std::cout<<"[info]: Server started
";
        }
    private:
        void socket() {
            std::cout<<"[info]: Creating socket file descriptor"<<std::endl;
            if ((server_fd_ = ::socket(AF_INET, SOCK_STREAM, 0)) == 0)
            {
                perror("socket failed");
                exit(EXIT_FAILURE);
            }
        }

        void setsockopt(int opt) {
            std::cout<<"[info]: setsockopt "<<std::endl;
            if (::setsockopt(server_fd_, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT,
                           &opt, sizeof(opt)))
            {
                perror("setsockopt");
                exit(EXIT_FAILURE);
            }
            address_.sin_family = AF_INET;
            address_.sin_addr.s_addr = INADDR_ANY;
            address_.sin_port = htons( port_ );
        }

        void setsockopt(struct timeval& tv) {
            std::cout<<"[info]: setsockopt "<<std::endl;
            if (::setsockopt(server_fd_, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, (const char*)&tv, sizeof(tv)))
            {
                perror("setsockopt");
                exit(EXIT_FAILURE);
            }
            address_.sin_family = AF_INET;
            address_.sin_addr.s_addr = INADDR_ANY;
            address_.sin_port = htons( port_ );
        }

        void bind() {
            std::cout<<"[info]: Forcefully bind socket to the port "<<port_<<std::endl;
            if (::bind(server_fd_, (struct sockaddr *)&address_, sizeof(address_)) < 0)
            {
                perror("bind failed");
                exit(EXIT_FAILURE);
            }
        }

        void listen() {
            std::cout<<"[info]: Start listen"<<std::endl;
            if (::examplelisten(server_fd_, 3) < 0)
            {
                perror("listen");
                exit(EXIT_FAILURE);
            }
        }

        void accept() {
            std::cout<<"[info]: Accept connection"<<std::endl;
            int addrlen = sizeof(address_);
            while ((socket_ = ::accept(server_fd_, (struct sockaddr *)&address_,(socklen_t*)&addrlen)) < 0)
            {
                perror("accept");
                exit(EXIT_FAILURE);
            }
            close(server_fd_);
        }

    public:

        int read(uint8_t *buf, int buf_size) {
            int valread = ::read( socket_ , buf, buf_size);
            return valread;
        }

    private:
        ssize_t server_fd_;
        ssize_t socket_;
        struct sockaddr_in address_;
        int port_ = 5555;
    };

ffmpeg decoder: decoder.hpp

#pragma once

extern "C" {
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
};

#include <iostream>

class decoder {
public:
    decoder() {
        init();
    }

public:
    void init() {
        av_register_all();
        avformat_network_init();
        pPacket = av_packet_alloc();
        if (!pPacket) {
            std::cout << "packet alloc error
";
        }

        pCodec = avcodec_find_decoder(AV_CODEC_ID_H264);
        if (!pCodec) {
            std::cout << "codec alloc error
";
        }

        pParser = av_parser_init(pCodec->id);
        if (!pParser) {
            std::cout << "parser alloc error
";
        }

        pCodecContext = avcodec_alloc_context3(pCodec);
        if (!pCodecContext) {
            std::cout << "codec ctx alloc error
";
        }

        if (avcodec_open2(pCodecContext, pCodec, NULL) < 0) {
            std::cout << "Codec open error
";
        }
    }

    cv::Mat decode(uint8_t *buffer, size_t buffer_size) {
        uint8_t inbuf[327680];

        uint8_t *data = buffer;
        size_t data_size = buffer_size;

        pPacket->data = new uint8_t[data_size];
        memcpy(pPacket->data, data, data_size);
        pPacket->size = data_size;

        pFrame = av_frame_alloc();
        if (!pFrame) {
            std::cout << "frame alloc error
";
        }

        int ret;
        while (data_size > 0) {

            if (pPacket->size) {
                int ret;

                ret = avcodec_send_packet(pCodecContext, pPacket);
                if (ret < 0) {
                    fprintf(stderr, "Error sending a packet for decoding
");
                    exit(1);
                }

                while (ret >= 0) {
                    ret = avcodec_receive_frame(pCodecContext, pFrame);
                    if (ret < 0) {
                        fprintf(stderr, "Error during decoding
");
                        exit(1);
                    } else {
                        // TODO: convert cv::Mat and return
                    }
                }
            }
        }
    }

private:
    AVFormatContext *pFormatContext;
    AVCodecParameters *pCodecParameters;
    AVCodecParserContext *pParser;
    AVCodec *pCodec;
    AVCodecContext *pCodecContext;
    AVPacket *pPacket;
    AVFrame *pFrame;
    int video_stream;
};

main.cpp

#include <iostream>
#include "sserver.hpp"
#include "new_decoder.hpp"

int main() {
    sserver sserver(5555);
    sserver.start();

    int buf_size = 327680;
    uint8_t *buf = new uint8_t[buf_size];
    int len = sserver.read(buf, buf_size);

    decoder decoder;
    while (true) {
        len = sserver.read(buf, buf_size);
        decoder.decode((unsigned char *) buf, len);
    }
    return 0;
}
question from:https://stackoverflow.com/questions/65921592/ffmpeg-decoding-avpackets-received-from-tcp-socket

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...