OpenVisualCloud / SVT-HEVC

SVT HEVC encoder. Scalable Video Technology (SVT) is a software-based video coding technology that is highly optimized for Intel® Xeon® processors. Using the open source SVT-HEVC encoder, it is possible to spread video encoding processing across multiple Intel® Xeon® processors to achieve a real advantage of processing efficiency.
Other
519 stars 169 forks source link

[SVT-HEVC] ReadInputFrames doesn't read last 9 bytes from fifo pipe because of Y4M header probing #432

Closed rayvbr closed 4 years ago

rayvbr commented 4 years ago

When sending N frames worth of raw YUV frames to SVT through a fifo pipe (note: without y4m header), SVT doesn't read the last frame. After some debugging, I believe this is caused by the following lines in Source/App/EbAppProcessCmd.c:

if (config->y4m_input == EB_FALSE && config->processedFrameCount == 0 && config->inputFile == stdin) {
                    /* if not a y4m file and input is read from stdin, 9 bytes were already read when checking
                       or the YUV4MPEG2 string in the stream, so copy those bytes over */
                    memcpy(ebInputPtr, config->y4m_buf, YUV4MPEG2_IND_SIZE);
                    headerPtr->nFilledLen += YUV4MPEG2_IND_SIZE;
                    ebInputPtr += YUV4MPEG2_IND_SIZE;
                    headerPtr->nFilledLen += (uint32_t)fread(ebInputPtr, 1, lumaReadSize - YUV4MPEG2_IND_SIZE, inputFile);
                }

The problem seems to be that this process is not applied when the input is fifo/named pipe.

The following patch seems to resolve the issue:

--- a/Source/App/EbAppProcessCmd.c
+++ b/Source/App/EbAppProcessCmd.c
@@ -822,5 +822,5 @@ static void ReadInputFrames(                    
               const uint32_t lumaReadSize = inputPaddedWidth * inputPaddedHeight << is16bit;
               ebInputPtr = inputPtr->luma;
-              if (config->y4m_input == EB_FALSE && config->processedFrameCount == 0 && config->inputFile == stdin) {
+              if (config->y4m_input == EB_FALSE && config->processedFrameCount == 0) {
                    /* if not a y4m file and input is read from stdin, 9 bytes were already read when checking
                       or the YUV4MPEG2 string in the stream, so copy those bytes over */
tianjunwork commented 4 years ago

Hi @rayvbr,

/* check if the input file is in YUV4MPEG2 (y4m) format */
EB_BOOL check_if_y4m(EbConfig_t *cfg) {
...
       //If we found this file is not y4m, we seek it back to the beginning.
        if (cfg->inputFile != stdin) {
            fseek(cfg->inputFile, 0, SEEK_SET);
        }
}

The problem is that, if inputFile is fifo, the fseek doesn’t work: ESPIPE The file descriptor underlying stream is not seekable (e.g.,refers to a pipe, FIFO, or socket). So in ReadInputFrames, we need to copy the 9 bytes back for input buffer.