Mailing List archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

AV_PES format - How can I detect frames?



I am trying to detect the frames of an AV_PES data stream
in order to be able to resume replaying a stored video
file at a given location (typically where the user left off
by stopping a previous replay session).

In order to do this I have written a small program (see attachment)
that detects the data blocks in an AV_PES data stream and lists the 
first few bytes of every block to stdout. The headers of these AV_PES
data blocks, however, don't appear to contain any information
on whether a new frame starts in this block, and wether that is
an 'I', 'P' or 'B' frame (being able to identify 'I' frames would
do for my purpose). So that information must be stored in the data
contained within the AV_PES blocks.

The reason why I want to be able to detect the single frames is
that if I start replaying in the middle of the data stream I am
likely to get a distorted picture for a few seconds. I also want to
implement a "fast rewind" function, which would also benefit greatly
from being able to go back by a certain number of 'I' frames.

The question is: can anybody point me to a place where I can get
information about the actual data contained in the AV_PES data
stream? I assume that must be the MPEG-2 data, but all the places
I found on the Web dealing with MPEG-2 data format are either much
too theoretical, or don't help to quickly identify frame borders
given a binary data stream.

Any help would be greatly appreciated.

Klaus Schmidinger
-- 
_______________________________________________________________

Klaus Schmidinger                       Phone: +49-8635-6989-10
CadSoft Computer GmbH                   Fax:   +49-8635-6989-40
Hofmark 2                               Email:   kls@cadsoft.de
D-84568 Pleiskirchen, Germany           URL:     www.cadsoft.de
_______________________________________________________________
    [ Part 2: "Attached Text" ]

/*

This program detects the data blocks in an AV_PES data stream.

AV_PES data format:

'A'  'V'  t  n  'U'  g  ll  d d d ...

where

- '*' are literal characters
- t   is the type (1 = Video, 2 = Audio)
- n   is a sequence number (0..255, wrapping)
- g   is a "gap" number (don't know what it means)
- ll  is the two byte length of data (high byte first)
- d   is the actual video or audio data

*/

#include <fcntl.h>
#include <netinet/in.h>
#include <stdio.h>
#include <unistd.h>

#define SHOWBYTES 20
 
typedef unsigned char uchar;
typedef unsigned short ushort;

struct tAVPES {
  uchar AV[2];
  uchar t;
  uchar n;
  uchar U;
  uchar g;
  ushort ll;
  bool IsHeader(void) { return AV[0] == 'A' && AV[1] == 'V' && (t == 1 || t == 2) && U == 'U'; }
  ushort Length(void) { return ntohs(ll); }
  };

int main(int argc, char *argv[])
{
  if (argc > 2)
     return 1;

  int f = argc == 2 ? open(argv[1], O_RDONLY) : fileno(stdin);

  if (f >= 0) {
     tAVPES a;
     int r;
     while ((r = read(f, &a, sizeof(a))) == sizeof(a)) {
           if (a.IsHeader()) {
              ushort l = a.Length();
              printf("%c%c %d %3d %c %02X %5d", a.AV[0], a.AV[1], a.t, a.n, a.U, a.g, l);
              uchar d[SHOWBYTES];
              int rd;
              if ((rd = read(f, &d, sizeof(d))) == sizeof(d)) {
                 for (int i = 0; i < SHOWBYTES; i++)
                     printf(" %02X", d[i]);
                 printf("\n");
                 lseek(f, l - SHOWBYTES, SEEK_CUR);
                 }
              else
                 break;
              }
           else
              lseek(f, -(r - 1), SEEK_CUR);
           }
     }
  else
     fprintf(stderr, "can't open '%s'\n", argv[1]);
  return 0;
}


Home | Main Index | Thread Index