

'''simple docstring'''




import logging
import math
from functools import partial
from typing import Any, Callable, Dict, Iterable, List, Optional, Sequence, Tuple, Union

import torch

from .tensor_utils import tensor_tree_map, tree_map


def    lowerCamelCase__		(    SCREAMING_SNAKE_CASE   : Union[dict, list, tuple, torch.Tensor]    ):
  UpperCAmelCase    				=						[]
  if isinstance(SCREAMING_SNAKE_CASE							, SCREAMING_SNAKE_CASE    ):
    for v in tree.values():
      shapes.extend(_fetch_dims(SCREAMING_SNAKE_CASE    )    )
  elif isinstance(SCREAMING_SNAKE_CASE							, (list, tuple)    ):
    for t in tree:
      shapes.extend(_fetch_dims(SCREAMING_SNAKE_CASE    )    )
  elif isinstance(SCREAMING_SNAKE_CASE							, torch.Tensor    ):
    shapes.append(tree.shape    )
  else:
    raise ValueError('Not supported'    )

  return shapes


@torch.jit.ignore
def    lowerCamelCase__		(    SCREAMING_SNAKE_CASE   : int							, SCREAMING_SNAKE_CASE   : Tuple[int, ...]    ):
  UpperCAmelCase    				=						[]
  for d in reversed(SCREAMING_SNAKE_CASE    ):
    idx.append(flat_idx % d    )
    UpperCAmelCase    				=						flat_idx // d

  return tuple(reversed(SCREAMING_SNAKE_CASE    )    )


@torch.jit.ignore
def    lowerCamelCase__		(    SCREAMING_SNAKE_CASE   : Sequence[int]							, SCREAMING_SNAKE_CASE   : Sequence[int]							, SCREAMING_SNAKE_CASE   : Sequence[int]							, SCREAMING_SNAKE_CASE   : Optional[Sequence[bool]] = None							, SCREAMING_SNAKE_CASE   : Optional[Sequence[bool]] = None							, ):

  # start_edges and end_edges both indicate whether, starting from any given
  # dimension, the start/end index is at the top/bottom edge of the
  # corresponding tensor, modeled as a tree
  def reduce_edge_list(SCREAMING_SNAKE_CASE   : List[bool]    ) -> None:
    UpperCAmelCase    				=						True
    for i in range(len(SCREAMING_SNAKE_CASE    )    ):
      UpperCAmelCase    				=						-1 * (i + 1)
      l[reversed_idx] &= tally
      UpperCAmelCase    				=						l[reversed_idx]

  if start_edges is None:
    UpperCAmelCase    				=						[s == 0 for s in start]
    reduce_edge_list(SCREAMING_SNAKE_CASE    )
  if end_edges is None:
    UpperCAmelCase    				=						[e == (d - 1) for e, d in zip(SCREAMING_SNAKE_CASE							, SCREAMING_SNAKE_CASE    )]
    reduce_edge_list(SCREAMING_SNAKE_CASE    )

  # Base cases. Either start/end are empty and we're done, or the final,
  # one-dimensional tensor can be simply sliced
  if len(SCREAMING_SNAKE_CASE    ) == 0:
    return [()]
  elif len(SCREAMING_SNAKE_CASE    ) == 1:
    return [(slice(start[0]							, end[0] + 1    ),)]

  UpperCAmelCase    				=						[]
  UpperCAmelCase    				=						[]

  # Dimensions common to start and end can be selected directly
  for s, e in zip(SCREAMING_SNAKE_CASE							, SCREAMING_SNAKE_CASE    ):
    if s == e:
      path_list.append(slice(SCREAMING_SNAKE_CASE							, s + 1    )    )
    else:
      break

  UpperCAmelCase    				=						tuple(SCREAMING_SNAKE_CASE    )
  UpperCAmelCase    				=						len(SCREAMING_SNAKE_CASE    )

  # start == end, and we're done
  if divergence_idx == len(SCREAMING_SNAKE_CASE    ):
    return [path]

  def upper() -> Tuple[Tuple[slice, ...], ...]:
    assert start_edges is not None
    assert end_edges is not None

    UpperCAmelCase    				=						start[divergence_idx]
    return tuple(
        path + (slice(SCREAMING_SNAKE_CASE							, sdi + 1    ),) + s
        for s in _get_minimal_slice_set(
            start[divergence_idx + 1 :]							, [d - 1 for d in dims[divergence_idx + 1 :]]							, dims[divergence_idx + 1 :]							, start_edges=start_edges[divergence_idx + 1 :]							, end_edges=[True for _ in end_edges[divergence_idx + 1 :]]							, )    )

  def lower() -> Tuple[Tuple[slice, ...], ...]:
    assert start_edges is not None
    assert end_edges is not None

    UpperCAmelCase    				=						end[divergence_idx]
    return tuple(
        path + (slice(SCREAMING_SNAKE_CASE							, edi + 1    ),) + s
        for s in _get_minimal_slice_set(
            [0 for _ in start[divergence_idx + 1 :]]							, end[divergence_idx + 1 :]							, dims[divergence_idx + 1 :]							, start_edges=[True for _ in start_edges[divergence_idx + 1 :]]							, end_edges=end_edges[divergence_idx + 1 :]							, )    )

  # If both start and end are at the edges of the subtree rooted at
  # divergence_idx, we can just select the whole subtree at once
  if start_edges[divergence_idx] and end_edges[divergence_idx]:
    slices.append(path + (slice(start[divergence_idx]							, end[divergence_idx] + 1    ),)    )
  # If just start is at the edge, we can grab almost all of the subtree,
  # treating only the ragged bottom edge as an edge case
  elif start_edges[divergence_idx]:
    slices.append(path + (slice(start[divergence_idx]							, end[divergence_idx]    ),)    )
    slices.extend(lower()    )
  # Analogous to the previous case, but the top is ragged this time
  elif end_edges[divergence_idx]:
    slices.extend(upper()    )
    slices.append(path + (slice(start[divergence_idx] + 1							, end[divergence_idx] + 1    ),)    )
  # If both sides of the range are ragged, we need to handle both sides
  # separately. If there's contiguous meat in between them, we can index it
  # in one big chunk
  else:
    slices.extend(upper()    )
    UpperCAmelCase    				=						end[divergence_idx] - start[divergence_idx]
    if middle_ground > 1:
      slices.append(path + (slice(start[divergence_idx] + 1							, end[divergence_idx]    ),)    )
    slices.extend(lower()    )

  return slices


@torch.jit.ignore
def    lowerCamelCase__		(    SCREAMING_SNAKE_CASE   : torch.Tensor							, SCREAMING_SNAKE_CASE   : int							, SCREAMING_SNAKE_CASE   : int							, SCREAMING_SNAKE_CASE   : int    ):
  UpperCAmelCase    				=						t.shape[:no_batch_dims]
  UpperCAmelCase    				=						list(_flat_idx_to_idx(SCREAMING_SNAKE_CASE							, SCREAMING_SNAKE_CASE    )    )
  # _get_minimal_slice_set is inclusive
  UpperCAmelCase    				=						list(_flat_idx_to_idx(flat_end - 1							, SCREAMING_SNAKE_CASE    )    )

  # Get an ordered list of slices to perform
  UpperCAmelCase    				=						_get_minimal_slice_set(
      SCREAMING_SNAKE_CASE							, SCREAMING_SNAKE_CASE							, SCREAMING_SNAKE_CASE							, )

  UpperCAmelCase    				=						[t[s] for s in slices]

  return torch.cat([s.view((-1,) + t.shape[no_batch_dims:]    ) for s in sliced_tensors]    )


def    lowerCamelCase__		(    SCREAMING_SNAKE_CASE   : Callable							, SCREAMING_SNAKE_CASE   : Dict[str, Any]							, SCREAMING_SNAKE_CASE   : int							, SCREAMING_SNAKE_CASE   : int							, SCREAMING_SNAKE_CASE   : bool = False							, SCREAMING_SNAKE_CASE   : Any = None							, SCREAMING_SNAKE_CASE   : bool = False							, ):
  if not (len(SCREAMING_SNAKE_CASE    ) > 0):
    raise ValueError('Must provide at least one input'    )

  UpperCAmelCase    				=						[shape[:no_batch_dims] for shape in _fetch_dims(SCREAMING_SNAKE_CASE    )]
  UpperCAmelCase    				=						tuple([max(SCREAMING_SNAKE_CASE    ) for s in zip(*SCREAMING_SNAKE_CASE    )]    )

  def _prep_inputs(SCREAMING_SNAKE_CASE   : torch.Tensor    ) -> torch.Tensor:
    if not low_mem:
      if not sum(t.shape[:no_batch_dims]    ) == no_batch_dims:
        UpperCAmelCase    				=						t.expand(orig_batch_dims + t.shape[no_batch_dims:]    )
      UpperCAmelCase    				=						t.reshape(-1							, *t.shape[no_batch_dims:]    )
    else:
      UpperCAmelCase    				=						t.expand(orig_batch_dims + t.shape[no_batch_dims:]    )
    return t

  UpperCAmelCase    				=						tensor_tree_map(_prep_inputs							, SCREAMING_SNAKE_CASE    )
  UpperCAmelCase    				=						None
  if _out is not None:
    UpperCAmelCase    				=						tensor_tree_map(lambda SCREAMING_SNAKE_CASE    : t.view([-1] + list(t.shape[no_batch_dims:]    )    )							, _out    )

  UpperCAmelCase    				=						1
  for d in orig_batch_dims:
    flat_batch_dim *= d

  UpperCAmelCase    				=						flat_batch_dim // chunk_size + (flat_batch_dim % chunk_size != 0)

  def _select_chunk(SCREAMING_SNAKE_CASE   : torch.Tensor    ) -> torch.Tensor:
    return t[i : i + chunk_size] if t.shape[0] != 1 else t

  UpperCAmelCase    				=						0
  UpperCAmelCase    				=						prepped_outputs
  for _ in range(SCREAMING_SNAKE_CASE    ):
    # Chunk the input
    if not low_mem:
      UpperCAmelCase    				=						_select_chunk
    else:
      UpperCAmelCase    				=						partial(
          _chunk_slice							, flat_start=SCREAMING_SNAKE_CASE							, flat_end=min(SCREAMING_SNAKE_CASE							, i + chunk_size    )							, no_batch_dims=len(SCREAMING_SNAKE_CASE    )							, )

    UpperCAmelCase    				=						tensor_tree_map(SCREAMING_SNAKE_CASE							, SCREAMING_SNAKE_CASE    )

    # Run the layer on the chunk
    UpperCAmelCase    				=						layer(**SCREAMING_SNAKE_CASE    )

    # Allocate space for the output
    if out is None:
      UpperCAmelCase    				=						tensor_tree_map(lambda SCREAMING_SNAKE_CASE    : t.new_zeros((flat_batch_dim,) + t.shape[1:]    )							, SCREAMING_SNAKE_CASE    )

    # Put the chunk in its pre-allocated space
    if isinstance(SCREAMING_SNAKE_CASE							, SCREAMING_SNAKE_CASE    ):

      def assign(SCREAMING_SNAKE_CASE   : dict							, SCREAMING_SNAKE_CASE   : dict    ) -> None:
        for k, v in da.items():
          if isinstance(SCREAMING_SNAKE_CASE							, SCREAMING_SNAKE_CASE    ):
            assign(SCREAMING_SNAKE_CASE							, da[k]    )
          else:
            if _add_into_out:
              v[i : i + chunk_size] += da[k]
            else:
              UpperCAmelCase    				=						da[k]

      assign(SCREAMING_SNAKE_CASE							, SCREAMING_SNAKE_CASE    )
    elif isinstance(SCREAMING_SNAKE_CASE							, SCREAMING_SNAKE_CASE    ):
      for xa, xa in zip(SCREAMING_SNAKE_CASE							, SCREAMING_SNAKE_CASE    ):
        if _add_into_out:
          xa[i : i + chunk_size] += xa
        else:
          UpperCAmelCase    				=						xa
    elif isinstance(SCREAMING_SNAKE_CASE							, torch.Tensor    ):
      if _add_into_out:
        out[i : i + chunk_size] += output_chunk
      else:
        UpperCAmelCase    				=						output_chunk
    else:
      raise ValueError('Not supported'    )

    i += chunk_size

  UpperCAmelCase    				=						tensor_tree_map(lambda SCREAMING_SNAKE_CASE    : t.view(orig_batch_dims + t.shape[1:]    )							, SCREAMING_SNAKE_CASE    )

  return out



class 							lowercase_						:

  '''simple docstring'''





  def __init__(  self ,			a_ = 5_1_2 ,			)				->					Any:


    """simple docstring"""
    UpperCAmelCase    				=						max_chunk_size
    UpperCAmelCase    				=						None
    UpperCAmelCase    				=						None
  def     snake_case_      (  self ,			a_ ,			a_ ,			a_  )				->					int:


    """simple docstring"""
    logging.info('Tuning chunk size...'  )

    if min_chunk_size >= self.max_chunk_size:
      return min_chunk_size

    UpperCAmelCase    				=						[2**l for l in range(int(math.log(self.max_chunk_size ,			2  )  ) + 1  )]
    UpperCAmelCase    				=						[c for c in candidates if c > min_chunk_size]
    UpperCAmelCase    				=						[min_chunk_size] + candidates
    candidates[-1] += 4

    def test_chunk_size(a_  ) -> bool:
      try:
        with torch.no_grad():
          fn(*a_ ,			chunk_size=a_  )
        return True
      except RuntimeError:
        return False

    UpperCAmelCase    				=						0
    UpperCAmelCase    				=						len(a_  ) - 1
    while i > min_viable_chunk_size_index:
      UpperCAmelCase    				=						test_chunk_size(candidates[i]  )
      if not viable:
        UpperCAmelCase    				=						(min_viable_chunk_size_index + i) // 2
      else:
        UpperCAmelCase    				=						i
        UpperCAmelCase    				=						(i + len(a_  ) - 1) // 2

    return candidates[min_viable_chunk_size_index]
  def     snake_case_      (  self ,			a_ ,			a_  )				->					bool:


    """simple docstring"""
    UpperCAmelCase    				=						True
    for aa, aa in zip(a_ ,			a_  ):
      assert type(a_  ) == type(a_  )
      if isinstance(a_ ,			(list, tuple)  ):
        consistent &= self._compare_arg_caches(a_ ,			a_  )
      elif isinstance(a_ ,			a_  ):
        UpperCAmelCase    				=						[v for _, v in sorted(aa.items() ,			key=lambda a_  : x[0]  )]
        UpperCAmelCase    				=						[v for _, v in sorted(aa.items() ,			key=lambda a_  : x[0]  )]
        consistent &= self._compare_arg_caches(a_ ,			a_  )
      else:
        consistent &= aa == aa

    return consistent





  def     snake_case_      (  self ,			a_ ,			a_ ,			a_ ,			)				->					int:


    """simple docstring"""
    UpperCAmelCase    				=						True
    UpperCAmelCase    				=						tree_map(lambda a_  : a.shape if isinstance(a_ ,			torch.Tensor  ) else a ,			a_ ,			a_  )
    if self.cached_arg_data is not None:
      # If args have changed shape/value, we need to re-tune
      assert len(self.cached_arg_data  ) == len(a_  )
      UpperCAmelCase    				=						self._compare_arg_caches(self.cached_arg_data ,			a_  )
    else:
      # Otherwise, we can reuse the precomputed value
      UpperCAmelCase    				=						False

    if not consistent:
      UpperCAmelCase    				=						self._determine_favorable_chunk_size(
          a_ ,			a_ ,			a_ ,			)
      UpperCAmelCase    				=						arg_data

    assert self.cached_chunk_size is not None

    return self.cached_chunk_size





'''simple docstring'''




from io import BytesIO
from typing import List, Union

import requests

from ..utils import add_end_docstrings, is_decord_available, is_torch_available, logging, requires_backends
from .base import PIPELINE_INIT_ARGS, Pipeline


if is_decord_available():
  import numpy as np
  from decord import VideoReader


if is_torch_available():
  from ..models.auto.modeling_auto import MODEL_FOR_VIDEO_CLASSIFICATION_MAPPING

_a					:			List[Any]							=    logging.get_logger(__name__)



@add_end_docstrings(a			)
class 							lowercase_						(		a			):

  '''simple docstring'''





  def __init__(  self ,			*a_ ,			**a_  )				->					str:


    """simple docstring"""
    super().__init__(*a_ ,			**a_  )
    requires_backends(self ,			'decord'  )
    self.check_model_type(a_  )
  def     snake_case_      (  self ,			a_=None ,			a_=None ,			a_=None  )				->					int:


    """simple docstring"""
    UpperCAmelCase    				=						{}
    if frame_sampling_rate is not None:
      UpperCAmelCase    				=						frame_sampling_rate
    if num_frames is not None:
      UpperCAmelCase    				=						num_frames

    UpperCAmelCase    				=						{}
    if top_k is not None:
      UpperCAmelCase    				=						top_k
    return preprocess_params, {}, postprocess_params
  def __call__(  self ,			a_ ,			**a_  )				->					Union[str, Any]:


    """simple docstring"""
    return super().__call__(a_ ,			**a_  )
  def     snake_case_      (  self ,			a_ ,			a_=None ,			a_=1  )				->					Tuple:


    """simple docstring"""
    if num_frames is None:
      UpperCAmelCase    				=						self.model.config.num_frames

    if video.startswith('http://'  ) or video.startswith('https://'  ):
      UpperCAmelCase    				=						BytesIO(requests.get(a_  ).content  )

    UpperCAmelCase    				=						VideoReader(a_  )
    videoreader.seek(0  )

    UpperCAmelCase    				=						0
    UpperCAmelCase    				=						num_frames * frame_sampling_rate - 1
    UpperCAmelCase    				=						np.linspace(a_ ,			a_ ,			num=a_ ,			dtype=np.intaa  )

    UpperCAmelCase    				=						videoreader.get_batch(a_  ).asnumpy()
    UpperCAmelCase    				=						list(a_  )

    UpperCAmelCase    				=						self.image_processor(a_ ,			return_tensors=self.framework  )
    return model_inputs
  def     snake_case_      (  self ,			a_  )				->					Union[str, Any]:


    """simple docstring"""
    UpperCAmelCase    				=						self.model(**a_  )
    return model_outputs





  def     snake_case_      (  self ,			a_ ,			a_=5  )				->					Union[str, Any]:


    """simple docstring"""
    if top_k > self.model.config.num_labels:
      UpperCAmelCase    				=						self.model.config.num_labels

    if self.framework == "pt":
      UpperCAmelCase    				=						model_outputs.logits.softmax(-1  )[0]
      UpperCAmelCase				,   UpperCAmelCase    				=						probs.topk(a_  )
    else:
      raise ValueError(F'''Unsupported framework: {self.framework}'''  )

    UpperCAmelCase    				=						scores.tolist()
    UpperCAmelCase    				=						ids.tolist()
    return [{"score": score, "label": self.model.config.idalabel[_id]} for score, _id in zip(a_ ,			a_  )]


