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 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…