view libmpdemux/parse_es.c @ 11623:ecaf7047b6e8

Patch from the author, Zoltan Hidvegi: The filmdint filter does not handle NTSC "telecined" 15fps movies where there is a frame break in the middle of every second NTSC frame, it outputs only 15 frames for every 30 input frames, ignoring the io option. You can notice this during encoding such a sequence you will have lots of diplicate frames / skip frames messages. The patch below fixes this.
author rfelker
date Thu, 11 Dec 2003 04:47:42 +0000
parents 66837325b929
children 8ea2e7ab3106
line wrap: on
line source

//=================== MPEG-ES VIDEO PARSER =========================

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include "config.h"
#include "mp_msg.h"
#include "help_mp.h"

#include "stream.h"
#include "demuxer.h"
#include "parse_es.h"

//static unsigned char videobuffer[MAX_VIDEO_PACKET_SIZE];
unsigned char* videobuffer=NULL;
int videobuf_len=0;
unsigned char videobuf_code[4];
int videobuf_code_len=0;

// sync video stream, and returns next packet code
int sync_video_packet(demux_stream_t *ds){
  int skipped=0;
  // we need enough bytes in the buffer:
  while(videobuf_code_len<4){
#if 0
    int c;
    c=demux_getc(ds);if(c<0){ return 0;} // EOF
    videobuf_code[videobuf_code_len++]=c;
#else
    videobuf_code[videobuf_code_len++]=demux_getc(ds);
#endif
  }
  // sync packet:
  while(1){
    int c;
    if(videobuf_code[0]==0 &&
       videobuf_code[1]==0 &&
       videobuf_code[2]==1) break; // synced
    // shift buffer, drop first byte
    ++skipped;
    videobuf_code[0]=videobuf_code[1];
    videobuf_code[1]=videobuf_code[2];
    videobuf_code[2]=videobuf_code[3];
    c=demux_getc(ds);if(c<0){ return 0;} // EOF
    videobuf_code[3]=c;
  }
  if(skipped) mp_dbg(MSGT_PARSEES,MSGL_DBG2,"videobuf: %d bytes skipped  (next: 0x1%02X)\n",skipped,videobuf_code[3]);
  return 0x100|videobuf_code[3];
}

// return: packet length
int read_video_packet(demux_stream_t *ds){
int packet_start;
  
  // SYNC STREAM
//  if(!sync_video_packet(ds)) return 0; // cannot sync (EOF)

  // COPY STARTCODE:
  packet_start=videobuf_len;
  videobuffer[videobuf_len+0]=videobuf_code[0];
  videobuffer[videobuf_len+1]=videobuf_code[1];
  videobuffer[videobuf_len+2]=videobuf_code[2];
  videobuffer[videobuf_len+3]=videobuf_code[3];
  videobuf_len+=4;
  
  // READ PACKET:
  { unsigned int head=-1;
    while(videobuf_len<VIDEOBUFFER_SIZE){
      int c=demux_getc(ds);
      if(c<0) break; // EOF
      videobuffer[videobuf_len++]=c;
#if 1
      head<<=8;
      if(head==0x100) break; // synced
      head|=c;
#else
      if(videobuffer[videobuf_len-4]==0 &&
         videobuffer[videobuf_len-3]==0 &&
         videobuffer[videobuf_len-2]==1) break; // synced
#endif
    }
  }
  
  if(ds->eof){
    videobuf_code_len=0; // EOF, no next code
    return videobuf_len-packet_start;
  }
  
  videobuf_len-=4;

  mp_dbg(MSGT_PARSEES,MSGL_DBG2,"videobuf: packet 0x1%02X  len=%d  (total=%d)\n",videobuffer[packet_start+3],videobuf_len-packet_start,videobuf_len);

  // Save next packet code:
  videobuf_code[0]=videobuffer[videobuf_len];
  videobuf_code[1]=videobuffer[videobuf_len+1];
  videobuf_code[2]=videobuffer[videobuf_len+2];
  videobuf_code[3]=videobuffer[videobuf_len+3];
  videobuf_code_len=4;

  return videobuf_len-packet_start;
}

// return: next packet code
int skip_video_packet(demux_stream_t *ds){

  // SYNC STREAM
//  if(!sync_video_packet(ds)) return 0; // cannot sync (EOF)
  
  videobuf_code_len=0; // force resync
  
  // SYNC AGAIN:
  return sync_video_packet(ds);
}