//******************************************************* int defaultAudioSlave( muxerMT *context ) { DIA_encoding *work=(DIA_encoding *)context->opaque; uint32_t total_sample=0; uint32_t total_size=0; uint32_t samples,audioLen; printf("[AudioThread] Starting\n"); while(context->audioEncoder->getPacket(context->audioBuffer, &audioLen, &samples) && total_sample<context->audioTargetSample) { total_sample+=samples; total_size+=audioLen; accessMutex.lock(); if(context->audioAbort) { context->audioDone=1; context->muxer->audioEof(); accessMutex.unlock(); return 1; } work->setAudioSize(total_size); accessMutex.unlock(); while(!context->muxer->needAudio()) { if(context->audioAbort) { context->muxer->audioEof(); context->audioDone=1; return 1; } }; if(audioLen) { context->muxer->writeAudioPacket(audioLen,context->audioBuffer); } accessMutex.lock(); context->feedAudio+=audioLen; accessMutex.unlock(); } accessMutex.lock(); // Let's say audio is always ok, shall we :) context->audioDone=1; context->muxer->audioEof(); accessMutex.unlock(); printf("[AudioThread] Exiting\n"); printf("[AudioThread] Target %u, got %u, %f %%\n",context->audioTargetSample,total_sample, (float)total_sample/(float)context->audioTargetSample); return 1; }
void *ADM_alloc(size_t size) { #ifdef __APPLE__ return malloc(size); #else char *c; uint64_t l, lorg; uint32_t *backdoor; int dome = doMemStat; if(dome) memAccess.lock(); l = (uint64_t)malloc(size + 32); // Get next boundary lorg = l; l = (l + 15) & 0xfffffffffffffff0LL; l += 16; c = (char*)l; backdoor = (uint32_t*)(c - 8); *backdoor = (0xdead << 16) + l - lorg; backdoor[1] = size; if(dome) memAccess.unlock(); ADM_consumed += size; return c; #endif }
void ADM_dezalloc(void *ptr) { int dome=doMemStat; uint32_t *backdoor; uint32_t size,offset; char *c=(char *)ptr; if(!ptr) return; backdoor=(uint32_t *)ptr; backdoor-=2; if(*backdoor==0xbeefbeef) { printf("Double free gotcha!\n"); ADM_assert(0); } ADM_assert(((*backdoor)>>16)==0xdead); offset=backdoor[0]&0xffff; size=backdoor[1]; *backdoor=0xbeefbeef; // Scratch sig if(dome) memAccess.lock(); free(c-offset); ADM_consumed-=size; if(dome) memAccess.unlock(); }
/** \fn getBuffer \brief returns a VDPAU render masquerading as a AVFrame */ int decoderFFLIBVA::getBuffer(AVCodecContext *avctx, AVFrame *pic) { decoderFFLIBVA *x=(decoderFFLIBVA *)avctx->opaque; imageMutex.lock(); ADM_assert(!freeSurfaceQueue.empty()); ADM_vaSurface *s= x->freeSurfaceQueue[0]; x->freeSurfaceQueue.popFront(); imageMutex.unlock(); libvaMarkSurfaceUsed(s,this); aprintf("Alloc Buffer : 0x%llx\n",s); uint8_t *p=(uint8_t *)s->surface; pic->data[0]=p; pic->data[1]=p; pic->data[2]=p; pic->data[3]=p; pic->linesize[0]=0; pic->linesize[1]=0; pic->linesize[2]=0; pic->linesize[3]=0; pic->type=FF_BUFFER_TYPE_USER; // render->state =0; // render->state |= FF_LIBVA_STATE_USED_FOR_REFERENCE; // render->state &= ~FF_LIBVA_STATE_DECODED; // render->psf=0; pic->reordered_opaque= avctx->reordered_opaque; // pic->opaque= avctx->opaque; return 0; }
/** * \fn lookupBySurfaceId * @param * @return */ ADM_vaSurface *decoderFFLIBVA::lookupBySurfaceId(VASurfaceID id) { imageMutex.lock(); int n=allSurfaceQueue.size(); for(int i=0;i<n;i++) if(allSurfaceQueue[i]->surface==id) { imageMutex.unlock(); return allSurfaceQueue[i]; } imageMutex.unlock(); ADM_warning("Lookup a non existing surface\n"); ADM_assert(0); return NULL; }
/** \fn markSurfaceUsed \brief mark the surfave as used. Can be called multiple time. */ bool decoderFFLIBVA::markSurfaceUsed(ADM_vaSurface *s) { imageMutex.lock(); s->refCount++; imageMutex.unlock(); return true; }
//******************************************************* int defaultVideoSlave( muxerMT *context ) { DIA_encoding *work=(DIA_encoding *)context->opaque; ADMBitstream *bitstream=context->bitstream; uint32_t mx=context->nbVideoFrame; printf("[VideoThread] Starting\n"); for(uint32_t i=0;i<mx;i++) { bitstream->cleanup(i); if(context->videoAbort) { context->videoDone=1; context->muxer->videoEof(); return 1; } if(!context->videoEncoder->encode( i,bitstream)) { accessMutex.lock(); context->videoDone=2; context->muxer->videoEof(); accessMutex.unlock(); return 1; } if(bitstream->len) context->muxer->writeVideoPacket(bitstream); work->setFrame(i,bitstream->len,bitstream->out_quantizer,mx); accessMutex.lock(); context->currentVideoFrame=i; context->feedVideo+=bitstream->len; accessMutex.unlock(); } accessMutex.lock(); context->videoDone=1; context->muxer->videoEof(); accessMutex.unlock(); printf("[VideoThread] Exiting\n"); return 1; }
/** \fn markSurfaceUsed \brief mark the surfave as used. Can be called multiple time. */ static bool libvaMarkSurfaceUsed(void *v, void * cookie) { ADM_vaSurface *img=(ADM_vaSurface *)v; decoderFFLIBVA *decoder=(decoderFFLIBVA *)cookie; imageMutex.lock(); img->refCount++; imageMutex.unlock(); return true; }
/** \fn markSurfaceUnused \brief mark the surfave as unused by the caller. Can be called multiple time. */ bool decoderFFLIBVA::markSurfaceUnused(ADM_vaSurface *img) { imageMutex.lock(); img->refCount--; aprintf("Surface %x, Ref count is now %d\n",img->surface,img->refCount); if(!img->refCount) { vaPool.freeSurfaceQueue.append(img); } imageMutex.unlock(); return true; }
/** * * @param avctx * @param pic * @return */ int decoderFFLIBVA::getBuffer(AVCodecContext *avctx, AVFrame *pic) { imageMutex.lock(); if(vaPool.freeSurfaceQueue.empty()) { aprintf("Allocating new vaSurface\n"); ADM_vaSurface *img=allocateADMVaSurface(avctx); if(!img) { imageMutex.unlock(); ADM_warning("Cannot allocate new vaSurface!\n"); return -1; } vaPool.freeSurfaceQueue.append(img); vaPool.allSurfaceQueue.append(img); }else { aprintf("Reusing vaSurface from pool\n"); } ADM_vaSurface *s= vaPool.freeSurfaceQueue[0]; vaPool.freeSurfaceQueue.popFront(); imageMutex.unlock(); s->refCount=0; markSurfaceUsed(s); // 1 ref taken by lavcodec pic->buf[0]=av_buffer_create((uint8_t *)&(s->surface), // Maybe a memleak here... sizeof(s->surface), ADM_LIBVAreleaseBuffer, (void *)this, AV_BUFFER_FLAG_READONLY); aprintf("Alloc Buffer : 0x%llx, surfaceid=%x\n",s,(int)s->surface); pic->data[0]=(uint8_t *)s; pic->data[3]=(uint8_t *)(uintptr_t)s->surface; pic->reordered_opaque= avctx->reordered_opaque; return 0; }
/** \fn markSurfaceUnused \brief mark the surfave as unused by the caller. Can be called multiple time. */ static bool libvaMarkSurfaceUnused(void *v, void * cookie) { ADM_vaSurface *img=(ADM_vaSurface *)v; decoderFFLIBVA *decoder=(decoderFFLIBVA *)cookie; imageMutex.lock(); img->refCount--; aprintf("Ref count is now %d\n",img->refCount); if(!img->refCount) { decoder->reclaimImage(img); } imageMutex.unlock(); return true; }
/** * \fn dtor */ decoderFFLIBVA::~decoderFFLIBVA() { imageMutex.lock(); int m=vaPool.allSurfaceQueue.size(); int n=vaPool.freeSurfaceQueue.size(); if(n!=m) { ADM_warning("Some surfaces are not reclaimed! (%d/%d)\n",n,m); } for(int i=0;i<n;i++) { delete vaPool.freeSurfaceQueue[i]; } vaPool.freeSurfaceQueue.clear(); imageMutex.unlock(); }
/** * \fn dtor */ decoderFFLIBVA::~decoderFFLIBVA() { if(_context) // duplicate ~decoderFF to make sure in transit buffers are // released { avcodec_close (_context); av_free(_context); _context=NULL; } imageMutex.lock(); int m=this->allSurfaceQueue.size(); int n=freeSurfaceQueue.size(); if(n!=m) { ADM_warning("Some surfaces are not reclaimed! (%d/%d)\n",n,m); } for(int i=0;i<n;i++) { delete freeSurfaceQueue[i]; } freeSurfaceQueue.clear(); imageMutex.unlock(); nbSurface=0; if(libva!=VA_INVALID) admLibVA::destroyDecoder(libva); libva=VA_INVALID; if(scratch) delete scratch; scratch=NULL; if(va_context) { delete va_context; va_context=NULL; } }