(C_UDP Socket编程) 如何将二进制文件转换为视频格式?

问题描述 投票:0回答:1

我正在练习UDP套接字编程。我的代码的功能如下。

  1. 连接服务器-客户端并互相发送“hello”消息(正在工作)。
  2. 然后服务器正在向客户端发送视频文件(问题)。

将视频文件传输到客户端正在工作。但它是用二进制编写的,所以我无法打开视频。

所以我尝试使用ffmpeg来转换视频,但是不起作用。

我的代码有问题吗?如何将接收到的文件转换为视频文件?

我的环境是MacOs。

Server.c(服务器代码):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/socket.h>

#define PORT 8888
#define BUF_SIZE 256

int main(){
    int serv_sock;
    char message[BUF_SIZE];
    char buf[BUF_SIZE];
    int str_len;
    socklen_t clnt_adr_sz;

    struct sockaddr_in serv_adr, clnt_adr;
    
    //create socket
    serv_sock=socket(PF_INET, SOCK_DGRAM, 0);
    if(serv_sock == -1){
        perror("socket() error");
        exit(1);
    }
    
    //socket address
    memset(&serv_adr, 0, sizeof(serv_adr));
    serv_adr.sin_family=AF_INET;
    serv_adr.sin_addr.s_addr=htonl(INADDR_ANY);
    serv_adr.sin_port=htons(PORT);
    //binding socket
    if(bind(serv_sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr)) == -1){
        perror("bind() error");
        exit(1);
    }
    
    while(1){
        clnt_adr_sz=sizeof(clnt_adr);
        str_len=recvfrom(serv_sock, message, BUF_SIZE, 0, (struct sockaddr *)&clnt_adr, &clnt_adr_sz);
         if (str_len < 0) {
            perror("recvfrom error");
            exit(1);
        }
    
        char hello_message[] = "hello i am server";
        if (sendto(serv_sock, hello_message, strlen(hello_message), 0, (struct sockaddr *)&clnt_adr, clnt_adr_sz) < 0) {
            perror("sendto error");
            exit(1);
        }
        
        //print message
        message[str_len] = '\0';
        printf("client say: %s\n", message);
        
        char buf[BUF_SIZE];
        ssize_t bytes_read;
        // sending viedo file
        printf("sending video file...\n");
        size_t fsize;
    
        //video file
        FILE *file;
        char *filename = "video.mp4";
        // open video file
        file = fopen(filename, "rb");
        if (file == NULL) {
            perror("File opening failed");
            exit(EXIT_FAILURE);
        }
        //calculate video file memory
        fseek(file, 0, SEEK_END);
        fsize = ftell(file);
        fseek(file,0,SEEK_SET);
    
        size_t size = htonl(fsize);
        int nsize =0;
        
        while(nsize!=fsize){
            int fpsize = fread(buf,1, BUF_SIZE, file);
            nsize += fpsize;
            if (sendto(serv_sock, &size, sizeof(size), 0, (struct sockaddr *)&clnt_adr, clnt_adr_sz) < 0) {
                perror("sendto");
                exit(EXIT_FAILURE);    
            }
            fclose(file);
            /*
            while ((bytes_read = fread(buf, 1, BUF_SIZE, file)) > 0) {
                if (sendto(serv_sock, buf, bytes_read, 0,
                       (struct sockaddr *)&clnt_adr, clnt_adr_sz) < 0) {
                    perror("sendto");
                    exit(EXIT_FAILURE);
                }       
            }
            */
        }        
    }
    close(serv_sock);
    return 0;
}

Client.c(客户端代码)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/socket.h>

#define BUFSIZE 256
#define PORT 8888

int main(){
    int sock;
    char message[BUFSIZE];
    int str_len;
    socklen_t adr_sz;

    struct sockaddr_in serv_addr, client_addr;   
    
    sock = socket(PF_INET, SOCK_DGRAM, 0);
    if(sock == -1){
        printf("socket() error\n");
        exit(1);
    }

    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    serv_addr.sin_port = htons(PORT);

    char hello_message[] = "hello i am client";
    sendto(sock, hello_message, strlen(hello_message), 0, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
    adr_sz = sizeof(client_addr);
    str_len=recvfrom(sock,message,BUFSIZE,0,(struct sockaddr*)&client_addr,&adr_sz);
   
    message[str_len] = '\0';
    printf("client say: %s\n", message);
    
    /*
    char buf[BUFSIZE];
    ssize_t bytes_received;
    socklen_t serv_len = sizeof(serv_addr);
    while ((bytes_received = recvfrom(sock, buf, BUFSIZE, 0,
                                      (struct sockaddr *)&serv_addr, &serv_len)) > 0) {
        fwrite(buf, 1, bytes_received, file);
    }
    */
     
    FILE *file = fopen("received_test.mp4", "wb");

    int nbyte = BUFSIZE;
    while(nbyte>= BUFSIZE){
        nbyte = recvfrom(sock, message, BUFSIZE, 0, (struct sockaddr*)&serv_addr, &adr_sz);
        fwrite(message, sizeof(char), nbyte, file);
    }

    if (file == NULL) {
        perror("File opening failed");
        exit(EXIT_FAILURE);
    }

    fclose(file);
    close(sock);
    printf("File received successfully\n");
    
    return 0;
}

我尝试使用 ffmpeg 将二进制文件转换为

.mp4
文件 但它不起作用:

ffmpeg -i received_test.mp4 output.mp4
ffmpeg version 7.0 Copyright (c) 2000-2024 the FFmpeg developers
  built with Apple clang version 15.0.0 (clang-1500.3.9.4)
  configuration: --prefix=/opt/homebrew/Cellar/ffmpeg/7.0 --enable-shared --enable-pthreads --enable-version3 --cc=clang --host-cflags= --host-ldflags='-Wl,-ld_classic' --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libaribb24 --enable-libbluray --enable-libdav1d --enable-libharfbuzz --enable-libjxl --enable-libmp3lame --enable-libopus --enable-librav1e --enable-librist --enable-librubberband --enable-libsnappy --enable-libsrt --enable-libssh --enable-libsvtav1 --enable-libtesseract --enable-libtheora --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopenvino --enable-libspeex --enable-libsoxr --enable-libzmq --enable-libzimg --disable-libjack --disable-indev=jack --enable-videotoolbox --enable-audiotoolbox --enable-neon
  libavutil      59.  8.100 / 59.  8.100
  libavcodec     61.  3.100 / 61.  3.100
  libavformat    61.  1.100 / 61.  1.100
  libavdevice    61.  1.100 / 61.  1.100
  libavfilter    10.  1.100 / 10.  1.100
  libswscale      8.  1.100 /  8.  1.100
  libswresample   5.  1.100 /  5.  1.100
  libpostproc    58.  1.100 / 58.  1.100
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x12a62bdb0] Format mov,mp4,m4a,3gp,3g2,mj2 detected only with low score of 1, misdetection possible!
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x12a62bdb0] moov atom not found
[in#0 @ 0x12b0043c0] Error opening input: Invalid data found when processing input
Error opening input file received_test.mp4.
Error opening input files: Invalid data found when processing input
c sockets video ffmpeg udp
1个回答
0
投票

在服务器端,您不会将文件的字节发送到客户端,而是一遍又一遍地发送

size
变量。并且,您将在第一次循环迭代后关闭文件,因此后续迭代无法再从文件中读取。

© www.soinside.com 2019 - 2024. All rights reserved.