int mp4_initSamrTrack(const MP4_CONTAINER_T *pMp4, MP4_TRAK_SAMR_T *pMp4BoxSet) { if(!pMp4 || !pMp4BoxSet) { return -1; } if(!pMp4->pStream || !pMp4->pStream->cbCheckFd(pMp4->pStream)) { return -1; } memset(pMp4BoxSet, 0, sizeof(MP4_TRAK_SAMR_T)); if(pMp4->pStream->cbSeek(pMp4->pStream, 0, SEEK_SET) != 0) { return -1; } if((pMp4BoxSet->pSamr = (BOX_SAMR_T *) mp4_loadTrack(pMp4->proot, &pMp4BoxSet->tk, *((uint32_t *) "samr"), 1)) == NULL) { LOG(X_ERROR("No valid samr track found in %s"), pMp4->pStream->cbGetName(pMp4->pStream)); return -1; } if((pMp4BoxSet->pDamr = (BOX_DAMR_T *) mp4_findBoxChild( (BOX_T *)pMp4BoxSet->pSamr, *((uint32_t *) "damr"))) == NULL) { LOG(X_ERROR("No valid damr track found in %s"), pMp4->pStream->cbGetName(pMp4->pStream)); return -1; } return 0; }
int mp4_initMp4vTrack(const MP4_CONTAINER_T *pMp4, MP4_TRAK_MP4V_T *pMp4BoxSet) { if(!pMp4 || !pMp4BoxSet) { return -1; } if(!pMp4->pStream || !pMp4->pStream->cbCheckFd(pMp4->pStream)) { return -1; } memset(pMp4BoxSet, 0, sizeof(MP4_TRAK_MP4V_T)); if(pMp4->pStream->cbSeek(pMp4->pStream, 0, SEEK_SET) != 0) { return -1; } if((pMp4BoxSet->pMp4v = (BOX_MP4V_T *) mp4_loadTrack(pMp4->proot, &pMp4BoxSet->tk, *((uint32_t *) "mp4v"), 1)) == NULL) { LOG(X_ERROR("No valid mp4v track found in %s"), pMp4->pStream->cbGetName(pMp4->pStream)); return -1; } if((pMp4BoxSet->pEsds = (BOX_ESDS_T *) mp4_findBoxChild( (BOX_T *)pMp4BoxSet->pMp4v, *((uint32_t *) "esds"))) == NULL) { LOG(X_ERROR("No valid esds track found in %s"), pMp4->pStream->cbGetName(pMp4->pStream)); return -1; } return 0; }
int mp4_initAvcCTrack(const MP4_CONTAINER_T *pMp4, MP4_TRAK_AVCC_T *pMp4BoxSet) { if(!pMp4 || !pMp4BoxSet) { return -1; } if(!pMp4->pStream || !pMp4->pStream->cbCheckFd(pMp4->pStream)) { return -1; } memset(pMp4BoxSet, 0, sizeof(MP4_TRAK_AVCC_T)); if(pMp4->pStream->cbSeek(pMp4->pStream, 0, SEEK_SET) != 0) { return -1; } // // Perform initialization of the pMp4BoxSet->tk structure // if((pMp4BoxSet->pAvc1 = (BOX_AVC1_T *) mp4_loadTrack(pMp4->proot, &pMp4BoxSet->tk, *((uint32_t *) "avc1"), 1)) == NULL) { LOG(X_ERROR("No valid avc1 track found in %s"), pMp4->pStream->cbGetName(pMp4->pStream)); return -1; } if((pMp4BoxSet->pAvcC = (BOX_AVCC_T *) mp4_findBoxChild( (BOX_T *)pMp4BoxSet->pAvc1, *((uint32_t *) "avcC"))) == NULL) { LOG(X_ERROR("No valid avcC track found in %s"), pMp4->pStream->cbGetName(pMp4->pStream)); return -1; } if(pMp4BoxSet->pAvcC->avcc.numsps < 1) { LOG(X_ERROR("No SPS found in avcC")); return -1; } if(pMp4BoxSet->pAvcC->avcc.numpps < 1) { LOG(X_ERROR("No PPS found in avcC")); return -1; } return 0; }
int mp4_initMp4aTrack(const MP4_CONTAINER_T *pMp4, MP4_TRAK_MP4A_T *pMp4BoxSet) { BOX_T *pBox; if(!pMp4 || !pMp4BoxSet) { return -1; } if(!pMp4->pStream || !pMp4->pStream->cbCheckFd(pMp4->pStream)) { return -1; } memset(pMp4BoxSet, 0, sizeof(MP4_TRAK_MP4A_T)); if(pMp4->pStream->cbSeek(pMp4->pStream, 0, SEEK_SET) != 0) { return -1; } if((pMp4BoxSet->pMp4a = (BOX_MP4A_T *) mp4_loadTrack(pMp4->proot, &pMp4BoxSet->tk, *((uint32_t *) "mp4a"), 1)) == NULL) { LOG(X_ERROR("No valid mp4a track found in %s"), pMp4->pStream->cbGetName(pMp4->pStream)); return -1; } if(!(pMp4BoxSet->pEsds = (BOX_ESDS_T *) mp4_findBoxChild( (BOX_T *)pMp4BoxSet->pMp4a, *((uint32_t *) "esds")))) { // // iPhone 4 recordings can include mp4a -> chan/wave -> frma/mp4a/esds // if((pBox = mp4_findBoxChild( (BOX_T *)pMp4BoxSet->pMp4a, *((uint32_t *) "wave")))) { pMp4BoxSet->pEsds = (BOX_ESDS_T *) mp4_findBoxChild(pBox, *((uint32_t *) "esds")); } } if(!pMp4BoxSet->pEsds) { LOG(X_ERROR("No valid esds (audio) track found in %s"), pMp4->pStream->cbGetName(pMp4->pStream)); return -1; } return 0; }
int cap_http_load_next_mp4(void *pArg) { int rc = 0; MP4_EXTRACT_STATE_INT_T *pExtractSt = (MP4_EXTRACT_STATE_INT_T *) pArg; MP4_CONTAINER_T *pMp4 = NULL; CAP_ASYNC_DESCR_T *pCapCfg = NULL; MP4_EXTRACT_STATE_T *pExtSt = NULL; PLAYLIST_MPD_ENTRY_T *pEntry = NULL; CAP_HTTP_MP4_STREAM_T *pCapHttpMp4Stream = NULL; CAP_HTTP_MP4_NEXT_T *pNext = NULL; unsigned int idx, idxUsed; int trackId; MP4_TRAK_T trak; //const char *path = NULL; MP4_LOADER_NEXT_T nextLoader; //fprintf(stderr, "CAP_HTTP_LOAD_NEXT_MP4\n"); if(!pExtractSt || !(pExtSt = pExtractSt->pExtSt) || !pExtSt->pStream || !(pCapCfg = (CAP_ASYNC_DESCR_T *) pExtractSt->pExtSt->nextLoader.pCbData) || !(pCapHttpMp4Stream = (CAP_HTTP_MP4_STREAM_T *) pCapCfg->pUserData)) { return -1; } // // Ensure that this (capture) playlist has not reached the end // if(pCapHttpMp4Stream->pl.endOfList) { return -1; } if((trackId = mp4_get_track_id(pExtSt)) <= 0) { LOG(X_ERROR("Unable to determine track id from request")); return -1; } for(idx = 0; idx < sizeof(pCapHttpMp4Stream->next) / sizeof(pCapHttpMp4Stream->next[0]); idx++) { if(pCapHttpMp4Stream->next[idx].trackId == 0) { pCapHttpMp4Stream->next[idx].trackId = trackId; } if(trackId == pCapHttpMp4Stream->next[idx].trackId) { pNext = &pCapHttpMp4Stream->next[idx]; break; } } if(!pNext) { return -1; } pNext->count++; if(pNext->count > pCapHttpMp4Stream->highestCount) { pCapHttpMp4Stream->highestCount = pNext->count; // // Wait until there is an output file to be processed // if(!(pEntry = cap_http_wait_for_next_mp4(pCapCfg))) { return -1; } if(!(pMp4 = cap_http_mp4_open(pEntry->path, pCapCfg) )) { mpdpl_free_entry(&pCapHttpMp4Stream->pl, pEntry); return -1; } idxUsed = 0; if(pCapHttpMp4Stream->plUsed[0].plEntryUsed) { idxUsed = 1; if(pCapHttpMp4Stream->plUsed[0].active > 0) { pCapHttpMp4Stream->plUsed[0].active--; } if(pCapHttpMp4Stream->plUsed[1].plEntryUsed) { if(pCapHttpMp4Stream->plUsed[0].active > 0) { mpdpl_free_entry(&pCapHttpMp4Stream->pl, pEntry); return -1; } mpdpl_free_entry(&pCapHttpMp4Stream->pl, pCapHttpMp4Stream->plUsed[0].plEntryUsed); memcpy(&pCapHttpMp4Stream->plUsed[0], &pCapHttpMp4Stream->plUsed[1], sizeof(pCapHttpMp4Stream->plUsed[0])); pCapHttpMp4Stream->plUsed[0].active--; pCapHttpMp4Stream->plUsed[1].plEntryUsed = NULL; } } pEntry->pUserData = pMp4; pCapHttpMp4Stream->plUsed[idxUsed].plEntryUsed = pEntry; pCapHttpMp4Stream->plUsed[idxUsed].count = pNext->count; pCapHttpMp4Stream->plUsed[idxUsed].active = 1; } else { for(idxUsed = 0; idxUsed < sizeof(pCapHttpMp4Stream->plUsed) / sizeof(pCapHttpMp4Stream->plUsed[0]); idxUsed++) { if(pNext->count == pCapHttpMp4Stream->plUsed[idxUsed].count) { pEntry = pCapHttpMp4Stream->plUsed[idxUsed].plEntryUsed; pCapHttpMp4Stream->plUsed[idxUsed].active++; if(idxUsed == 1) { pCapHttpMp4Stream->plUsed[0].active--; } break; } } if(pEntry) { pMp4 = (MP4_CONTAINER_T *) pEntry->pUserData; } } if(!pMp4) { return -1; } if(!pMp4->haveMoov) { // // If the file is an mp4 fragment w/o the initializer MOOF parts // then preserve the trak components and only re-init the moof components // Note that the trak components will point to the original mp4 container context // which needs to be preserved // memcpy(&trak, &pExtSt->trak, sizeof(MP4_TRAK_T)); } //fprintf(stderr, "BEGIN CALLING LOADTRAK %c%c%c%c from load_next_mp4 for '%s'\n", MP4_BOX_NAME_INT2C(pExtSt->trak.stsdType), pMp4->pStream->cbGetName(pMp4->pStream)); if(!(mp4_loadTrack(pMp4->proot, &trak, pExtSt->trak.stsdType, pMp4->haveMoov))) { //mp4_close(pMp4); LOG(X_ERROR("Error loading next %c%c%c%c track from '%s'"), MP4_BOX_NAME_INT2C(pExtSt->trak.stsdType), pMp4->pStream->cbGetName(pMp4->pStream)); return -1; } //fprintf(stderr, "DONE CALLING LOADTRAK %c%c%c%c from load_next_mp4 for '%s' has %d samples\n", MP4_BOX_NAME_INT2C(pExtSt->trak.stsdType), pMp4->pStream->cbGetName(pMp4->pStream), pExtSt->cur.u.mf.countSamples); memcpy(&nextLoader, &pExtSt->nextLoader, sizeof(nextLoader)); memset(pExtSt, 0, sizeof(MP4_EXTRACT_STATE_T)); memcpy(&pExtSt->trak, &trak, sizeof(MP4_TRAK_T)); memcpy(&pExtSt->nextLoader, &nextLoader, sizeof(pExtSt->nextLoader)); pExtSt->cur.pExtSt = pExtSt; pExtSt->start.pExtSt = pExtSt; pExtSt->lastSync.pExtSt = pExtSt; pExtSt->pStream = pMp4->pStream; return rc; }