📄 play_mp4.c
字号:
pSendContext->audioTracks = RMGetMP4NumberOfAudioTracks(pSendContext->mp4c); RMDBGLOG((ENABLE, "found %lu audio tracks\n", pSendContext->audioTracks)); if (pSendContext->audioTracks > 0) { RMuint32 i; pSendContext->currentAudioTrack = 0; if (pSendContext->priv_opt.audio_track) { RMDBGLOG((ENABLE, "open audio track %lu from cmdline\n", pSendContext->priv_opt.audio_track)); status = mp4_select_audio_track(pSendContext, pSendContext->priv_opt.audio_track); if (status == RM_OK) { pSendContext->currentAudioTrack = pSendContext->priv_opt.audio_track; goto init_spu_track; } else { RMDBGLOG((ENABLE, "cant select audio track %lu\n", pSendContext->priv_opt.audio_track)); goto disable_audio; } } for (i = 1; i <= pSendContext->audioTracks; i++) { // init the first working audio track status = mp4_select_audio_track(pSendContext, i); if (status != RM_OK) RMDBGLOG((ENABLE, "cant select audio track %lu, skipping!\n", i)); else { pSendContext->currentAudioTrack = i; break; } } if (pSendContext->currentAudioTrack != i) { disable_audio: // all audio tracks failed init, disable audio RMDBGLOG((ENABLE, "all audio tracks failed init, disabling audio\n")); pSendContext->SendAudioData = FALSE; pSendContext->isAudioOnly = FALSE; pSendContext->currentAudioTrack = 0; if (pSendContext->mp4tA) { RMDBGLOG((ENABLE, "closing audio track\n")); RMCloseMP4Track(pSendContext->mp4c, pSendContext->mp4tA); pSendContext->mp4tA = (ExternalRMmp4Track) NULL; } } } else { RMDBGLOG((ENABLE, ">> no audio\n")); pSendContext->SendAudioData = FALSE; pSendContext->isAudioOnly = FALSE; pSendContext->currentAudioTrack = 0; } init_spu_track: pSendContext->mp4tSPU = (ExternalRMmp4Track) NULL; pSendContext->currentSPUTrack = 0; pSendContext->spuTracks = RMGetMP4NumberOfSPUTracks(pSendContext->mp4c); RMDBGLOG((ENABLE, "found %lu spu tracks\n", pSendContext->spuTracks));#ifdef WITHOUT_NERO_SPU pSendContext->spuTracks = 0;#endif // WITHOUT_NERO_SPU if ((pSendContext->priv_opt.spuEnabled) && (pSendContext->spuTracks)) { RMuint32 i; pSendContext->enableSPU = TRUE; pSendContext->displaySPU = TRUE; for (i = 1; i <= pSendContext->spuTracks; i++) { // init the first working spu track status = mp4_select_spu_track(pSendContext, i); if (status != RM_OK) RMDBGLOG((ENABLE, "cant select spu track %lu, skipping!\n", i)); else { pSendContext->currentSPUTrack = i; break; } } if (pSendContext->currentSPUTrack != i) { // all spu tracks failed init, disable spu RMDBGLOG((ENABLE, "all spu tracks failed init, disabling spu\n")); pSendContext->SendSPUData = FALSE; pSendContext->spuTracks = 0; pSendContext->enableSPU = FALSE; if (pSendContext->mp4tSPU) { RMDBGLOG((ENABLE, "closing spu track\n")); RMCloseMP4Track(pSendContext->mp4c, pSendContext->mp4tSPU); pSendContext->mp4tSPU = (ExternalRMmp4Track) NULL; } } } /* init Subtitle track */ pSendContext->mp4tSubT = (ExternalRMmp4Track) NULL; pSendContext->currentSubtitleTrack = 0; pSendContext->subtitleTracks = RMGetMP4NumberOfSubtitleTracks(pSendContext->mp4c); RMDBGLOG((ENABLE, "found %lu subtitle tracks\n", pSendContext->subtitleTracks)); // disable subtitles to match Nero's behaviour (Nero Digital for Windows doesnt show subtitles, only SPU) pSendContext->subtitleTracks = 0; if ((pSendContext->priv_opt.subtitlesEnabled) && (pSendContext->subtitleTracks)) { RMuint32 i; pSendContext->enableSubtitles = TRUE; if (!pSendContext->displaySPU) pSendContext->displaySubtitles = TRUE; for (i = 1; i <= pSendContext->subtitleTracks; i++) { // init the first working subtitle track status = mp4_select_subtitle_track(pSendContext, i); if (status != RM_OK) RMDBGLOG((ENABLE, "cant select subtitle track %lu, skipping!\n", i)); else { pSendContext->currentSubtitleTrack = i; break; } } if (pSendContext->currentSubtitleTrack != i) { // all subtitle tracks failed init, disable subtitles RMDBGLOG((ENABLE, "all subtitle tracks failed init, disabling subtitles\n")); pSendContext->subtitleTracks = 0; pSendContext->enableSubtitles = FALSE; if (pSendContext->mp4tSubT) { RMDBGLOG((ENABLE, "closing subtitle track\n")); RMCloseMP4Track(pSendContext->mp4c, pSendContext->mp4tSubT); pSendContext->mp4tSubT = (ExternalRMmp4Track) NULL; } } } /* exit */ if ((pSendContext->audioTracks == 0) && (pSendContext->videoTracks == 0)) return RM_ERROR; RMDBGLOG((ENABLE, "initTracks done, video %lu(of %lu), audio %lu(of %lu), spu %lu(of %lu), subtitle %lu(of %lu)\n", pSendContext->currentVideoTrack, pSendContext->videoTracks, pSendContext->currentAudioTrack, pSendContext->audioTracks, pSendContext->currentSPUTrack, pSendContext->spuTracks, pSendContext->currentSubtitleTrack, pSendContext->subtitleTracks)); return RM_OK;}/* for audio and spu (spu has a dsisize=64 always, is the palette) */#define MAX_DSI_SIZE 64 static RMstatus mp4_select_audio_track(struct SendMP4DataContext *pSendContext, RMuint32 index){ RMuint32 audiotrackID = 0; RMstatus status; ExternalRMmp4Track newTrack; if (index > pSendContext->audioTracks) return RM_ERROR; if (index == pSendContext->currentAudioTrack) return RM_OK; status = RMGetMP4AudioTrackIDByIndex(pSendContext->mp4c, index, &audiotrackID); if (status != RM_OK) { RMDBGLOG((ENABLE, "cant get id for audio track %lu!\n", index)); return status; } if (audiotrackID > 0) { RMuint8 *dsibuf; RMuint32 dsisize; RMuint8 tempdsi[MAX_DSI_SIZE]; RMuint32 samplerate, channels; RMuint8 objID; RMmpeg4TrackType type; RMDBGLOG((ENABLE, "selecting audio track %lu, id %lu\n", index, audiotrackID)); newTrack = RMOpenMP4Track(pSendContext->mp4c, audiotrackID); if (!newTrack) { RMDBGLOG((ENABLE, "couldnt open track!\n")); return RM_ERROR; } RMGetMP4TrackType(newTrack, &type); if (type == RM_AUDIO_AAC_TRACK) { RMDBGLOG((ENABLE, ">> AAC audio\n")); dsibuf = RMGetMP4TrackDSI(newTrack, &dsisize); RMDBGLOG((ENABLE, "got %lu bytes of audio DSI, parsing...\n", dsisize)); if (dsibuf == NULL) { RMDBGLOG((ENABLE, "audio DSI not present!\n"));#ifdef WITH_MONO return RM_ERROR;#else return RM_OK;#endif } else if (dsisize > MAX_DSI_SIZE) { RMDBGLOG((ENABLE, "audio DSI too big!\n")); return RM_ERROR; } else if (dsisize == 0) { RMDBGLOG((ENABLE, "audio DSI has size zero!!\n")); return RM_ERROR; } /* copy the DSI in case we overwite it during parsing */ memcpy(tempdsi, dsibuf, dsisize); ParseMP4AudioDSI(tempdsi, &dsisize, &samplerate, &channels, &objID); pSendContext->audioSampleRate = samplerate; pSendContext->AAC_SampleRateFromDSI = samplerate; pSendContext->AAC_ChannelsFromDSI = channels; pSendContext->AAC_ObjectIDFromDSI = objID; pSendContext->isAACaudioPayload = TRUE; } else if (type == RM_AUDIO_AC3_TRACK) { RMDBGLOG((ENABLE, ">> AC3 audio\n")); pSendContext->isAACaudioPayload = FALSE; RMGetMP4TrackSampleRate(newTrack, &(pSendContext->audioSampleRate)); RMDBGLOG((ENABLE, "sample rate %lu\n", pSendContext->audioSampleRate)); } else { fprintf(stderr, "unknown audio!\n"); if (newTrack) { RMDBGLOG((ENABLE, "closing audio track\n")); RMCloseMP4Track(pSendContext->mp4c, newTrack); } return RM_ERROR; } if (pSendContext->mp4tA) { RMDBGLOG((ENABLE, "audio track already open, closing\n")); RMCloseMP4Track(pSendContext->mp4c, pSendContext->mp4tA); } pSendContext->mp4tA = newTrack; pSendContext->audio_vop_tir = AUDIO_BASE; pSendContext->AudioCTSTimeScale = RMGetMP4TrackTimeScale(pSendContext->mp4tA); RMDBGLOG((ENABLE, "********** audio VOP TIR %ld, AudioCTSTimeScale %ld\n", pSendContext->audio_vop_tir, pSendContext->AudioCTSTimeScale)); } else return RM_ERROR; #ifdef WITH_MONO { RMuint32 i; RMDBGLOG((ENABLE, "setup audio parameters for this track\n")); for (i = 0; i < pSendContext->audioInstances; i++) { RMmpeg4TrackType type; RMGetMP4TrackType(pSendContext->mp4tA, &type); if (type == RM_AUDIO_AAC_TRACK) { RMDBGLOG((ENABLE, ">> set audio codec[%lu] to AAC\n", i)); pSendContext->audio_opt[i].Codec = AudioDecoder_Codec_AAC; pSendContext->audio_opt[i].AACParams.InputFormat = 1; pSendContext->audio_opt[i].AACParams.OutputChannels = Aac_LR; } else if (type == RM_AUDIO_AC3_TRACK) { RMDBGLOG((ENABLE, ">> set audio codec[%lu] to AC3\n", i)); pSendContext->audio_opt[i].Codec = AudioDecoder_Codec_AC3; } if (!pSendContext->audio_opt[i].OutputChannelsExplicitAssign) pSendContext->audio_opt[i].OutputChannels = Audio_Out_Ch_LR; } }#endif return RM_OK;}static RMstatus mp4_select_spu_track(struct SendMP4DataContext *pSendContext, RMuint32 index){ RMuint32 sputrackID = 0; RMstatus status; ExternalRMmp4Track newTrack; if (index > pSendContext->spuTracks) return RM_ERROR; if (index == pSendContext->currentSPUTrack) return RM_OK; status = RMGetMP4SPUTrackIDByIndex(pSendContext->mp4c, index, &sputrackID); if (status != RM_OK) { RMDBGLOG((ENABLE, "cant get id for spu track %lu!\n", index)); return status; } if (sputrackID > 0) { RMuint8 *dsibuf; RMuint32 dsisize; RMDBGLOG((ENABLE, "selecting spu track %lu, id %lu\n", index, sputrackID)); newTrack = RMOpenMP4Track(pSendContext->mp4c, sputrackID); if (!newTrack) { RMDBGLOG((ENABLE, "couldnt open track!\n")); return RM_ERROR; } dsibuf = RMGetMP4TrackDSI(newTrack, &dsisize); RMDBGLOG((ENABLE, "got %lu bytes of spu DSI\n", dsisize)); if (dsibuf == NULL) { RMDBGLOG((ENABLE, "spu DSI not present!\n")); return RM_ERROR; } else if (dsisize > MAX_DSI_SIZE) { RMDBGLOG((ENABLE, "spu DSI too big!\n")); return RM_ERROR; } else if (dsisize == 0) { RMDBGLOG((ENABLE, "spu DSI has size zero!!\n")); return RM_ERROR; } if (pSendContext->mp4tSPU) { RMDBGLOG((ENABLE, "spu track already open, closing\n")); RMCloseMP4Track(pSendContext->mp4c, pSendContext->mp4tSPU); } pSendContext->mp4tSPU = newTrack; RMGetMP4TrackWidth(pSendContext->mp4tSPU, &(pSendContext->spuWidth)); RMGetMP4TrackHeight(pSendContext->mp4tSPU, &(pSendContext->spuHeight)); // we must do this in order to find the right value (but it is not in nero specification) pSendContext->spuWidth >>= 16; pSendContext->spuHeight >>= 16; RMDBGLOG((ENABLE, "spu is %lu x %lu\n", pSendContext->spuWidth, pSendContext->spuHeight)); pSendContext->spuDSIBuf = dsibuf; pSendContext->spuDSISize = dsisize; pSendContext->spuCTSTimeScale = RMGetMP4TrackTimeScale(pSendContext->mp4tSPU); RMDBGLOG((ENABLE, "spu timeScale %lu\n", pSendContext->spuCTSTimeScale)); } else return RM_ERROR; return RM_OK;}static RMstatus mp4_select_subtitle_track(struct SendMP4DataContext *pSendContext, RMuint32 index){ RMuint32 subtitletrackID = 0; RMstatus status; if (index > pSendContext->subtitleTracks) return RM_ERROR; if (index == pSendContext->currentSubtitleTrack) return RM_OK; status = RMGetMP4SubtitleTrackIDByIndex(pSendContext->mp4c, index, &subtitletrackID); if (status != RM_OK) { RMDBGLOG((ENABLE, "cant get id for subtitle track %lu!\n", index)); return status; } if (pSendContext->mp4tSubT) { RMDBGLOG((ENABLE, "subtitle track already open, closing\n")); RMCloseMP4Track(pSendContext->mp4c, pSendContext->mp4tSubT); pSendContext->mp4tSubT = (ExternalRMmp4Track) NULL; } if (subtitletrackID > 0) { RMDBGLOG((ENABLE, "selecting subtitle track %lu, id %lu\n", index, subtitletrackID)); pSendContext->mp4tSubT = RMOpenMP4Track(pSendContext->mp4c, subtitletrackID); if (pSendContext->mp4tSubT == NULL) { RMDBGLOG((ENABLE, "couldnt open subtitle track!!\n")); return RM_ERROR; } pSendContext->subtCTSTimeScale = RMGetMP4TrackTimeScale(pSendContext->mp4tSubT); RMDBGLOG((ENABLE, "subtitle timeScale %lu\n", pSendContext->subtCTSTimeScale)); } else return RM_ERROR; return RM_OK;}static RMstatus send_videoDSI(struct SendMP4DataContext * pSendContext){ RMuint32 i; RMstatus status; if (!pSendContext->sendVideoDSI) { return RM_OK; } while (RUAGetBuffer(pSendContext->pDMA, &(pSendContext->videosample.buf), COMMON_TIMEOUT_US) != RM_OK) RMDBGLOG((ENABLE, "there are no free buffers for video DSI right now, retry later...\n")); memcpy(pSendContext->videosample.buf, pSendContext->videodsiBuf, pSendContext->videodsiSize); pSendContext->videosample.size = pSendContext->videodsiSize; pSendContext->videosample.flags = 0; pSendContext->video_Info.ValidFields = 0; pSendContext->video_Info.TimeStamp = 0; for (i = 0; i < pSendContext->videodsiSize; i++) { RMDBGLOG((DISABLE, "videoDSI[%lu]=%02X\n", i, pSendContext->videodsiBuf[i])); } if (pSendContext->SendVideoData) { while( RUASendData(pSendContext->pRUA, pSendContext->dcc_info->video_decoder, pSendContext->pDMA, pSendContext->videosample.buf, pSendContext->videosample.size, &pSendContext->video_Info, sizeof(pSendContext->video_Info)) != RM_OK) { RMDBGLOG((ENABLE, "waiting to send video DSI\n")); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -