bool decodeFrame(StreamFrameMap& streamFrames) { bool done = false; while(!done) { // demux PacketPtr packet = demuxPacket(); if(packet == 0){ FlogE("demuxing failed"); return 0; } // decode decodePacket(packet, streamFrames); // check if any frames finished for(auto pair : streamFrames){ FramePtr frame = pair.second; if(frame->finished != 0){ // set timestamp and break out of loop int64_t pts = av_frame_get_best_effort_timestamp(frame->GetAvFrame()); if(pair.first == videoStream){ if(firstDts == AV_NOPTS_VALUE){ firstDts = frame->GetAvFrame()->pkt_dts; FlogD("setting firstDts to: " << firstDts); } if(firstPts == AV_NOPTS_VALUE){ firstPts = pts; FlogD("setting firstPts to: " << firstPts); } } frame->SetPts(pts); done = true; } } } // successfully decoded frame, reset retry counter ResetRetries(); return true; }
bool update() { tick(); adjustTime(); FramePtr newFrame = fetchFrame(); if(newFrame != 0){ // Don't free currentFrame if it is currentFrame itself that's being converted if(currentFrame == 0 || currentFrame->GetAvFrame() != newFrame->GetAvFrame()){ currentFrame = newFrame; // Save the current frame for snapshots etc. } lastFrameQueuePts = timeFromTs(newFrame->GetPts()); return true; } return false; }
void decodePacket(PacketPtr packet, StreamFrameMap& streamFrames) { int bytesRemaining = packet->avPacket.size; // Decode until all bytes in the read frame is decoded while(bytesRemaining > 0) { int bytesDecoded = 0; int idx = packet->avPacket.stream_index; auto it = streamFrames.find(idx); if(it != streamFrames.end()){ FramePtr frame = it->second; switch(pFormatCtx->streams[idx]->codec->codec_type){ case AVMEDIA_TYPE_VIDEO: if( (bytesDecoded = avcodec_decode_video2(pCodecCtx, frame->GetAvFrame(), &frame->finished, &packet->avPacket)) <= 0 ){ Retry(Str("avcodec_decode_video2() failed in decodePacket, returned: " << bytesDecoded)); } frame->hasVideo = true; break; case AVMEDIA_TYPE_AUDIO: if((bytesDecoded = audioHandler->decode(packet->avPacket, pFormatCtx->streams[audioStream], frame, frame->finished)) <= 0){ Retry(Str("audio decoder failed in decodePacket, returned: " << bytesDecoded)); } frame->hasAudio = true; break; default: break; } }else{ // stream not handled return; } bytesRemaining -= bytesDecoded; if(bytesRemaining > 0) Retry(Str("decodePacket not finished, bytesRemaining: " << bytesRemaining << ", bytesDecoded: " << bytesDecoded)); } }