как передать данные
От: sergey2b ЮАР  
Дата: 19.09.22 16:50
Оценка:
у мен есть С++ приложение которое принимает видеопоток и мне надо отправлять некоторые фреймы приложению на Python
для комуникации я использую named pipe
прототип на С++ работает нормально, но на Python нет

sender
#define _GNU_SOURCE

// C program to implement one side of FIFO
// This side writes first, then reads
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include<sys/wait.h>
#include <unistd.h>

#include <iostream>
#include <string>
#include <vector>

#include <opencv2/core/core.hpp>
#include <opencv2/video/video.hpp>
#include <opencv2/imgcodecs/imgcodecs.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/videoio/videoio.hpp>

#include <opencv2/core.hpp>
#include <opencv2/imgcodecs/legacy/constants_c.h>
#include <opencv2/videoio/legacy/constants_c.h>
#include <opencv2/photo/legacy/constants_c.h>
#include <opencv2/video/legacy/constants_c.h>

#ifdef _WIN64
#if _DEBUG
#pragma comment(lib, "opencv_world455d.lib")
#else
#pragma comment(lib, "opencv_world455.lib")
#endif
#endif

using namespace std;

#define PIPE_SIZE (512*1024)
#define BUFFER_SIZE (128*1024)

const int scale_value = 7;
const int quality = 95;

int main()
{
    int fd;

    // FIFO file path
    char * myfifo = "/tmp/myfifo";
    int nbytes=0;

    // Creating the named file(FIFO)
    // mkfifo(<pathname>, <permission>)
    mkfifo(myfifo, 0666);

//    char buffer[BUFFER_SIZE] = {0};
    
    // Open FIFO for write only
    //fd = open(myfifo, O_RDWR);
    fd = open(myfifo, O_WRONLY);
    
    printf("Pipe size: %d\n", fcntl(fd, F_GETPIPE_SZ));

    // resize the pipe with fcntl
    fcntl(fd, F_SETPIPE_SZ, PIPE_SIZE);
    printf("Pipe size: %d\n", fcntl(fd, F_GETPIPE_SZ));    
        
    while (1)
    {
        std::string image_path = "/home/superuser/Videos/0x0.jpg";
        cv::Mat img = cv::imread(image_path, cv::IMREAD_COLOR);
        if(img.empty())
        {
            std::cout << "Could not read the image: " << image_path << std::endl;
            return 1;
        }
        //cv::imshow("Display window", img);
        //int k = cv::waitKey(0); // Wait for a keystroke in the window        

        
        cv::Mat compressed_img;

        // Compression jpeg
        std::vector<int> compressing_factor;
        std::vector<uchar> buf;

        compressing_factor.push_back(cv::IMWRITE_JPEG_QUALITY);
        compressing_factor.push_back(quality);

        cv::imencode(".jpg", img, buf, compressing_factor);

        //compressed_img = cv::imdecode(buf, 1);

        // Shows processed image
        //cv::imshow("the recompressed image", compressed_img);
        //int k = cv::waitKey(0); // Wait for a keystroke in the window

        
        // Write the input arr2ing on FIFO
        // and close it
        nbytes = write(fd, buf.data(), buf.size());
        printf("buf.size%ld nbytes:%d\n",buf.size(),nbytes);
        
        //wait(NULL);
    }
    close(fd);
            
    return 0;
}


receiver
// C program to implement one side of FIFO
// This side reads first, then reads
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <algorithm>
#include <functional>
#include <iomanip>
#include <iostream>
#include <string_view>
#include <vector>

#include <opencv2/core/core.hpp>
#include <opencv2/video/video.hpp>
#include <opencv2/imgcodecs/imgcodecs.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/videoio/videoio.hpp>

#include <opencv2/core.hpp>
#include <opencv2/imgcodecs/legacy/constants_c.h>
#include <opencv2/videoio/legacy/constants_c.h>
#include <opencv2/photo/legacy/constants_c.h>
#include <opencv2/video/legacy/constants_c.h>

#ifdef _WIN64
#if _DEBUG
#pragma comment(lib, "opencv_world455d.lib")
#else
#pragma comment(lib, "opencv_world455.lib")
#endif
#endif

using namespace std;

#define PIPE_SIZE (512*1024)
#define BUFFER_SIZE (128*1024)

const int scale_value = 7;
const int quality = 95;

int main()
{
    int fd1;
    int nbytes=0;

    // FIFO file path
    char * myfifo = "/tmp/myfifo";

    // Creating the named file(FIFO)
    // mkfifo(<pathname>,<permission>)
    mkfifo(myfifo, 0666);

    unsigned char buffer[BUFFER_SIZE];
    
    // First open in read only and read
    fd1 = open(myfifo,O_RDONLY);
        
    while (1)
    {
        nbytes = read(fd1, buffer, BUFFER_SIZE);

        // Print the read string and close
        printf("nbytes=%d\n", nbytes);
        
        cv::Mat compressed_img;

        // Compression jpeg
        std::vector<uchar> buf(buffer, buffer+nbytes);
        
        printf("buf.size=%ld\n", buf.size());

        compressed_img = cv::imdecode(buf, 1);

        if (compressed_img.rows > 0 && compressed_img.cols > 0) { 
            // Shows processed image
            cv::imshow("the recompressed image", compressed_img);
            int k = cv::waitKey(1); // Wait for a keystroke in the window        
        }
        
    }
    close(fd1);
    
    return 0;
}


скрипт на python зависает на строке data = fifo.read()

import os
import errno

FIFO = "/tmp/myfifo"

try:
    mode = 0o600
    os.mkfifo(FIFO,mode)
except OSError as oe:
    if oe.errno != errno.EEXIST:
        raise

while True:
    print("Opening FIFO...")
    with open(FIFO, 'r+b', 0) as fifo:
        print("FIFO opened")
        while True:
            print('1')
            data = fifo.read()
            print('2')
            if len(data) == 0:
                print("Writer closed")
                break
            print('Read: "{0}"'.format(data))
Re: как передать данные
От: DiPaolo Россия  
Дата: 19.09.22 17:01
Оценка: 6 (1) +1
Ну с виду все норм. Надо дебажить.

Вот эта строка обращает на себя внимание

    with open(FIFO, 'r+b', 0) as fifo:


Возможно, стоит попробовать убрать '+'. И поиграться с третьим параметром: для начала убрать его вообще.

PS раздел форума кажется не тот.
Патриот здравого смысла
Re[2]: как передать данные
От: sergey2b ЮАР  
Дата: 19.09.22 17:29
Оценка:
Здравствуйте, DiPaolo, Вы писали:

DP>Ну с виду все норм. Надо дебажить.


в коде есть еще олна проблемма
я увеличил размер буфера pipe но всеравно некоторые видофреймы не влезают в этот буфер
и pipe передает их по частям (pipe is stream все логично)

но если на С читая поток я могу нормально найти маркеры начала и конца фрейма в буфере то на python это уже проблемма

например если маркер FI то он может распологаться в принятом буфере

FIqwertyuio
qwerFItyuio
qwertyuioFI
qwertyuioF

Re[3]: как передать данные
От: DiPaolo Россия  
Дата: 19.09.22 17:37
Оценка:
S>

S>FIqwertyuio
S>qwerFItyuio
S>qwertyuioFI
S>qwertyuioF


В чем проблема? С работой со строками vs работа с байтами?

Кстати, данные-то у вас бинарные ходят? Открываете как бинарный файл после изменений в коде? Отправляете тоже как бинарный?
Патриот здравого смысла
Re: как передать данные
От: PM  
Дата: 23.09.22 23:41
Оценка:
Здравствуйте, sergey2b, Вы писали:

S>у мен есть С++ приложение которое принимает видеопоток и мне надо отправлять некоторые фреймы приложению на Python

S>для комуникации я использую named pipe
S>прототип на С++ работает нормально, но на Python нет

Типичная ошибка новичка в сетевых программах — думать, что read/write читает/пишет указанное количество байт, хотя в документации явно сказано

read() attempts to read up to count bytes from file descriptor fd
into the buffer starting at buf.

...

RETURN VALUE

On success, the number of bytes read is returned (zero indicates
end of file), and the file position is advanced by this number.
It is not an error if this number is smaller than the number of
bytes requested; this may happen for example because fewer bytes
are actually available right now (maybe because we were close to
end-of-file, or because we are reading from a pipe, or from a
terminal), or because read() was interrupted by a signal. See
also NOTES.
...

write() writes up to count bytes from the buffer starting at buf
to the file referred to by the file descriptor fd.

The number of bytes written may be less than count if, for
example, there is insufficient space on the underlying physical
medium, or the RLIMIT_FSIZE resource limit is encountered (see
setrlimit(2)), or the call was interrupted by a signal handler
after having written less than count bytes. (See also pipe(7).)
...
RETURN VALUE

On success, the number of bytes written is returned. On error,
-1 is returned, and errno is set to indicate the error.

Note that a successful write() may transfer fewer than count
bytes. Such partial writes can occur for various reasons; for
example, because there was insufficient space on the disk device
to write all of the requested bytes, or because a blocked write()
to a socket, pipe, or similar was interrupted by a signal handler
after it had transferred some, but before it had transferred all
of the requested bytes.
...

Re[2]: как передать данные
От: sergey2b ЮАР  
Дата: 24.09.22 03:45
Оценка:
Здравствуйте, PM, Вы писали:

PM>Типичная ошибка новичка в сетевых программах — думать, что read/write читает/пишет указанное количество байт, хотя в документации явно сказано



спасибо
я читал про это в керниган ричи, но так как я знаю что в jpg есть специальный маркер начала файла и его конца
я решил не перегружать пример излишними деталями

ЗЫ проблемма была в том как opencv работает в С++ и Python
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.