Hello list readers,

I'm trying to interleave some continuous private data into an MPEG-TS
container alongside to some audio data. As far as I know, MPEG-TS
supports private streams, but I can not get it, to work cleanly.

I've attached a little working example to show, what I've got so far
and what problems I've encountered.

The example file works like this:
* Muxing:
  * Open a format context for the MPEG-TS container.
  * Add a stream with codec-type AVMEDIA_TYPE_DATA.
  * Open file, write header.
  * Fill packets with 1024 bytes of random data (either only digits '0'
    to '9', or char (0 - 255), and write them to the container.
  * Write trailer, close file, free format context.
* Demuxing:
  * Open format context and file.
  * Find and write out stream info.
  * Read packets and write out some info.
  * Free format context.

Results, when running the example:
* With digit-only data ('0' - '9'):
  * Stream's codec-type is AVMEDIA_TYPE_UNKNOWN
  * Packet sizes are correct 1024 bytes, as generated while muxing.
* Using full bytes:
  * Stream's codec-type is AVMEDIA_TYPE_AUDIO
  * I guess FFMPEG tries to decode the not-audio data using either mp3
    (FFMPEG 2.2.3) or aac (FFMPEG 2.4.1).
  * Packet sizes are not preserved. :-(

I can work around these problems, by ignoring all warning and error
messages, as well as the codec-types. I can just use a dedicated stream
ID identify the data stream. I can put the size of each packet at the
beginning of each packet, to demangle the package data. But I'd rather
have a cleaner solution, where the codec-type is set correctly and
FFMPEG does not try to decode my data.

So... What have I done wrong? What is the correct way to achieve this?

Thanks,
  Wolfgang
#include <libavformat/avformat.h>
#include <libavformat/avio.h>

#include <stdio.h>

void writeFile(char * fileName, char digits)
{
	AVFormatContext * formatContext = NULL;
	AVStream * stream = NULL;
	AVRational refTimeBase = {1, 100};
	int c, d;
	
	/* set up container */
	avformat_alloc_output_context2(&formatContext,
	                               NULL,
	                               "mpegts",
	                               fileName);
	
	/* set up stream */
	stream = avformat_new_stream(formatContext,
	                             NULL);
	stream->codec->time_base = refTimeBase;
	stream->codec->codec_type = AVMEDIA_TYPE_DATA;
	stream->codec->bit_rate = 81920;
	stream->time_base = refTimeBase;
	stream->id = 0x1001;
	
	/* open output file */
	avio_open(&(formatContext->pb),
	          fileName,
	          AVIO_FLAG_WRITE);
	avformat_write_header(formatContext,
	                      NULL);
	
	for(c = 0; c < 100; ++c)
	{
		AVPacket packet = {0};
		av_init_packet(&packet);
		packet.data = 0;
		packet.size = 0;
		av_grow_packet(&packet, 1024);
		
		packet.stream_index = 0;
		packet.duration = 1 * refTimeBase.num * stream->time_base.den / refTimeBase.den / stream->time_base.num;
		packet.pts = c * refTimeBase.num * stream->time_base.den / refTimeBase.den / stream->time_base.num;;
		packet.dts = packet.pts;
		
		/* fill packet */
		for(d = 0; d < 1024; ++d)
		{
			if(digits)
			{
				packet.data[d] = (char) (rand() % 10) + '0';
			}else
			{
				packet.data[d] = (char) (rand() % 0x100);
			}
		}
		
		/* write packet */
		av_interleaved_write_frame(formatContext, &packet);
		
		/* free packet */
		av_free_packet(&packet);
	}
	
	av_write_trailer(formatContext);
	avio_close(formatContext->pb);
	avformat_free_context(formatContext);
}

void readFile(char * fileName)
{
	AVFormatContext * formatContext = NULL;
	AVPacket packet = {0};
	int c;
	
	/* open file */
	avformat_open_input(&formatContext,
	                    fileName,
	                    NULL,
	                    NULL);
	
	/* stream info */
	avformat_find_stream_info(formatContext,
	                          NULL);
	
	for(c = 0; c < formatContext->nb_streams; ++c)
	{
		printf("Stream: %d, id: %d, codec type: ", c, formatContext->streams[c]->id);
		
		switch(formatContext->streams[c]->codec->codec_type)
		{
		case AVMEDIA_TYPE_DATA:
			printf("Data");
			break;
			
		case AVMEDIA_TYPE_UNKNOWN:
			printf("Unknown");
			break;
			
		case AVMEDIA_TYPE_AUDIO:
			printf("Audio");
			break;
			
		default:
			printf("Something else");
		}
		
		printf("\n");
	}
	
	/* packet info */
	av_init_packet(&packet);
	packet.data = 0;
	packet.size = 0;
	while((c = av_read_frame(formatContext, &packet)) >= 0)
	{
		printf("Packet at %d*%d/%d: size: %d\n",
		       packet.pts,
		       formatContext->streams[packet.stream_index]->time_base.num,
		       formatContext->streams[packet.stream_index]->time_base.den,
		       packet.size);
		
		av_free_packet(&packet);
		packet.data = 0;
		packet.size = 0;
	}
	
	avformat_free_context(formatContext);
}

int main(int argc, char ** argv)
{
	int c;
	int digits = 0;
	for(c = 1; c < argc; ++c)
	{
		if(strcmp(argv[c], "--help") == 0 || strcmp(argv[c], "-h") == 0)
		{
			printf("Usage: %s --help | --only-digits\n", argv[0]);
			return EXIT_SUCCESS;
		}else if(strcmp(argv[c], "--only-digits") == 0 || strcmp(argv[c], "-d") == 0)
		{
			digits = 1;
		}else
		{
			fprintf(stderr, "Unknown command line option: %s\nCall %s --help\n", argv[c], argv[0]);
			return EXIT_FAILURE;
		}
	}
	
	/* register stuff */
	av_register_all();
	avcodec_register_all();
	
	writeFile("testfile.ts", digits);
	readFile("testfile.ts");
	
	return EXIT_SUCCESS;
}


_______________________________________________
Libav-user mailing list
Libav-user@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/libav-user

Reply via email to