📄 video.c
字号:
cleanup(THREAD_FAILURE); } DBG("Video file successfully opened\n"); initMask |= VIDEOFILEINITIALIZED; /* Open the input fifo */ if (FifoUtil_open(&displayEnv.inFifo, sizeof(BufferElement)) == FIFOUTIL_FAILURE) { ERR("Failed to open input fifo\n"); cleanup(THREAD_FAILURE); } initMask |= INFIFOOPENED; /* Open the output fifo */ if (FifoUtil_open(&displayEnv.outFifo, sizeof(BufferElement)) == FIFOUTIL_FAILURE) { ERR("Failed to open output fifo\n"); cleanup(THREAD_FAILURE); } initMask |= OUTFIFOOPENED; /* Initialize the priming synchronization mutex */ pthread_mutex_init(&displayEnv.prime, NULL); /* Initialize the thread attributes */ if (pthread_attr_init(&attr)) { ERR("Failed to initialize thread attrs\n"); cleanup(THREAD_FAILURE); } /* Force the thread to use custom scheduling attributes */ if (pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED)) { ERR("Failed to set schedule inheritance attribute\n"); cleanup(THREAD_FAILURE); } /* Set the thread to be fifo real time scheduled */ if (pthread_attr_setschedpolicy(&attr, SCHED_FIFO)) { ERR("Failed to set FIFO scheduling policy\n"); cleanup(THREAD_FAILURE); } /* Set the thread priority */ schedParam.sched_priority = sched_get_priority_max(SCHED_FIFO); if (pthread_attr_setschedparam(&attr, &schedParam)) { ERR("Failed to set scheduler parameters\n"); cleanup(THREAD_FAILURE); } /* Create the thread */ displayEnv.hRendezvous = envp->hRendezvous; if (pthread_create(&displayThread, &attr, displayThrFxn, &displayEnv)) { ERR("Failed to create display thread\n"); cleanup(THREAD_FAILURE); } initMask |= DISPLAYTHREADCREATED; DBG("Display thread created\n"); /* Reset, load, and start DSP Engine */ hEngine = Engine_open(ENGINE_NAME, NULL, NULL); if (hEngine == NULL) { ERR("Failed to open codec engine %s\n", ENGINE_NAME); cleanup(THREAD_FAILURE); } DBG("Codec Engine opened in video thread\n"); initMask |= ENGINEOPENED; /* Allocate and initialize video decoder on the engine */ if (videoDecodeAlgCreate(hEngine, &hDecode, envp->videoDecoder, &lState.readSize) == FAILURE) { cleanup(THREAD_FAILURE); } DBG("Video decoder created\n"); initMask |= VIDEODECODERCREATED; lState.readBuffer = (char *) Memory_contigAlloc(lState.readBufSize, Memory_DEFAULTALIGNMENT); if (lState.readBuffer == NULL) { ERR("Failed to allocate contiguous memory block.\n"); cleanup(THREAD_FAILURE); } DBG("Contiguous buffer allocated at physical address 0x%lx\n", Memory_getPhysicalAddress(lState.readBuffer)); initMask |= READBUFFERALLOCATED; memset(bufferElements, 0, sizeof(BufferElement) * DISPLAY_BUFFERS); for (i=0; i < DISPLAY_BUFFERS; i++) { bufferElements[i].frameBuffer = (char *) Memory_contigAlloc(D1_MAX_FRAME_SIZE, Memory_DEFAULTALIGNMENT); if (bufferElements[i].frameBuffer == NULL) { ERR("Failed to allocate contiguous memory block.\n"); cleanup(THREAD_FAILURE); } DBG("Contiguous buffer allocated at physical address 0x%lx\n", Memory_getPhysicalAddress(bufferElements[i].frameBuffer)); bufferElements[i].id = i; } initMask |= DISPLAYBUFFERSALLOCATED; /* Signal that initialization is done and wait for other threads */ Rendezvous_meet(envp->hRendezvous);prime: /* Prime the file loader */ if (loaderPrime(&lState, &framePtr) == FAILURE) { cleanup(THREAD_FAILURE); } /* Lock the display priming mutex */ pthread_mutex_lock(&displayEnv.prime); /* Tell the display thread that we are priming */ e.id = DISPLAY_PRIME; if (FifoUtil_put(&displayEnv.outFifo, &e) == FIFOUTIL_FAILURE) { ERR("Failed to put buffer to output fifo\n"); pthread_mutex_unlock(&displayEnv.prime); cleanup(THREAD_FAILURE); } outputID = 0; frameDone = 1; /* Prime the display thread with buffers */ for (i=0; i < DISPLAY_BUFFERS; i++) { /* If interlaced frame, use same destination for both fields */ if (outputID == BUFFER_KEPT_RESUBMIT_DST) { i--; } if (decodeVideoBuffer(hDecode, framePtr, lState.readSize, i, bufferElements[i].frameBuffer, &frameSize, &outputID, &frameStats, &frameDone) == FAILURE) { breakLoop(THREAD_FAILURE); } if (lState.firstFrame) { if (getClipSize(hDecode, &clipWidth, &clipHeight) == FAILURE) { breakLoop(THREAD_FAILURE); } } /* Read a new frame of encoded data from disk */ if (loaderGetFrame(&lState, frameSize, &framePtr) == FAILURE) { breakLoop(THREAD_FAILURE); } if (lState.endClip) { ERR("Clip needs to have at least %d frames\n", DISPLAY_BUFFERS); breakLoop(THREAD_FAILURE); } if (outputID >= 0) { bufferElements[outputID].width = clipWidth; bufferElements[outputID].height = clipHeight; if (FifoUtil_put(&displayEnv.outFifo, &bufferElements[outputID]) == FIFOUTIL_FAILURE) { ERR("Failed to put buffer in output fifo\n"); breakLoop(THREAD_FAILURE); } numDisplayBufs++; } } /* Release the display thread */ pthread_mutex_unlock(&displayEnv.prime); DBG("Entering video main loop.\n"); while (!gblGetQuit()) { /* Get a used buffer from display thread if required */ if (outputID != BUFFER_KEPT_RESUBMIT_DST) { /* Receive a buffer with a displayed frame from display thread */ if (FifoUtil_get(&displayEnv.inFifo, &e) == FIFOUTIL_FAILURE) { ERR("Failed to get buffer from input fifo\n"); breakLoop(THREAD_FAILURE); } /* Is the display thread flushing the pipe? */ if (e.id == DISPLAY_FLUSH) { breakLoop(THREAD_SUCCESS); } numDisplayBufs--; } /* Decode the encoded frame to the display frame buffer */ if (decodeVideoBuffer(hDecode, framePtr, lState.readSize, e.id, e.frameBuffer, &frameSize, &outputID, &frameStats, &frameDone) == FAILURE) { breakLoop(THREAD_FAILURE); } /* If the codec didn't keep the buffer, send it to the display thread */ if (outputID >= 0) { bufferElements[outputID].width = clipWidth; bufferElements[outputID].height = clipHeight; if (FifoUtil_put(&displayEnv.outFifo, &bufferElements[outputID]) == FIFOUTIL_FAILURE) { ERR("Failed to put buffer to output fifo\n"); breakLoop(THREAD_FAILURE); } numDisplayBufs++; } /* Read a new frame of encoded data from disk */ if (loaderGetFrame(&lState, frameSize, &framePtr) == FAILURE) { breakLoop(THREAD_FAILURE); } if (lState.endClip) { /* Drain the display thread */ while (numDisplayBufs > 0) { if (FifoUtil_get(&displayEnv.inFifo, &e) == FIFOUTIL_FAILURE) { ERR("Failed to get buffer from input fifo\n"); breakLoop(THREAD_FAILURE); } /* Is the display thread flushing the pipe? */ if (e.id == DISPLAY_FLUSH) { breakLoop(THREAD_SUCCESS); } numDisplayBufs--; } /* Recreate the algorithm */ VIDDEC_delete(hDecode); if (videoDecodeAlgCreate(hEngine, &hDecode, envp->videoDecoder, &lState.readSize) == FAILURE) { breakLoop(THREAD_FAILURE); } /* Reprime the file loader and display thread */ goto prime; } gblIncVideoBytesEncoded(frameSize); } printf("\nTotal I-frames: %d, P-frames: %d, B-frames: %d, IDR-frames: %d " "rejected: %d\n", frameStats.iFrames, frameStats.pFrames, frameStats.bFrames, frameStats.idrFrames, frameStats.framesRejected);cleanup: /* Make sure the other threads aren't waiting for init to complete */ Rendezvous_force(envp->hRendezvous); /* Make sure the display thread isn't stuck in FifoUtil_get() */ FifoUtil_put(&displayEnv.outFifo, &flush); /* Drain the display thread */ while (numDisplayBufs-- > 0 && e.id != DISPLAY_FLUSH) { if (FifoUtil_get(&displayEnv.inFifo, &e) == FIFOUTIL_FAILURE) { ERR("Failed to get buffer from input fifo\n"); break; } } /* Clean up the video thread */ if (initMask & DISPLAYBUFFERSALLOCATED) { for (i=0; i < DISPLAY_BUFFERS; i++) { if (bufferElements[i].frameBuffer) { Memory_contigFree(bufferElements[i].frameBuffer, D1_MAX_FRAME_SIZE); } } } if (initMask & READBUFFERALLOCATED) { Memory_contigFree(lState.readBuffer, lState.readBufSize); } if (initMask & VIDEODECODERCREATED) { VIDDEC_delete(hDecode); } if (initMask & ENGINEOPENED) { Engine_close(hEngine); } if (initMask & DISPLAYTHREADCREATED) { if (pthread_join(displayThread, &ret) == 0) { status = ret; } pthread_mutex_destroy(&displayEnv.prime); } if (initMask & OUTFIFOOPENED) { FifoUtil_close(&displayEnv.outFifo); } if (initMask & INFIFOOPENED) { FifoUtil_close(&displayEnv.inFifo); } if (initMask & VIDEOFILEINITIALIZED) { close(lState.inputFd); } return status;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -