📄 play_mp4.c
字号:
case Profile_MPEG4_HD_Padding: case Profile_MPEG4_SD_DeInt_Padding: case Profile_MPEG4_HD_DeInt_Padding: RMDBGLOG((ENABLE, "MPEG4 video\n")); ParseMP4VideoDSI(pSendContext->videodsiBuf, pSendContext->videodsiSize, (void *) &pSendContext->video_vop_tir, sizeof(RMuint32)); break; case Profile_VC1_SD: case Profile_VC1_HD: RMDBGLOG((ENABLE, "VC1 video\n")); pSendContext->video_vop_tir = pSendContext->VideoCTSTimeScale; break; case Profile_H264_SD: case Profile_H264_HD: case Profile_H264_SD_DeInt: case Profile_H264_HD_DeInt: RMDBGLOG((ENABLE, "H264 video\n")); pSendContext->video_vop_tir = pSendContext->VideoCTSTimeScale; break; } RMDBGLOG((ENABLE,"********** video VOP TIR %lu, VideoCTSTimeScale %lu\n", pSendContext->video_vop_tir, pSendContext->VideoCTSTimeScale)); if (!pSendContext->video_vop_tir) { RMDBGLOG((ENABLE, "video_vop_tir = 0!!, reset to VideoCTSTimeScale\n")); pSendContext->video_vop_tir = pSendContext->VideoCTSTimeScale; } } else goto disable_video; } else { disable_video: RMDBGLOG((ENABLE, ">> no video\n")); pSendContext->SendVideoData = FALSE; pSendContext->isAudioOnly = TRUE; pSendContext->currentVideoTrack = 0; if (pSendContext->mp4tV) { RMDBGLOG((ENABLE, "closing video track\n")); RMCloseMP4Track(pSendContext->mp4c, pSendContext->mp4tV); pSendContext->mp4tV = (ExternalRMmp4Track) NULL; } } // continue with other tracks#if 0 if (!pSendContext->play_opt->send_audio) goto init_spu_track;#endif RMDBGLOG((ENABLE, "init mp4 audio track(s)\n")); pSendContext->mp4tA = (ExternalRMmp4Track) NULL; 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -