Hi,

We are using FFMpeg (libavformat) for demultiplexing an MPEG2 transport
streams. The transport stream is a DVB recording which is streamed by
VLC using multicast RTP.

Our problem is that libavformat seems to require a lot of data (approx.
1MB) to analyze the stream and determine what audio and video tracks are
available and what formats they have. With our test streams, these 1MB
of data correspond to roughly 3.2 seconds of live video, so it takes
roughly 3.2 seconds for libavformat to analyze the stream. We would like
to find out if this is a problem with the way we are using libavformat,
a problem of the specific implementation of the MPEG2 transport stream
demultiplexer in libavformat or a general problem of demultiplexing
MPEG2 transport streams that can not be avoided.

We are currently using FFMpeg revision 11871 from the SVN repository.

I have attached an example program which shows how we use libavformat.
It reads an MPEG2 transport stream from a file called "test.ts" and
exits when the stream has been analyzed, after displaying some
information about the stream.

The example program only contains the code necessary for analyzing the
MPEG2 transport stream without any error handling or cleanup code
whatsoever, to keep it simple. Also for simplicity, it reads from a file
rather than receiving a live stream. With the test stream we used, it
reads almost 1MB before displaying information about the stream. In the
"real" scenario, we read from a sequence of buffers received from the
network in "real-time", so it takes roughly 3.2 seconds until 1MB of
data has been received and the stream has been analyzed.

Is there a way in libavformat to speed up the analyzing process for
MPEG2 transport streams so that less data is required to retrieve all
information about the stream? Do you see anything wrong in the way we
are using libavformat?

Best regards and thanks in advance,
Florian

#include <iostream>
#include <fstream>
#include <cstring>

using namespace ::std;

extern "C" {
  #include <ffmpeg/avformat.h>
  #include <ffmpeg/opt.h>
}


// File stream to read from
std::ifstream ifs;

// Total number of read bytes
static size_t total_read_bytes = 0;


/** Read callback.
 * Invoked by FFMpeg to pull data from the file.
 */
static int read_packet_stream(void* opaque, uint8_t* buf, int buf_size)
{
  // Read data from file
  ifs.read(reinterpret_cast<char*>(buf), buf_size);
  size_t num_read_bytes = ifs.gcount();
  total_read_bytes += num_read_bytes;
  return num_read_bytes;
};

int main()
{
  // -------------------------------------- Init FFMpeg

  // Open file
  ifs.open("test.ts");

  // Create IO context
  ByteIOContext *io = new ByteIOContext();
  io->is_streamed = 1;

  // Register all FFMpeg codecs
  av_register_all();

  // Create format parameters
  AVFormatParameters params;
  AVFormatParameters *ap = &params;
  memset(ap, 0, sizeof(*ap));
  ap->prealloced_context = 1;

  // Create format contex
  AVFormatContext *pFormatCtx = av_alloc_format_context();
  av_set_double(pFormatCtx, "probesize", 10240);

  // Create input format
  AVInputFormat *fmt = av_find_input_format("mpegts");
  fmt->flags |= AVFMT_NOFILE;

  // Init buffer
  const int buffer_size = 100000;
  unsigned char *initbuffer = new unsigned char[ buffer_size ];


  // -------------------------------------- Retrieve stream information

  init_put_byte(io, initbuffer, buffer_size, 0, 0, &read_packet_stream, NULL, NULL);

  // Open input stream
  cout << "av_open_input_stream" << endl;
  if(av_open_input_stream(&pFormatCtx, io, "", fmt, ap)) {
    cerr << "Failed to open input stream. "  << endl;
    return 1;
  };

  // Retrieve stream information
  cout << "av_find_stream_info" << endl;
  if(av_find_stream_info(pFormatCtx)<0){
    cerr << "Couldn't find stream information" << endl;
    return 1;
  }

  std::cout << "Total read: " << total_read_bytes << endl;


  // -------------------------------------- Detect streams

  // If no programs are found, take first video and audio pid
  int vpid;
  int apid;
  if(!pFormatCtx->nb_programs) {
    cerr << "WARNING : no programs found -> take first video and audio pid" << endl;
    for(unsigned int i=0; i<pFormatCtx->nb_streams; i++) {
      int codec_type = pFormatCtx->streams[i]->codec->codec_type;
      int pid = pFormatCtx->streams[i]->id;

      // Default video
      if(codec_type == CODEC_TYPE_VIDEO && vpid == 0) {
        vpid = pid;
        cout << "     -> default vpid: " << vpid << endl;
      }

      // Default audio
      if(codec_type == CODEC_TYPE_AUDIO && apid == 0) {
        apid = pid;
        cout << "     -> default apid: " << apid << endl;
      }
    }

    // Check if default pids are found
    if(vpid != 0 || apid != 0) {
      return 0;
    }
    else {
      cerr << "ERROR : no default pids found -> abort" << endl;
      return 1;
    }
  }

  // Parse ffmpeg program table
  unsigned int programs = pFormatCtx->nb_programs;
  cout << "found " << programs << " programs" << endl;
  for(unsigned int i=0; i < programs; i++) {
    int sid = pFormatCtx->programs[i]->id;
    unsigned int streams = pFormatCtx->programs[i]->nb_stream_indexes;
    const char *name = (pFormatCtx->programs[i]->name) ?
        pFormatCtx->programs[i]->name : "";
    int additional_audio_streams = 0;
    bool define_default_pids = false;

    cout << "  Program " << i << " [" << sid << "] ";
    cout << name << endl;

    // Get information for specific stream
    for(unsigned int k=0; k < streams; k++) {
      int index = pFormatCtx->programs[i]->stream_index[k];
      int codec_type = pFormatCtx->streams[index]->codec->codec_type;
      int codec_id = pFormatCtx->streams[index]->codec->codec_id;
      int pid = pFormatCtx->streams[index]->id;
      char* lang = pFormatCtx->streams[index]->language;

      // Detect format of stream and define output jack
      if(codec_type == CODEC_TYPE_VIDEO) {
        cout << "CODEC_TYPE_VIDEO" << endl;
        if(codec_id == CODEC_ID_H264) {
          cout << "CODEC_ID_H264" << endl;
        }
        else {
          cout << "(mpeg?)" << endl;
        }
      }
      else if(codec_type == CODEC_TYPE_AUDIO) {
        if(codec_id == CODEC_ID_AC3) {
          cout << "CODEC_ID_AC3" << endl;
        }
        else {
          cout << "(mpeg?)" << endl;
        }
      }
    }
  }

  return 0;
}
_______________________________________________
libav-user mailing list
[email protected]
https://lists.mplayerhq.hu/mailman/listinfo/libav-user

Reply via email to