📄 play_avi_push.c
字号:
} } }#endif#if 0 if (decoder == 0) return;#endif if (chunkLength == 0) { RMDBGLOG((AVIDBG, "discard 0 size chunk\n")); return; } if (FSMstate == RM_PSM_Prebuffering) RMDBGPRINT((ENABLE, "%s", (decoder == avi_info->dcc_info->video_decoder) ? "v":"a")); if ((decoder == avi_info->dcc_info->video_decoder) && (avi_info->dontSendMPEG4pts)) { // do not send pts for MPEG4, bug 6018 RMbool isIFrame = FALSE; if ((chunkLength > 4) && (flags & RMAVI_FLAG_CHUNK_START)) { // send PTS only for IFrames, bug 6769 (this is a hack) RMuint8 *dummy = chunk; RMuint8 byte; RMuint32 i; RMDBGPRINT((DISABLE, "chunk of size %7lu, pts %9llu is: '", chunkLength, Info.TimeStamp)); for (i = 0; i < chunkLength-3; i++) { if ((dummy[i] == 0) && (dummy[i+1] == 0) && (dummy[i+2] == 1) && (dummy[i+3] == 0xb6)) { byte = dummy[4]; byte &= 0xC0; byte >>= 6; RMDBGPRINT((DISABLE, "%s", (byte == 0) ? "I": ((byte == 1) ? "P": ((byte == 2) ? "B":"")))); if (byte == 0) isIFrame = TRUE; } } RMDBGPRINT((DISABLE, "'\n")); } if ((!avi_info->firstPTS) && !isIFrame) { if ((FSMstate != RM_PSM_IForward) && (FSMstate != RM_PSM_IRewind)) { Info.TimeStamp = 0; Info.ValidFields = 0; } }#if 0 else if (Info.ValidFields) avi_info->firstPTS = FALSE;#endif if (isIFrame) { RMDBGLOG((ENABLE, "send pts for iframe %lu size %6lu, pts %8llu valid %lu\n", avi_info->videoFrameCounter, chunkLength, Info.TimeStamp, Info.ValidFields)); } } RMDBGLOG((SENDDBG, "sending %s size %6lu pts %8llu valid %lu\n", (decoder == avi_info->dcc_info->video_decoder) ? "video":"audio", chunkLength, Info.TimeStamp, Info.ValidFields));#if 0 if (decoder != avi_info->dcc_info->video_decoder) { RMDBGLOG((ENABLE, "ByteCounter %lu FrameCounter %lu PTS %llu TimeScale %lu TimeBase %lu SampleRate %lu\n", avi_info->audio_info[avi_info->currentAudioIndex].audioByteCounter, avi_info->audio_info[avi_info->currentAudioIndex].audioFrameCounter, avi_info->audio_info[avi_info->currentAudioIndex].audioPTS, avi_info->audio_info[avi_info->currentAudioIndex].audioTimeScale, avi_info->audio_info[avi_info->currentAudioIndex].audio_base, avi_info->audio_info[avi_info->currentAudioIndex].audio_sample_rate)); RMDBGLOG((ENABLE, "sending %s size %6lu pts %8llu valid %lu\n", (decoder == avi_info->dcc_info->video_decoder) ? "video":"audio", chunkLength, Info.TimeStamp, Info.ValidFields)); }#endif if ((avi_info->firstPTS) && (Info.ValidFields & TIME_STAMP_INFO)) { RMuint32 scale = (decoder == avi_info->dcc_info->video_decoder) ? avi_info->vopTimeIncrementResolution : avi_info->audio_info[avi_info->currentAudioIndex].audioTimeScale; RMDBGLOG((ENABLE, "firstPTS is %s %llu/%lu (valid %lu)\n", (decoder == avi_info->dcc_info->video_decoder) ? "video":"audio", Info.TimeStamp, scale, Info.ValidFields)); avi_info->firstPTS = FALSE; if (scale) DCCSTCSetTime(avi_info->dcc_info->pStcSource, Info.TimeStamp - (scale / 3), scale); } if (isAudio) { RMint32 lastOKinstance = -1; if (!play_opt->send_audio) return; while (DCCMultipleAudioSendData(avi_info->dcc_info->pMultipleAudioSource, avi_info->pDMA, chunk, chunkLength, &Info, sizeof(Info), &lastOKinstance) != RM_OK) { struct DCCAudioSourceHandle audioHandle; struct RUAEvent e; if (lastOKinstance == -1) return; //RMDBGLOG((ENABLE, "Cannot send audio data\n")); check_prebuf_state(avi_info, 0); switch ((avi_info->label = local_process_key(avi_info, TRUE))) { case LABEL_ERROR: case LABEL_QUIT: case LABEL_STOP: case LABEL_STOP_SEEK_ZERO: avi_info->quitCallback = TRUE; return; case LABEL_NONE: break; } FSMstate = RM_PSM_GetState(avi_info->PSMcontext, &(avi_info->dcc_info)); /* skip audio in trickmode */ if ((FSMstate != RM_PSM_Playing) && (FSMstate != RM_PSM_Paused)) return; err = DCCMultipleAudioSourceGetSingleDecoderHandleForInstance(avi_info->dcc_info->pMultipleAudioSource, lastOKinstance, &audioHandle); if (RMFAILED(err)) return; e.ModuleID = audioHandle.moduleID; e.Mask = RUAEVENT_XFER_FIFO_READY; RUAWaitForMultipleEvents(avi_info->pRUA, &e, 1, SENDDATA_TIMEOUT_US, NULL); RUAResetEvent(avi_info->pRUA, &e); } } else { // send VC1 start codes if ((flags & RMAVI_FLAG_CHUNK_START) && (avi_info->isVC1)) { RMuint32 dumpedFrameSize = 0;// send entry point header for all frames not just iframes#define ADD_ENTRY_HDR 0 if (avi_info->getStartCodeBuffer) { if (avi_info->startCodeBuffer) { RMDBGLOG((VC1_STARTCODE_DBG, "releasing startCodeBuffer @0x%08lx, bytes left %lu\n", (RMuint32)avi_info->startCodeBuffer, avi_info->startCodeBufferLeft)); RUAReleaseBuffer(avi_info->pDMA, avi_info->startCodeBuffer); } while(RUAGetBuffer(avi_info->pDMA, &(avi_info->startCodeBuffer), COMMON_TIMEOUT_US) != RM_OK) { RMDBGLOG((ENABLE, "cant get buffer for VC1 startcode\n")); } avi_info->startCodeBufferSize = (1 << play_opt->dmapool_log2size); avi_info->startCodeBufferLeft = (1 << play_opt->dmapool_log2size); RMDBGLOG((VC1_STARTCODE_DBG, "got a new startCodeBuffer @0x%08lx, size %lu\n", (RMuint32)avi_info->startCodeBuffer, avi_info->startCodeBufferSize)); avi_info->getStartCodeBuffer = FALSE; } // check for start code presence in bitstream from ASF if ((chunk[0] == 0) && (chunk[1] == 0) && (chunk[2] == 1)) { if (chunk[3] == 0x0F) { // all start codes are already present in the bitstream // dont add any avi_info->addSeqHeader = FALSE; avi_info->addEntryHeader = FALSE; avi_info->addFrameHeader = FALSE; } else if (chunk[3] == 0x0E) { // dont add entryHeader nor frameHeader avi_info->addEntryHeader = FALSE; avi_info->addFrameHeader = FALSE; } else if (chunk[3] == 0x0D) { // dont add frameHeader avi_info->addFrameHeader = FALSE; } // no start code present, add them (default) } dumpedFrameSize += chunkLength; if (avi_info->addSeqHeader) dumpedFrameSize += avi_info->seqHeaderSize; if ((avi_info->addEntryHeader && avi_info->frameIsIFrame) || ADD_ENTRY_HDR) dumpedFrameSize += avi_info->entryHeaderSize; if (avi_info->addFrameHeader) dumpedFrameSize += 4;#ifndef WITH_MONO if (play_opt->savems) { RMstatus err; RMuint32 dummy; RMuint8 *buffer = (RMuint8*)&dummy; RMuint32ToLeBuf(dumpedFrameSize, buffer); RMDBGLOG((ENABLE, "frameSize %lu, dumpedFrameSize %lu (0x%lx)\n", chunkLength, dumpedFrameSize, dumpedFrameSize)); err = dump_data_into_file(play_opt, RMVDEMUX_VIDEO, buffer, sizeof(RMuint32), 0, FALSE, FALSE); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot dump pts data %d\n", err)); return; } }#endif // WITH_MONO // sequence header if (avi_info->addSeqHeader) { RMuint32 i; // copy the seqHeader RMDBGLOG((ENABLE, "adding seqHeader, size %lu, startCodeBufferLeft %lu\n", avi_info->seqHeaderSize, avi_info->startCodeBufferLeft)); for (i = 0; i < avi_info->seqHeaderSize; i++) *(avi_info->startCodeBuffer + i) = *(avi_info->seqHeader + i); // send the seqHeader if (play_opt->send_video) { while (RUASendData(avi_info->pRUA, decoder, avi_info->pDMA, avi_info->startCodeBuffer, avi_info->seqHeaderSize, &Info, sizeof(Info)) != RM_OK) { RMDBGLOG((ENABLE, "waiting for sendSeqHeader to complete\n")); } } // we only send the PTS with the first chunk Info.TimeStamp = 0; Info.ValidFields = 0; // eventually, dump it to a file { RMstatus err; err = dump_data_into_file(play_opt, RMVDEMUX_VIDEO, avi_info->startCodeBuffer, avi_info->seqHeaderSize, 0, FALSE, FALSE); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot dump data %d\n", err)); return; } } avi_info->startCodeBuffer += avi_info->seqHeaderSize; avi_info->startCodeBufferLeft -= avi_info->seqHeaderSize; avi_info->addSeqHeader = FALSE; } // entry header (for iframes) if ((avi_info->addEntryHeader && avi_info->frameIsIFrame) || ADD_ENTRY_HDR) { RMuint32 i; // copy the entryHeader RMDBGLOG((VC1_STARTCODE_DBG, "adding entryHeader (size %lu) to iframe %lu, startCodeBufferLeft %lu\n", avi_info->entryHeaderSize, avi_info->videoFrameCounter, avi_info->startCodeBufferLeft )); for (i = 0; i < avi_info->entryHeaderSize; i++) *(avi_info->startCodeBuffer + i) = *(avi_info->entryHeader + i); // send the entryHeader if (play_opt->send_video) { while (RUASendData(avi_info->pRUA, decoder, avi_info->pDMA, avi_info->startCodeBuffer, avi_info->entryHeaderSize, &Info, sizeof(Info)) != RM_OK) { RMDBGLOG((ENABLE, "waiting for sendEntryHeader to complete\n")); } } // we only send the PTS with the first chunk Info.TimeStamp = 0; Info.ValidFields = 0; // eventually, dump it to a file { RMstatus err; err = dump_data_into_file(play_opt, RMVDEMUX_VIDEO, avi_info->startCodeBuffer, avi_info->entryHeaderSize, 0, FALSE, FALSE); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot dump data %d\n", err)); return; } } avi_info->startCodeBuffer += avi_info->entryHeaderSize; avi_info->startCodeBufferLeft -= avi_info->entryHeaderSize; } // picture header (for all frames) if (avi_info->addFrameHeader) { // new picture, add picture header startcode "00 00 01 0D" RMDBGLOG((VC1_STARTCODE_DBG, "add newPic startcode to frame %lu, startCodeBufferLeft %lu\n", avi_info->videoFrameCounter, avi_info->startCodeBufferLeft )); *(avi_info->startCodeBuffer) = 0x00; *(avi_info->startCodeBuffer + 1) = 0x00; *(avi_info->startCodeBuffer + 2) = 0x01; *(avi_info->startCodeBuffer + 3) = 0x0D; // send the startcode if (play_opt->send_video) { while (RUASendData(avi_info->pRUA, decoder, avi_info->pDMA, avi_info->startCodeBuffer, 4, &Info, sizeof(Info)) != RM_OK) { struct RUAEvent e; //RMDBGLOG((ENABLE, "Cannot send %s data\n", (decoder == avi_info->dcc_info->video_decoder) ? "video":"audio")); check_prebuf_state(avi_info, 0); switch ((avi_info->label = local_process_key(avi_info, TRUE))) { case LABEL_ERROR: case LABEL_QUIT: case LABEL_STOP: case LABEL_STOP_SEEK_ZERO: avi_info->quitCallback = TRUE; return; case LABEL_NONE: break; } FSMstate = RM_PSM_GetState(avi_info->PSMcontext, &(avi_info->dcc_info)); /* dont send anything if iframe (because we have flushed the fifos already) */ if ((FSMstate == RM_PSM_IForward) || (FSMstate == RM_PSM_IRewind)) return; e.ModuleID = decoder; e.Mask = RUAEVENT_XFER_FIFO_READY; RUAWaitForMultipleEvents(avi_info->pRUA, &e, 1, SENDDATA_TIMEOUT_US, NULL); } /* sendind data may fill-up the xfer fifo, so we reset the event */ { struct RUAEvent e; e.ModuleID = decoder; e.Mask = RUAEVENT_XFER_FIFO_READY; RUAResetEvent(avi_info->pRUA, &e); } } // we only send the PTS with the first chunk Info.TimeStamp = 0; Info.ValidFields = 0; // eventually, dump it to a file { RMstatus err; err = dump_data_into_file(play_opt, RMVDEMUX_VIDEO, avi_info->startCodeBuffer, 4, 0, FALSE, FALSE); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot dump data %d\n", err)); return; } } avi_info->startCodeBuffer += 4; avi_info->startCodeBufferLeft -= 4; } if (avi_info->startCodeBufferLeft < (avi_info->seqHeaderSize + avi_info->entryHeaderSize + 4)) avi_info->getStartCodeBuffer = TRUE; } err = dump_data_into_file(play_opt, RMVDEMUX_VIDEO, chunk, chunkLength, 0, FALSE, FALSE); if (err != RM_OK) { RMDBGLOG((ENABLE, "Cannot dump video \n")); } if (flags & RMAVI_FLAG_CHUNK_START) { if (avi_info->frameIsIFrame) { RMDBGLOG((ENABLE, "frame %lu isIFrame (pts %llu valid %lu time %lu)\n", avi_info->videoFrameCounter, Info.TimeStamp, Info.ValidFields, Info.TimeStamp / avi_info->vopTimeIncrementResolution)); if ((FSMstate != RM_PSM_IForward) && (FSMstate != RM_PSM_IRewind)) avi_info->frameIsIFrame = FALSE; } } if (!play_opt->send_video) return; while (RUASendData(avi_info->pRUA, decoder, avi_info->pDMA, chunk, chunkLength, &Info, sizeof(Info)) != RM_OK) { struct RUAEvent e; //RMDBGLOG((ENABLE, "Cannot send %s data\n", (decoder == avi_info->dcc_info->video_decoder) ? "video":"audio")); check_prebuf_state(avi_info, 0); switch ((avi_info->label = local_process_key(avi_info, TRUE))) { case LABEL_ERROR: case LABEL_QUIT: case LABEL_STOP: case LABEL_STOP_SEEK_ZERO: avi_info->quitCallback = TRUE; return; case LABEL_NONE: break; } FSMstate = RM_PSM_GetState(avi_info->PSMcontext, &(avi_info->dcc_info)); /* dont send anything if iframe (because we have flushed the fifos already) */ if ((FSMstate == RM_PSM_IForward) || (FSMstate == RM_PSM_IRewind)) return; e.ModuleID = decoder; e.Mask = RUAEVENT_XFER_FIFO_READY; RUAWaitForMultipleEvents(avi_info->pRUA, &e, 1, SENDDATA_TIMEOUT_US, NULL); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -