/*
 * Support for reversing
 *
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the MPEG TS, PS and ES tools.
 *
 * The Initial Developer of the Original Code is Amino Communications Ltd.
 * Portions created by the Initial Developer are Copyright (C) 2008
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *   Amino Communications Ltd, Swavesey, Cambridge UK
 *
 * ***** END LICENSE BLOCK *****
 */
#ifndef _reverse_defns
#define _reverse_defns

#include "compat.h"
#include "es_defns.h"

// Since reverse_data refers to h262 and acces_unit datastructures, and
// *they* refer to reverse_data, we need to break the circular referencing
// at some point
typedef struct reverse_data *reverse_data_p;
#include "h262_defns.h"
#include "accessunit_defns.h"

// ------------------------------------------------------------
// As the software progresses through the data stream forwards, it remembers
// the location, size and details for frames that it might want to output in
// reverse
struct reverse_data
{
  int        is_h264;     // Dealing with H.264 or H.262 data?

  // To do anything useful, we must then be linked to one or the other
  // type of input context (a union would save 4 bytes, but it doesn't
  // seem worth the bother at the moment).
  h262_context_p         h262;
  access_unit_context_p  h264;

  // Information for managing our arrays. `use_seq_offset` will be TRUE
  // for H.262 data, and FALSE for H.264 (MPEG-4/AVC)
  int        length;      // Number of items in our arrays
  int        size;        // How big our arrays are
  uint32_t   num_pictures;   // How many pictures we have
  // Four useful arrays (although the last is not used for H.264 data)
  uint32_t  *index;       // Which picture this is, counted from the start
  offset_t  *start_file;  // The start offset of an item in the input file
  int32_t   *start_pkt;   // and then within the PES packet (if needed)
  int32_t   *data_len;    // Its length in bytes

  byte      *seq_offset;  // For MPEG-2, the offset backwards in the arrays
                          // to the nearest earlier sequence header, or 0
                          // for a sequence header entry
  byte      *afd_byte;    // For MPEG-2, the AFD byte current for the picture

  // @@@ To be added later: for H.264 it's useful to know if a particular
  //     entry is an IDR or not. Thus add a ``byte *`` value called something
  //     like `is_IDR`, and make it point to `seq_offset`, since that is
  //     not used for H.264 data.
  //     (as a precursor to this, the code in reverse.c already allocates
  //     and extends the seq_offset array whether it is H.262 or H.264 data)
  
  // Is our "counting" in `index` going to last long enough? Well, if
  // we assume (worst case) that every picture was remembered in our arrays,
  // then we would have 2**32-1 pictures. At (another worst case) 50 frames
  // per second, that gives us (2**32-1)/50 seconds, which is 85899345
  // seconds (rounded down), or 23860 hours. Which I think should be enough
  // (about two years - yes, that should be enough).

  // When a function (output_in_reverse_as_XX) is called to output
  // reversed data, the reversal can either start from a specific index,
  // or from the "default", which is the current index. To make this easier,
  // we need to remember the index of the last entry added (which may be
  // less than the length of the array, since we might have rewound, and
  // be adding pictures again). Note that this is undefined if `length`
  // is 0.
  //
  // (There's probably a better name for this, since it's really more
  // like the highwater mark for what we've played forwards since we last
  // started playing forwards again, but I can't think of anything startlingly
  // illustrative, so this name will stay for now.)
  uint32_t   last_posn_added;

  // Do we want to output sequence headers or not, when reversing H.262?
  int        output_sequence_headers;

  // If we're outputting TS packets, we need to know the PID and stream id
  // to use. We *could* pass that down to each reverse call, but it's easier
  // to set it once and for all.
  uint32_t   pid;
  byte       stream_id;
  
  // When a function (output_in_reverse_as_XX) is called to output
  // reversed data, some statistics are maintained by the call.
  // Despite saying "picture", these also apply to H.264 access units as well
  // (and in fact "frame" would be a better term).
  int        pictures_written; // The number of pictures written out
  int        pictures_kept;    // The number of *different* pictures written
  int        first_written;    // Which picture was the first written out
  int        last_written;     // Which picture was the last written out
  // (for both of the latter, the value is the index of said picture in
  // our arrays). Remember that if forwards action is to be made after
  // reversing, it is important to reset the picture index in the H.262
  // or access_unit context to the picture index of the last written
  // picture. This must be done by the caller.
};
#define SIZEOF_REVERSE_DATA sizeof(struct reverse_data)

#define REVERSE_ARRAY_START_SIZE  1000
#define REVERSE_ARRAY_INCREMENT_SIZE  500

#endif // _reverse_defns

// Local Variables:
// tab-width: 8
// indent-tabs-mode: nil
// c-basic-offset: 2
// End:
// vim: set tabstop=8 shiftwidth=2 expandtab:
