⛏️ index : haiku.git

/*
 * Copyright (c) 2004-2010 Marcus Overhagen <marcus@overhagen.de>
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without restriction, 
 * including without limitation the rights to use, copy, modify, 
 * merge, publish, distribute, sublicense, and/or sell copies of 
 * the Software, and to permit persons to whom the Software is 
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be 
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 
 * OTHER DEALINGS IN THE SOFTWARE.
 */

#include <media/MediaFormats.h>
#include <media/MediaNode.h>
#include <stdio.h>
#include "MediaFormat.h"

extern "C" {
  #include "avcodec.h"

#ifdef DEBUG
  // Needed to fix debug build, otherwise the linker complains about
  // "undefined reference to `ff_log2_tab'"
  const uint8_t ff_log2_tab[256] = {0};
#endif

}  // extern "C"


#if LIBAVCODEC_VERSION_INT <= ((54 << 16) | (50 << 8))
#define AV_CODEC_ID_AC3 CODEC_ID_AC3
#define AV_CODEC_ID_MP3 CODEC_ID_MP3
#define AV_CODEC_ID_MPEG2VIDEO CODEC_ID_MPEG2VIDEO
#endif


void
PrintFormat(const media_format &format)
{
	char s[200];
	string_for_format(format, s, sizeof(s));
	printf("%s\n", s);
}


void
PrintFormat(const media_output &output)
{
	PrintFormat(output.format);
}


static status_t
GetHeaderFormatAc3Audio(media_format *out_format, const uint8 *header, size_t size)
{
	printf("GetHeaderFormatAc3Audio\n");

	status_t status;
	media_format_description desc;
//	desc.family = B_WAV_FORMAT_FAMILY;
//	desc.u.wav.codec = 0x2000;
	desc.family = B_MISC_FORMAT_FAMILY;
	desc.u.misc.file_format = 'ffmp';
	desc.u.misc.codec = AV_CODEC_ID_AC3;

	BMediaFormats formats;	
	status = formats.InitCheck();
	if (status) {
		printf("formats.InitCheck failed, error %lu\n", status);
		return status;
	}
	
	status = formats.GetFormatFor(desc, out_format);
	if (status) {
		printf("formats.GetFormatFor failed, error %lu\n", status);
		return status;
	}
	
	return B_OK;
}



static status_t
GetHeaderFormatDtsAudio(media_format *out_format, const uint8 *header, size_t size)
{
	printf("GetHeaderFormatDtsAudio: unsupported\n");
	return B_ERROR;
}


static status_t
GetHeaderFormatLpcmAudio(media_format *out_format, const uint8 *header, size_t size)
{
	printf("GetHeaderFormatLpcmAudio: unsupported\n");
	return B_ERROR;
}


static status_t
GetHeaderFormatPrivateStream(media_format *out_format, const uint8 *header, size_t size)
{
	printf("GetHeaderFormatPrivateStream: unsupported, assuming AC3\n");
	return GetHeaderFormatAc3Audio(out_format, header, size);
}


static status_t
GetHeaderFormatMpegAudio(media_format *out_format, const uint8 *header, size_t size)
{
	printf("GetHeaderFormatMpegAudio\n");

	status_t status;
	media_format_description desc;
//	desc.family = B_MPEG_FORMAT_FAMILY;
//	desc.u.mpeg.id = B_MPEG_2_AUDIO_LAYER_2;
	desc.family = B_MISC_FORMAT_FAMILY;
	desc.u.misc.file_format = 'ffmp';
	desc.u.misc.codec = AV_CODEC_ID_MP3;
	
	
	BMediaFormats formats;	
	status = formats.InitCheck();
	if (status) {
		printf("formats.InitCheck failed, error %lu\n", status);
		return status;
	}
	
	status = formats.GetFormatFor(desc, out_format);
	if (status) {
		printf("formats.GetFormatFor failed, error %lu\n", status);
		return status;
	}

	out_format->u.encoded_audio.output.frame_rate = 48000;
	out_format->u.encoded_audio.output.channel_count = 2;
	out_format->u.encoded_audio.output.buffer_size = 1024;
	return B_OK;
}


static status_t
GetHeaderFormatMpegVideo(media_format *out_format, const uint8 *header, size_t size)
{
	printf("GetHeaderFormatMpegVideo\n");

	status_t status;
	media_format_description desc;
//	desc.family = B_MPEG_FORMAT_FAMILY;
//	desc.u.mpeg.id = B_MPEG_2_VIDEO;
	desc.family = B_MISC_FORMAT_FAMILY;
	desc.u.misc.file_format = 'ffmp';
	desc.u.misc.codec = AV_CODEC_ID_MPEG2VIDEO;

	BMediaFormats formats;
	status = formats.InitCheck();
	if (status) {
		printf("formats.InitCheck failed, error %lu\n", status);
		return status;
	}
	
	status = formats.GetFormatFor(desc, out_format);
	if (status) {
		printf("formats.GetFormatFor failed, error %lu\n", status);
		return status;
	}

	return B_OK;
}


status_t
GetHeaderFormat(media_format *out_format, const void *header, size_t size, int stream_id)
{
	const uint8 *h = (const uint8 *)header;
	status_t status;

	printf("GetHeaderFormat: stream_id %02x\n", stream_id);
	printf("inner frame header: "
		   "%02x %02x %02x %02x %02x %02x %02x %02x "
		   "%02x %02x %02x %02x %02x %02x %02x %02x\n",
		   h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7], 
		   h[8], h[9], h[10], h[11], h[12], h[13], h[14], h[15]);

	if (stream_id >= 0x80 && stream_id <= 0x87)
		status = GetHeaderFormatAc3Audio(out_format, h, size);
	else if (stream_id >= 0x88 && stream_id <= 0x8F)
		status = GetHeaderFormatDtsAudio(out_format, h, size);
	else if (stream_id >= 0xA0 && stream_id <= 0xA7)
		status = GetHeaderFormatLpcmAudio(out_format, h, size);
	else if (stream_id == 0xBD)
		status = GetHeaderFormatPrivateStream(out_format, h, size);
	else if (stream_id >= 0xC0 && stream_id <= 0xDF)
		status = GetHeaderFormatMpegAudio(out_format, h, size);
	else if (stream_id >= 0xE0 && stream_id <= 0xEF)
		status = GetHeaderFormatMpegVideo(out_format, h, size);
	else {
		printf("GetHeaderFormat: don't know what this stream_id means\n");
		status = B_ERROR;
	}
	
	if (status != B_OK) {
		printf("GetHeaderFormat: failed!\n");
	} else {
		printf("GetHeaderFormat: out_format ");
		PrintFormat(*out_format);
	}
	return status;
}