?? play_mp4.c
字號:
e.ModuleID = pSendContext->dcc_info->video_decoder; e.Mask = RUAEVENT_XFER_FIFO_READY; RUAWaitForMultipleEvents(pSendContext->pRUA, &e, 1, COMMON_TIMEOUT_US, NULL); RMDBGLOG((ENABLE, "waiting to send video startcode\n")); } else { RMDBGLOG((ENABLE, "waiting to send video startcode\n")); return status; } } } status = dump_data_into_file(pSendContext->play_opt, RMVDEMUX_VIDEO, videoDMAStartCodeBuffer, 4, pSendContext->video_Info.TimeStamp, (pSendContext->video_Info.ValidFields & TIME_STAMP_INFO), pSendContext->video_Info.FirstAccessUnitPointer); if (RMFAILED(status)) { RMDBGLOG((ENABLE, "Cannot dump data %d\n", status)); return status; } pSendContext->h264sendStartCode = FALSE; // required for prebuffering routine pSendContext->videoDataSent += 4; pSendContext->startCodeDMABufferOffset += 4; if (pSendContext->startCodeDMABufferOffset + DMABUFFER_UNUSED_BLOCK_SIZE >= sizeBuffer) { RMDBGLOG((DBG, "release buffer 0x%lx startcode %lu\n", (RMuint32)pSendContext->startCodeDMABuffer, pSendContext->startCodeDMABufferOffset)); RUAReleaseBuffer(pSendContext->pDMA, pSendContext->startCodeDMABuffer); pSendContext->startCodeDMABuffer = NULL; pSendContext->startCodeDMABufferOffset = 0; } RMDBGLOG((H264_SC_DBG, "sent startcode\n")); if (pSendContext->SendVideoData) { RMDBGLOG((SENDDBG, "sent H264 video startcode : frameCount %lu totalBytes %lu pts %lld ( 0x%llx ) %s\n", pSendContext->videoFrameCount, pSendContext->videoDataSent, pSendContext->video_Info.TimeStamp, pSendContext->video_Info.TimeStamp, (pSendContext->video_Info.ValidFields & TIME_STAMP_INFO) ? "valid":"")); } // dont send pts with subsequent packets pSendContext->video_Info.ValidFields = 0; pSendContext->video_Info.TimeStamp = 0; } // read avcPkt size if (pSendContext->h264readPacketSize) { while (sample->size) { *(pSendContext->h264PktLenBuf) = *(sample->buf); pSendContext->h264PktLenBuf++; sample->size--; sample->buf++; pSendContext->h264LengthSize--; if (!pSendContext->h264LengthSize) break; } if (!pSendContext->h264LengthSize) { pSendContext->h264readPacketSize = FALSE; RMGetH264LengthSize(pSendContext->mp4tV, &(pSendContext->h264LengthSize)); pSendContext->h264PktLenBuf -= pSendContext->h264LengthSize; switch (pSendContext->h264LengthSize) { case 2: pSendContext->h264PktLen = RMbeBufToUint16(pSendContext->h264PktLenBuf); break; case 3: pSendContext->h264PktLen = RMbeBufToUint24(pSendContext->h264PktLenBuf); break; case 4: pSendContext->h264PktLen = RMbeBufToUint32(pSendContext->h264PktLenBuf); break; default: RMDBGLOG((ENABLE, "ERROR! unhandled h264LengthSize %lu\n", pSendContext->h264LengthSize)); return RM_ERROR; } RMDBGLOG((H264_SC_DBG, "read h264 packet size %lu (0x%lx)\n", pSendContext->h264PktLen, pSendContext->h264PktLen)); pSendContext->h264BytesLeft = pSendContext->h264PktLen; } if (!sample->size) { RMDBGLOG((ENABLE, "get new sample\n")); return RM_OK; } } // send the rest of the buffer sizeToSend = RMmin(pSendContext->h264BytesLeft, sample->size); if (pSendContext->SendVideoData) { status = RUASendData(pSendContext->pRUA, pSendContext->dcc_info->video_decoder, pSendContext->pDMA, sample->buf, sizeToSend, &pSendContext->video_Info, sizeof(pSendContext->video_Info)); if (status != RM_OK) { if (status == RM_PENDING) { RMDBGLOG((ENABLE, "video transfer pending\n")); pSendContext->videoTransferPending = TRUE; } return status; } pSendContext->videoTransferPending = FALSE; } status = dump_data_into_file(pSendContext->play_opt, RMVDEMUX_VIDEO, sample->buf, sizeToSend, pSendContext->video_Info.TimeStamp, (pSendContext->video_Info.ValidFields & TIME_STAMP_INFO), pSendContext->video_Info.FirstAccessUnitPointer); if (RMFAILED(status)) { RMDBGLOG((ENABLE, "Cannot dump data %d\n", status)); } pSendContext->h264BytesLeft -= sizeToSend; sample->size -= sizeToSend; sample->buf += sizeToSend; // required for prebuffering routine pSendContext->videoDataSent += sizeToSend; RMDBGLOG((H264_SC_DBG, "send payload (%5lu/%5lu), sampleSize %5lu, bytesLeft %5lu\n", sizeToSend, pSendContext->h264PktLen, sample->size, pSendContext->h264BytesLeft)); if (!pSendContext->h264BytesLeft) { pSendContext->h264sendStartCode = TRUE; pSendContext->h264readPacketSize = TRUE; } if (pSendContext->SendVideoData) { RMDBGLOG((SENDDBG, "sent a video packet (flags %lu) frameCount %lu size %ld / %lu (total %lu ) pts %lld ( 0x%llx ) %s\n", pSendContext->videosample.flags, pSendContext->videoFrameCount, sizeToSend, pSendContext->videoSampleSize, pSendContext->videoDataSent, pSendContext->video_Info.TimeStamp, pSendContext->video_Info.TimeStamp, (pSendContext->video_Info.ValidFields & TIME_STAMP_INFO) ? "valid":"")); } } return RM_OK; } // else, just send the packets coming from the MP4 parser if (pSendContext->SendVideoData) { status = RUASendData(pSendContext->pRUA, pSendContext->dcc_info->video_decoder, pSendContext->pDMA, pSendContext->videosample.buf, pSendContext->videosample.size, &pSendContext->video_Info, sizeof(pSendContext->video_Info)); if (status != RM_OK) { if (status == RM_PENDING) { RMDBGLOG((ENABLE, "video transfer pending\n")); pSendContext->videoTransferPending = TRUE; } return status; } pSendContext->videoTransferPending = FALSE; } status = dump_data_into_file(pSendContext->play_opt, RMVDEMUX_VIDEO, pSendContext->videosample.buf, pSendContext->videosample.size, pSendContext->video_Info.TimeStamp, (pSendContext->video_Info.ValidFields & TIME_STAMP_INFO), pSendContext->video_Info.FirstAccessUnitPointer); if (RMFAILED(status)) { RMDBGLOG((ENABLE, "Cannot dump data %d\n", status)); } { RMuint8 picType = 0xFF; // check MPEG4 picture type, 0=I;1=P;2=B;3=S if ((pSendContext->videosample.size > 5) && (!pSendContext->isH264)) { RMuint8 *dummy = pSendContext->videosample.buf; RMuint8 byte; if ((dummy[0] == 0) && (dummy[1] == 0) && (dummy[2] == 1) && (dummy[3] == 0xb6)) { byte = dummy[4]; byte &= 0xC0; byte >>= 6; picType = byte; } } if (pSendContext->SendVideoData) { RMDBGLOG((SENDDBG, "sent a packet video %s dma 0x%08X, sample 0x%08X, size %ld, total %lu, pts %lld(0x%llx) %s\n", (picType == 0) ? "(picType: I)": ((picType == 1) ? "(picType: P)": ((picType == 2) ? "(picType: B)":"")), pSendContext->pDMA, pSendContext->videosample.buf, pSendContext->videosample.size, pSendContext->videoDataSent, pSendContext->video_Info.TimeStamp, pSendContext->video_Info.TimeStamp, (pSendContext->video_Info.ValidFields & TIME_STAMP_INFO) ? "valid":"")); } } // required for prebuffering routine pSendContext->videoDataSent += pSendContext->videosample.size; return RM_OK;}static RMstatus send_MP4_video(struct SendMP4DataContext * pSendContext){ RMstatus status; RMuint64 pts; RMbool notEOS = TRUE; //enum RM_PSM_State PlaybackStatus = RM_PSM_GetState(pSendContext->PSMcontext, &(pSendContext->dcc_info)); if (pSendContext->videoTransferPending) goto send_data; pSendContext->videosample.buf = pSendContext->videoDMABuffer + pSendContext->videoDMABufferOffset; pSendContext->videosample.size = (1<<pSendContext->dmaBufferSizeLog2) - pSendContext->videoDMABufferOffset; if (pSendContext->play_opt->disk_ctrl_state == DISK_CONTROL_STATE_SLEEPING) RMDBGLOG((ENABLE, "trying to read from a suspended drive!!\n")); if (pSendContext->isIFrameMode && pSendContext->IFrameDirection > 0) { notEOS = RMGetNextMP4RandomAccessSample(pSendContext->mp4tV, &(pSendContext->videosample), pSendContext->videosample.size); } else if (pSendContext->isIFrameMode && pSendContext->IFrameDirection < 0) { notEOS = RMGetPrevMP4RandomAccessSample(pSendContext->mp4tV, &(pSendContext->videosample), pSendContext->videosample.size); } else notEOS = RMGetNextMP4Sample(pSendContext->mp4tV, &(pSendContext->videosample), pSendContext->videosample.size); if (!notEOS) { RMDBGLOG((ENABLE,"Failed to get Video sample -> end of video stream\n")); pSendContext->videoEOS = TRUE; return RM_EOS; } RMDBGLOG((DISABLE, "got video sample of size %ld\n", pSendContext->videosample.size)); pSendContext->videoSampleSize = pSendContext->videosample.size; pSendContext->video_Info.TimeStamp = 0; pSendContext->video_Info.ValidFields = 0; if (pSendContext->videosample.flags & MP4_AU_START) { pSendContext->videoFrameCount++; } //RMDBGLOG((ENABLE, "[%lu] sample size %lu flags %lu\n", pSendContext->videoFrameCount, pSendContext->videoSampleSize, pSendContext->videosample.flags)); if (pSendContext->videosample.flags & MP4_CTS_VALID) { pSendContext->video_Info.ValidFields = TIME_STAMP_INFO; pts = RMuint64from2RMuint32(pSendContext->videosample.CTS_MSB, pSendContext->videosample.CTS_LSB); pSendContext->video_Info.TimeStamp = pts; if (pSendContext->video_vop_tir != pSendContext->VideoCTSTimeScale) { pSendContext->video_Info.TimeStamp = round_int_div(pts * pSendContext->video_vop_tir, pSendContext->VideoCTSTimeScale); RMDBGLOG((DISABLE, "video pts scaling! old %lld => %lld thru a factor %ld/%ld\n", pts, pSendContext->video_Info.TimeStamp, pSendContext->video_vop_tir, pSendContext->VideoCTSTimeScale)); } else RMDBGLOG((DISABLE, "setting pts to %llu\n", pts)); if (pSendContext->videosample.DTS_MSB != pSendContext->videosample.CTS_MSB) { RMuint64 dts; RMuint64 cts; /* this is a hack for some h264 mov files which contain "invalid" pts bug #5606 */ dts = (RMuint64)pSendContext->videosample.DTS_MSB; dts <<= 32; dts |= pSendContext->videosample.DTS_LSB; cts = (RMuint64)pSendContext->videosample.CTS_MSB; cts <<= 32; cts |= pSendContext->videosample.CTS_LSB; RMDBGLOG((DISABLE, "dont send invalid pts. DTSh %08lx DTSl %08lx = %09llx CTSh %08lx CTSl %08lx = %09llx lastPTS %llx scale %lu\n", pSendContext->videosample.DTS_MSB, pSendContext->videosample.DTS_LSB, dts, pSendContext->videosample.CTS_MSB, pSendContext->videosample.CTS_LSB, cts, pSendContext->lastVideoPTS, pSendContext->video_vop_tir)); pSendContext->video_Info.TimeStamp = 0; pSendContext->video_Info.ValidFields = 0; } if (pSendContext->video_Info.TimeStamp) pSendContext->lastVideoPTS = (1000 * pSendContext->video_Info.TimeStamp) / pSendContext->video_vop_tir; } if (!pSendContext->SendVideoPts) { pSendContext->video_Info.TimeStamp = 0; pSendContext->video_Info.ValidFields = 0; } RMDBGLOG((DISABLE, "[%lu] sample size %lu flags %lu pts 0x%llx valid %lu\n", pSendContext->videoFrameCount, pSendContext->videoSampleSize, pSendContext->videosample.flags, pSendContext->video_Info.TimeStamp, pSendContext->video_Info.ValidFields)); // happens only once if (!pSendContext->video_ptsScalingMsg) { if (pSendContext->video_vop_tir != pSendContext->VideoCTSTimeScale) { RMDBGLOG((ENABLE, ">>>video pts scaling! thru a factor %ld/%ld\n", pSendContext->video_vop_tir, pSendContext->VideoCTSTimeScale)); } else RMDBGLOG((ENABLE, ">>> no video pts scaling required\n")); pSendContext->video_ptsScalingMsg = TRUE; } if (pSendContext->FirstSystemTimeStamp) { if (pSendContext->video_Info.ValidFields & TIME_STAMP_INFO) { RMuint64 dummyPTS = pSendContext->video_Info.TimeStamp; RMDBGLOG((ENABLE, "FirstSystemTimeStamp from video = %lld (0x%llX) at %ld/sec = %llu s\n", dummyPTS, dummyPTS, pSendContext->video_vop_tir, dummyPTS / pSendContext->video_vop_tir)); pSendContext->FirstSystemTimeStamp = FALSE; RMDBGLOG((ENABLE, "setting timers\n")); DCCSTCSetTime(pSendContext->dcc_info->pStcSource, dummyPTS, pSendContext->video_vop_tir);#if PLAY_TIMERS if ((PlaybackStatus != RM_PSM_Prebuffering) && (PlaybackStatus != RM_PSM_Paused) && (PlaybackStatus != RM_PSM_Stopped)) DCCSTCPlay(pSendContext->dcc_info->pStcSource);#endif } else { if (pSendContext->forceTimersToZero) { RMDBGLOG((ENABLE, ">>> no pts, force timers to zero\n")); DCCSTCSetTime(pSendContext->dcc_info->pStcSource, 0, pSendContext->video_vop_tir);#if PLAY_TIMERS if ((PlaybackStatus != RM_PSM_Prebuffering) && (PlaybackStatus != RM_PSM_Paused) && (PlaybackStatus != RM_PSM_Stopped)) DCCSTCPlay(pSendContext->dcc_info->pStcSource);#endif pSendContext->FirstSystemTimeStamp = FALSE; } else { RMDBGLOG((ENABLE, "waiting for first time stamp to be detected, timer not set!!!, video skipped\n")); return RM_OK; } } } RMDBGLOG((DISABLE, "about to send a packet video dma 0x%08X, sample 0x%08X, size %ld, pts %lld(0x%llx) %s\n", pSendContext->pDMA, pSendContext->videosample.buf, pSendContext->videosample.size, pSendContext->video_Info.TimeStamp, pSendContext->video_Info.TimeStamp, (pSendContext->video_Info.ValidFields & TIME_STAMP_INFO) ? "valid":"")); pSendContext->videoDMABufferOffset += pSendContext->videosample.size; send_data: if (pSendContext->videosample.size != 0) { status = send_video_payload(pSendContext); if (status != RM_OK) return status; } else { RMDBGLOG((ENABLE, "got video sample of size 0!\n")); } return RM_OK;}#define SPU_SAMPLES_QUEUE_SIZE 10 #ifdef WITH_MONOstatic void flush_spu_fifo(struct SendMP4DataContext * pSendContext){ struct spu_fifo_entry_type *buf_info = NULL; RMuint32 rd1, rd2; RMuint32 size1; RMDBGLOG((SPU_DBG, "flush_spu_fifo\n"));#ifndef
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -