(self)
| 717 | self._streamer._log(f"[VIDEO] ProcessedVideoTrack target resolution set to {width}x{height}") |
| 718 | |
| 719 | async def recv(self): |
| 720 | # Ensure MediaClock is started |
| 721 | if not self._streamer._media_clock.is_started: |
| 722 | self._streamer._media_clock.start() |
| 723 | |
| 724 | clock = self._streamer._media_clock |
| 725 | |
| 726 | if self.use_camera: |
| 727 | # Check if user provided a frame override |
| 728 | if self._streamer.user_frame is not None: |
| 729 | # Use user-provided frame instead of camera |
| 730 | img = self._streamer.user_frame |
| 731 | # Get timing from camera track if available |
| 732 | try: |
| 733 | camera_frame = await self.video_track.recv() |
| 734 | pts = camera_frame.pts |
| 735 | time_base = camera_frame.time_base |
| 736 | except: |
| 737 | # Fallback timing using MediaClock |
| 738 | pts = clock.get_video_pts(self.warmup_frames, 30) |
| 739 | time_base = fractions.Fraction(1, MediaClock.VIDEO_CLOCK_RATE) |
| 740 | else: |
| 741 | # Get frame from camera |
| 742 | frame = await self.video_track.recv() |
| 743 | img = frame.to_ndarray(format="bgr24") |
| 744 | pts = frame.pts |
| 745 | time_base = frame.time_base |
| 746 | |
| 747 | if img.shape[:2] != (self.height, self.width): |
| 748 | img = cv2.resize(img, (self.width, self.height)) |
| 749 | |
| 750 | # Store frame for reference |
| 751 | self.frame = img.copy() |
| 752 | |
| 753 | # Log encoder warmup progress |
| 754 | if self.warmup_frames < 10: |
| 755 | self.warmup_frames += 1 |
| 756 | if self.warmup_frames == 10: |
| 757 | self._streamer._log("[VIDEO] Encoder warmed up - optimal encoding should begin") |
| 758 | |
| 759 | # Apply user callback if registered |
| 760 | if self.callback is not None: |
| 761 | try: |
| 762 | # Apply user's processing function |
| 763 | processed_img = self.callback(img) |
| 764 | |
| 765 | # Convert back to VideoFrame |
| 766 | new_frame = VideoFrame.from_ndarray(processed_img, format="bgr24") |
| 767 | new_frame.pts = pts |
| 768 | new_frame.time_base = time_base |
| 769 | return new_frame |
| 770 | except Exception as e: |
| 771 | if self._streamer.verbose: |
| 772 | traceback.print_exc() |
| 773 | self._streamer._log(f"Error in frame callback: {e}", force=True) |
| 774 | # Return original frame if processing fails |
| 775 | new_frame = VideoFrame.from_ndarray(img, format="bgr24") |
| 776 | new_frame.pts = pts |
nothing calls this directly
no test coverage detected