      if fr is not None:
        print(f"Decompressing frames {s}")
        frames = []
        for i in tqdm(range(fr.frame_count)):
          img = fr.get(i, pix_fmt='yuv420p')[0]
          frames.append(img.flatten().tobytes())
  
      vs.create_buffers(stream, 40, False, size[0], size[1])
      if use_extra_client:
        vs.create_buffers(VisionStreamType.VISION_STREAM_WIDE_ROAD, 40, False, size[0], size[1])
 
</s> remove     if pix_fmt not in ("yuv420p", "rgb24"):
 </s> add     if pix_fmt not in ("nv12", "yuv420p", "rgb24"): </s> remove           img = frs[msg.which()].get(frame_idxs[msg.which()], pix_fmt="yuv420p")[0]
 </s> add           img = frs[msg.which()].get(frame_idxs[msg.which()], pix_fmt="nv12")[0] </s> remove         for stream_type, frame_size, state in streams:
          dat = np.empty(int(frame_size[0]*frame_size[1]*3/2), dtype=np.uint8)
 </s> add         for stream_type, frame_spec, state in streams:
          if TICI:
            dat = np.empty(frame_spec[2], dtype=np.uint8)
          else:
            dat = np.empty(int(frame_spec[0]*frame_spec[1]*3/2), dtype=np.uint8) </s> remove     uint8_t *u = y + width * height;
    uint8_t *v = u + (width / 2) * (height / 2);
    libyuv::NV12ToI420(f->data[0], f->linesize[0], f->data[1], f->linesize[1],
                       y, width, u, width / 2, v, width / 2, width, height);
 </s> add     uint8_t *uv = y + width * height;
    for (int i = 0; i < height/2; i++) {
      memcpy(y + (i*2 + 0)*width, f->data[0] + (i*2 + 0)*f->linesize[0], width);
      memcpy(y + (i*2 + 1)*width, f->data[0] + (i*2 + 1)*f->linesize[0], width);
      memcpy(uv + i*width, f->data[1] + i*f->linesize[1], width);
    }
        img = fr.get(i, pix_fmt='nv12')[0]
      if fr is not None:
        print(f"Decompressing frames {s}")
        frames = []
        for i in tqdm(range(fr.frame_count)):
        img = fr.get(i, pix_fmt='nv12')[0]
          frames.append(img.flatten().tobytes())
  
      vs.create_buffers(stream, 40, False, size[0], size[1])
      if use_extra_client:
        vs.create_buffers(VisionStreamType.VISION_STREAM_WIDE_ROAD, 40, False, size[0], size[1])
keep keep keep keep replace keep keep keep keep keep
 nv12: encoderd avoids a full frame copy (#24519)

* rgb to nv12

* nv12 works (w memcpy)

* correct now

* no copy

* fix nv12 with fast debayer

* reverts of unused stuff

* ui use nv12

* comment out thumbnails for now

* rebase fix

* dm read nv12

* model read nv12

* fix ffmpeg encoder

* thumbnails from nv12

* replay to nv12

* python framereader support nv12

* remove hardcoded frame/buffer sizes

* fix build

* ffmpeg encoder fix buffers

* small cleanup

* reduce power usage test

* fix cpu usage test

* fix snapshot

* fix loggerd test

* bump cereal

Co-authored-by: Comma Device <device@comma.ai>
Co-authored-by: Joost Wooning <jwooning@gmail.com> 
selfdrive/test/process_replay/regen.py