void VideoStreamPlaybackWebm::update(float p_delta) { if ((!playing || paused) || !video) return; time += p_delta; if (time < video_pos) { return; } bool audio_buffer_full = false; if (samples_offset > -1) { //Mix remaining samples const int to_read = num_decoded_samples - samples_offset; const int mixed = mix_callback(mix_udata, pcm + samples_offset * webm->getChannels(), to_read); if (mixed != to_read) { samples_offset += mixed; audio_buffer_full = true; } else { samples_offset = -1; } } const bool hasAudio = (audio && mix_callback); while ((hasAudio && !audio_buffer_full && !has_enough_video_frames()) || (!hasAudio && video_frames_pos == 0)) { if (hasAudio && !audio_buffer_full && audio_frame->isValid() && audio->getPCMF(*audio_frame, pcm, num_decoded_samples) && num_decoded_samples > 0) { const int mixed = mix_callback(mix_udata, pcm, num_decoded_samples); if (mixed != num_decoded_samples) { samples_offset = mixed; audio_buffer_full = true; } } WebMFrame *video_frame; if (video_frames_pos >= video_frames_capacity) { WebMFrame **video_frames_new = (WebMFrame **)memrealloc(video_frames, ++video_frames_capacity * sizeof(void *)); ERR_FAIL_COND(!video_frames_new); //Out of memory (video_frames = video_frames_new)[video_frames_capacity - 1] = memnew(WebMFrame); } video_frame = video_frames[video_frames_pos]; if (!webm->readFrame(video_frame, audio_frame)) //This will invalidate frames break; //Can't demux, EOS? if (video_frame->isValid()) ++video_frames_pos; }; bool video_frame_done = false; while (video_frames_pos > 0 && !video_frame_done) { WebMFrame *video_frame = video_frames[0]; // It seems VPXDecoder::decode has to be executed even though we might skip this frame if (video->decode(*video_frame)) { VPXDecoder::IMAGE_ERROR err; VPXDecoder::Image image; if (should_process(*video_frame)) { if ((err = video->getImage(image)) != VPXDecoder::NO_FRAME) { if (err == VPXDecoder::NO_ERROR && image.w == webm->getWidth() && image.h == webm->getHeight()) { PoolVector<uint8_t>::Write w = frame_data.write(); bool converted = false; if (image.chromaShiftW == 1 && image.chromaShiftH == 1) { yuv420_2_rgb8888(w.ptr(), image.planes[0], image.planes[2], image.planes[1], image.w, image.h, image.linesize[0], image.linesize[1], image.w << 2, 0); // libyuv::I420ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2], image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h); converted = true; } else if (image.chromaShiftW == 1 && image.chromaShiftH == 0) { yuv422_2_rgb8888(w.ptr(), image.planes[0], image.planes[2], image.planes[1], image.w, image.h, image.linesize[0], image.linesize[1], image.w << 2, 0); // libyuv::I422ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2], image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h); converted = true; } else if (image.chromaShiftW == 0 && image.chromaShiftH == 0) { yuv444_2_rgb8888(w.ptr(), image.planes[0], image.planes[2], image.planes[1], image.w, image.h, image.linesize[0], image.linesize[1], image.w << 2, 0); // libyuv::I444ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2], image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h); converted = true; } else if (image.chromaShiftW == 2 && image.chromaShiftH == 0) { // libyuv::I411ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2], image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h); // converted = true; } if (converted) { Ref<Image> img = memnew(Image(image.w, image.h, 0, Image::FORMAT_RGBA8, frame_data)); texture->set_data(img); //Zero copy send to visual server video_frame_done = true; } } } } } video_pos = video_frame->time; memmove(video_frames, video_frames + 1, (--video_frames_pos) * sizeof(void *)); video_frames[video_frames_pos] = video_frame; } if (video_frames_pos == 0 && webm->isEOS()) stop(); }
static void conf_process(MSFilter *f){ int i; ConfState *s=(ConfState*)f->data; Channel *chan; Channel *chan0; ms_mutex_lock(&s->lock); /*read from all inputs and put into bufferizers*/ for (i=0;i<CONF_MAX_PINS;++i){ if (f->inputs[i]!=NULL){ chan=&s->channels[i]; ms_bufferizer_put_from_queue(&chan->buff,f->inputs[i]); if (ms_bufferizer_get_avail(&chan->buff)>0) { chan->missed=0; /* reset counter of missed packet */ if (/*i>0 && */chan->is_used==FALSE) { chan->is_used=TRUE; ms_message("msconf: new contributing stream (chan=%i) %i", ms_bufferizer_get_avail(&chan->buff), i); } } } } /*do the job */ while(should_process(f,s)==TRUE){ conf_sum(f, s); conf_dispatch(f,s); } #if 0 /* mixer is disabled! -> copy A->B and B->A*/ if (s->mix_mode == FALSE) { /* get the soundread data and copy it to pinX */ for (i=1;i<CONF_MAX_PINS;i=i+2){ if (f->inputs[i]!=NULL){ chan0=&s->channels[0]; chan=&s->channels[i]; if (chan->is_used==TRUE) { while (ms_bufferizer_read(&chan->buff,(uint8_t*)chan->input,s->conf_gran)==s->conf_gran) { if (f->outputs[0]!=NULL) { /* send in pin0 */ mblk_t *m=allocb(s->conf_gran,0); memcpy(m->b_wptr, chan->input, s->conf_gran); m->b_wptr+=s->conf_gran; ms_queue_put(f->outputs[0],m); } } } if (chan0->is_used==TRUE) { while (ms_bufferizer_read(&chan0->buff,(uint8_t*)chan0->input,s->conf_gran)==s->conf_gran) { if (f->outputs[i]!=NULL) { /* send in pinI */ mblk_t *m=allocb(s->conf_gran,0); memcpy(m->b_wptr, chan0->input, s->conf_gran); m->b_wptr+=s->conf_gran; ms_queue_put(f->outputs[i],m); } } } break; } } } #endif // 0 ms_mutex_unlock(&s->lock); }