bool BMediaTrack::SetupFormatTranslation(const media_format &from, media_format *to) { _plugin_manager.DestroyDecoder(fRawDecoder); fRawDecoder = NULL; #ifdef TRACE_MEDIA_TRACK char s[200]; string_for_format(from, s, sizeof(s)); printf("BMediaTrack::SetupFormatTranslation: from: %s\n", s); #endif status_t res = _plugin_manager.CreateDecoder(&fRawDecoder, from); if (res != B_OK) { ERROR("BMediaTrack::SetupFormatTranslation: CreateDecoder failed\n"); return false; } // XXX video? int buffer_size = from.u.raw_audio.buffer_size; int frame_size = (from.u.raw_audio.format & 15) * from.u.raw_audio.channel_count; media_format notconstFrom = from; ChunkProvider *chunkProvider = new(std::nothrow) RawDecoderChunkProvider(fDecoder, buffer_size, frame_size); if (!chunkProvider) { ERROR("BMediaTrack::SetupFormatTranslation: can't create chunk " "provider\n"); goto error; } fRawDecoder->SetChunkProvider(chunkProvider); res = fRawDecoder->Setup(¬constFrom, 0, 0); if (res != B_OK) { ERROR("BMediaTrack::SetupFormatTranslation: Setup failed\n"); goto error; } #ifdef TRACE_MEDIA_TRACK string_for_format(*to, s, sizeof(s)); printf("BMediaTrack::SetupFormatTranslation: to: %s\n", s); #endif res = fRawDecoder->NegotiateOutputFormat(to); if (res != B_OK) { ERROR("BMediaTrack::SetupFormatTranslation: NegotiateOutputFormat " "failed\n"); goto error; } #ifdef TRACE_MEDIA_TRACK string_for_format(*to, s, sizeof(s)); printf("BMediaTrack::SetupFormatTranslation: res: %s\n", s); #endif return true; error: _plugin_manager.DestroyDecoder(fRawDecoder); fRawDecoder = NULL; return false; }
status_t BMediaTrack::DecodedFormat(media_format *inout_format, uint32 flags) { CALLED(); if (!inout_format) return B_BAD_VALUE; if (!fExtractor || !fDecoder) return B_NO_INIT; _plugin_manager.DestroyDecoder(fRawDecoder); fRawDecoder = NULL; #ifdef TRACE_MEDIA_TRACK char s[200]; string_for_format(*inout_format, s, sizeof(s)); printf("BMediaTrack::DecodedFormat: req1: %s\n", s); #endif if ((fWorkaroundFlags & FORCE_RAW_AUDIO) || ((fWorkaroundFlags & IGNORE_ENCODED_AUDIO) && inout_format->type == B_MEDIA_ENCODED_AUDIO)) { inout_format->type = B_MEDIA_RAW_AUDIO; inout_format->u.raw_audio = media_multi_audio_format::wildcard; } if ((fWorkaroundFlags & FORCE_RAW_VIDEO) || ((fWorkaroundFlags & IGNORE_ENCODED_VIDEO) && inout_format->type == B_MEDIA_ENCODED_VIDEO)) { inout_format->type = B_MEDIA_RAW_VIDEO; inout_format->u.raw_video = media_raw_video_format::wildcard; } if (inout_format->type == B_MEDIA_RAW_AUDIO) { if (fWorkaroundFlags & FORCE_RAW_AUDIO_HOST_ENDIAN) inout_format->u.raw_audio.byte_order = B_MEDIA_HOST_ENDIAN; if (fWorkaroundFlags & FORCE_RAW_AUDIO_INT16_FORMAT) inout_format->u.raw_audio.format = media_raw_audio_format::B_AUDIO_SHORT; if (fWorkaroundFlags & FORCE_RAW_AUDIO_INT32_FORMAT) inout_format->u.raw_audio.format = media_raw_audio_format::B_AUDIO_INT; if (fWorkaroundFlags & FORCE_RAW_AUDIO_FLOAT_FORMAT) inout_format->u.raw_audio.format = media_raw_audio_format::B_AUDIO_FLOAT; } #ifdef TRACE_MEDIA_TRACK string_for_format(*inout_format, s, sizeof(s)); printf("BMediaTrack::DecodedFormat: req2: %s\n", s); #endif fFormat = *inout_format; status_t res; res = fDecoder->NegotiateOutputFormat(inout_format); #ifdef TRACE_MEDIA_TRACK string_for_format(*inout_format, s, sizeof(s)); printf("BMediaTrack::DecodedFormat: nego: %s\n", s); #endif if (inout_format->type == 0) debugger("Decoder didn't set output format type"); if (inout_format->type == B_MEDIA_RAW_AUDIO) { if (inout_format->u.raw_audio.byte_order == 0) debugger("Decoder didn't set raw audio output byte order"); if (inout_format->u.raw_audio.format == 0) debugger("Decoder didn't set raw audio output sample format"); if (inout_format->u.raw_audio.buffer_size <= 0) debugger("Decoder didn't set raw audio output buffer size"); } if (inout_format->type == B_MEDIA_RAW_VIDEO) { if (inout_format->u.raw_video.display.format == 0) debugger("Decoder didn't set raw video output color space"); if (inout_format->u.raw_video.display.line_width == 0) debugger("Decoder didn't set raw video output line_width"); if (inout_format->u.raw_video.display.line_count == 0) debugger("Decoder didn't set raw video output line_count"); if (inout_format->u.raw_video.display.bytes_per_row == 0) debugger("Decoder didn't set raw video output bytes_per_row"); } if (0 == (flags & B_MEDIA_DISABLE_FORMAT_TRANSLATION)) { if (fFormat.type == B_MEDIA_RAW_AUDIO && inout_format->type == B_MEDIA_RAW_AUDIO && fFormat.u.raw_audio.format != 0 && fFormat.u.raw_audio.format != inout_format->u.raw_audio.format) { if (SetupFormatTranslation(*inout_format, &fFormat)) { *inout_format = fFormat; } } } fFormat = *inout_format; // string_for_format(*inout_format, s, sizeof(s)); // printf("BMediaTrack::DecodedFormat: res: %s\n", s); return res; }
status_t FlangerNode::validateProposedFormat( const media_format& preferredFormat, media_format& ioProposedFormat) { char formatStr[256]; PRINT(("FlangerNode::validateProposedFormat()\n")); ASSERT(preferredFormat.type == B_MEDIA_RAW_AUDIO); string_for_format(preferredFormat, formatStr, 255); PRINT(("\ttemplate format: %s\n", formatStr)); string_for_format(ioProposedFormat, formatStr, 255); PRINT(("\tproposed format: %s\n", formatStr)); status_t err = B_OK; if(ioProposedFormat.type != B_MEDIA_RAW_AUDIO) { // out of the ballpark ioProposedFormat = preferredFormat; return B_MEDIA_BAD_FORMAT; } // wildcard format media_raw_audio_format& wild = media_raw_audio_format::wildcard; // proposed format media_raw_audio_format& f = ioProposedFormat.u.raw_audio; // template format const media_raw_audio_format& pref = preferredFormat.u.raw_audio; if(pref.frame_rate != wild.frame_rate) { if(f.frame_rate != pref.frame_rate) { if(f.frame_rate != wild.frame_rate) err = B_MEDIA_BAD_FORMAT; f.frame_rate = pref.frame_rate; } } if(pref.channel_count != wild.channel_count) { if(f.channel_count != pref.channel_count) { if(f.channel_count != wild.channel_count) err = B_MEDIA_BAD_FORMAT; f.channel_count = pref.channel_count; } } if(pref.format != wild.format) { if(f.format != pref.format) { if(f.format != wild.format) err = B_MEDIA_BAD_FORMAT; f.format = pref.format; } } if(pref.byte_order != wild.byte_order) { if(f.byte_order != pref.byte_order) { if(f.byte_order != wild.byte_order) err = B_MEDIA_BAD_FORMAT; f.byte_order = pref.byte_order; } } if(pref.buffer_size != wild.buffer_size) { if(f.buffer_size != pref.buffer_size) { if(f.buffer_size != wild.buffer_size) err = B_MEDIA_BAD_FORMAT; f.buffer_size = pref.buffer_size; } } if(err != B_OK) { string_for_format(ioProposedFormat, formatStr, 255); PRINT(( "\tformat conflict; suggesting:\n\tformat %s\n", formatStr)); } return err; }
status_t RawDecoder::NegotiateAudioOutputFormat(media_format *ioDecodedFormat) { char s[1024]; TRACE("RawDecoder::NegotiateAudioOutputFormat enter:\n"); ioDecodedFormat->type = B_MEDIA_RAW_AUDIO; switch (ioDecodedFormat->u.raw_audio.format) { case media_raw_audio_format::B_AUDIO_FLOAT: case media_raw_audio_format::B_AUDIO_SHORT: case media_raw_audio_format::B_AUDIO_UCHAR: case media_raw_audio_format::B_AUDIO_CHAR: ioDecodedFormat->u.raw_audio.valid_bits = 0; break; // we can produce this on request case media_raw_audio_format::B_AUDIO_INT: ioDecodedFormat->u.raw_audio.valid_bits = fInputFormat.u.raw_audio.valid_bits; break; // we can produce this on request default: switch (fInputFormat.u.raw_audio.format & B_AUDIO_FORMAT_MASK) { case media_raw_audio_format::B_AUDIO_SHORT: case media_raw_audio_format::B_AUDIO_UCHAR: case media_raw_audio_format::B_AUDIO_CHAR: ioDecodedFormat->u.raw_audio.format = fInputFormat.u.raw_audio.format & B_AUDIO_FORMAT_MASK; ioDecodedFormat->u.raw_audio.valid_bits = 0; break; case media_raw_audio_format::B_AUDIO_INT: case B_AUDIO_FORMAT_INT24: ioDecodedFormat->u.raw_audio.format = media_raw_audio_format::B_AUDIO_INT; ioDecodedFormat->u.raw_audio.valid_bits = fInputFormat.u.raw_audio.valid_bits; break; case media_raw_audio_format::B_AUDIO_FLOAT: case B_AUDIO_FORMAT_FLOAT64: default: ioDecodedFormat->u.raw_audio.format = media_raw_audio_format::B_AUDIO_FLOAT; ioDecodedFormat->u.raw_audio.valid_bits = 0; break; } break; } ioDecodedFormat->u.raw_audio.frame_rate = fInputFormat.u.raw_audio.frame_rate; ioDecodedFormat->u.raw_audio.channel_count = fInputFormat.u.raw_audio.channel_count; fFrameRate = (int32) ioDecodedFormat->u.raw_audio.frame_rate; fOutputSampleSize = (ioDecodedFormat->u.raw_audio.format & B_AUDIO_FORMAT_SIZE_MASK); fOutputFrameSize = fOutputSampleSize * ioDecodedFormat->u.raw_audio.channel_count; if (ioDecodedFormat->u.raw_audio.byte_order == 0) ioDecodedFormat->u.raw_audio.byte_order = B_MEDIA_HOST_ENDIAN; ioDecodedFormat->u.raw_audio.channel_mask = 0; ioDecodedFormat->u.raw_audio.matrix_mask = 0; ioDecodedFormat->u.raw_audio.buffer_size = fInputFormat.u.raw_audio.buffer_size; // I don't believe we can negotiate the buffer size with the reader // the decoder might use a different buffer for output but it must read all bytes given. // if (ioDecodedFormat->u.raw_audio.buffer_size < 128 || ioDecodedFormat->u.raw_audio.buffer_size > 65536) { // ioDecodedFormat->u.raw_audio.buffer_size = AudioBufferSize( // ioDecodedFormat->u.raw_audio.channel_count, // ioDecodedFormat->u.raw_audio.format, // ioDecodedFormat->u.raw_audio.frame_rate); // } else { // round down to exact multiple of output frame size // ioDecodedFormat->u.raw_audio.buffer_size = (ioDecodedFormat->u.raw_audio.buffer_size / fOutputFrameSize) * fOutputFrameSize; // } fOutputBufferFrameCount = ioDecodedFormat->u.raw_audio.buffer_size / fOutputFrameSize; // setup input swapping function if (fInputFormat.u.raw_audio.byte_order == B_MEDIA_HOST_ENDIAN) { fSwapInput = 0; } else { switch (fInputFormat.u.raw_audio.format & B_AUDIO_FORMAT_MASK) { case B_AUDIO_FORMAT_INT16: fSwapInput = &swap_int16; break; case B_AUDIO_FORMAT_INT24: fSwapInput = &swap_int24; break; case B_AUDIO_FORMAT_INT32: fSwapInput = &swap_int32; break; case B_AUDIO_FORMAT_FLOAT32: fSwapInput = &swap_float32; break; case B_AUDIO_FORMAT_FLOAT64: fSwapInput = &swap_float64; break; case B_AUDIO_FORMAT_UINT8: case B_AUDIO_FORMAT_INT8: fSwapInput = 0; break; default: debugger("RawDecoder::NegotiateAudioOutputFormat unknown input format\n"); break; } } // setup output swapping function if (ioDecodedFormat->u.raw_audio.byte_order == B_MEDIA_HOST_ENDIAN) { fSwapOutput = 0; } else { switch (ioDecodedFormat->u.raw_audio.format) { case B_AUDIO_FORMAT_INT16: fSwapOutput = &swap_int16; break; case B_AUDIO_FORMAT_INT32: fSwapOutput = &swap_int32; break; case B_AUDIO_FORMAT_FLOAT32: fSwapOutput = &swap_float32; break; case B_AUDIO_FORMAT_UINT8: case B_AUDIO_FORMAT_INT8: fSwapOutput = 0; break; default: debugger("RawDecoder::NegotiateAudioOutputFormat unknown output format\n"); break; } } // setup sample conversation function switch (fInputFormat.u.raw_audio.format & B_AUDIO_FORMAT_MASK) { case B_AUDIO_FORMAT_UINT8: switch (ioDecodedFormat->u.raw_audio.format) { case B_AUDIO_FORMAT_UINT8: fConvert = &uint8_to_uint8; break; case B_AUDIO_FORMAT_INT8: fConvert = &uint8_to_int8; break; case B_AUDIO_FORMAT_INT16: fConvert = &uint8_to_int16; break; case B_AUDIO_FORMAT_INT32: fConvert = &uint8_to_int32; break; case B_AUDIO_FORMAT_FLOAT32: fConvert = &uint8_to_float32; break; default: debugger("RawDecoder::NegotiateAudioOutputFormat unknown output format\n"); break; } break; case B_AUDIO_FORMAT_INT8: switch (ioDecodedFormat->u.raw_audio.format) { case B_AUDIO_FORMAT_UINT8: fConvert = &int8_to_uint8; break; case B_AUDIO_FORMAT_INT8: fConvert = &int8_to_int8; break; case B_AUDIO_FORMAT_INT16: fConvert = &int8_to_int16; break; case B_AUDIO_FORMAT_INT32: fConvert = &int8_to_int32; break; case B_AUDIO_FORMAT_FLOAT32: fConvert = &int8_to_float32; break; default: debugger("RawDecoder::NegotiateAudioOutputFormat unknown output format\n"); break; } break; case B_AUDIO_FORMAT_INT16: switch (ioDecodedFormat->u.raw_audio.format) { case B_AUDIO_FORMAT_UINT8: fConvert = &int16_to_uint8; break; case B_AUDIO_FORMAT_INT8: fConvert = &int16_to_int8; break; case B_AUDIO_FORMAT_INT16: fConvert = &int16_to_int16; break; case B_AUDIO_FORMAT_INT32: fConvert = &int16_to_int32; break; case B_AUDIO_FORMAT_FLOAT32: fConvert = &int16_to_float32; break; default: debugger("RawDecoder::NegotiateAudioOutputFormat unknown output format\n"); break; } break; case B_AUDIO_FORMAT_INT24: switch (ioDecodedFormat->u.raw_audio.format) { case B_AUDIO_FORMAT_UINT8: fConvert = &int24_to_uint8; break; case B_AUDIO_FORMAT_INT8: fConvert = &int24_to_int8; break; case B_AUDIO_FORMAT_INT16: fConvert = &int24_to_int16; break; case B_AUDIO_FORMAT_INT32: fConvert = &int24_to_int32; break; case B_AUDIO_FORMAT_FLOAT32: fConvert = &int24_to_float32; break; default: debugger("RawDecoder::NegotiateAudioOutputFormat unknown output format\n"); break; } break; case B_AUDIO_FORMAT_INT32: switch (ioDecodedFormat->u.raw_audio.format) { case B_AUDIO_FORMAT_UINT8: fConvert = &int32_to_uint8; break; case B_AUDIO_FORMAT_INT8: fConvert = &int32_to_int8; break; case B_AUDIO_FORMAT_INT16: fConvert = &int32_to_int16; break; case B_AUDIO_FORMAT_INT32: fConvert = &int32_to_int32; break; case B_AUDIO_FORMAT_FLOAT32: fConvert = &int32_to_float32; break; default: debugger("RawDecoder::NegotiateAudioOutputFormat unknown output format\n"); break; } break; case B_AUDIO_FORMAT_FLOAT32: switch (ioDecodedFormat->u.raw_audio.format) { case B_AUDIO_FORMAT_UINT8: fConvert = &float32_to_uint8; break; case B_AUDIO_FORMAT_INT8: fConvert = &float32_to_int8; break; case B_AUDIO_FORMAT_INT16: fConvert = &float32_to_int16; break; case B_AUDIO_FORMAT_INT32: fConvert = &float32_to_int32; break; case B_AUDIO_FORMAT_FLOAT32: fConvert = &float32_to_float32; break; default: debugger("RawDecoder::NegotiateAudioOutputFormat unknown output format\n"); break; } break; case B_AUDIO_FORMAT_FLOAT64: switch (ioDecodedFormat->u.raw_audio.format) { case B_AUDIO_FORMAT_UINT8: fConvert = &float64_to_uint8; break; case B_AUDIO_FORMAT_INT8: fConvert = &float64_to_int8; break; case B_AUDIO_FORMAT_INT16: fConvert = &float64_to_int16; break; case B_AUDIO_FORMAT_INT32: fConvert = &float64_to_int32; break; case B_AUDIO_FORMAT_FLOAT32: fConvert = &float64_to_float32; break; default: debugger("RawDecoder::NegotiateAudioOutputFormat unknown output format\n"); break; } break; default: debugger("RawDecoder::NegotiateAudioOutputFormat unknown input format\n"); break; } fChunkBuffer = 0; fChunkSize = 0; fStartTime = 0; string_for_format(*ioDecodedFormat, s, sizeof(s)); TRACE("RawDecoder::NegotiateAudioOutputFormat leave: %s\n", s); if (ioDecodedFormat->type == 0) debugger("RawDecoder::NegotiateAudioOutputFormat ioDecodedFormat->type == 0"); /* TRACE("fFrameRate %ld\n", fFrameRate); TRACE("fInputFrameSize %ld\n", fInputFrameSize); TRACE("fOutputFrameSize %ld\n", fOutputFrameSize); TRACE("fInputSampleSize %ld\n", fInputSampleSize); TRACE("fOutputSampleSize %ld\n", fOutputSampleSize); TRACE("fOutputBufferFrameCount %ld\n", fOutputBufferFrameCount); TRACE("fSwapInput %p\n", fSwapInput); TRACE("fConvert %p\n", fConvert); TRACE("fSwapOutput %p\n", fSwapOutput); */ return B_OK; }
status_t AVFormatReader::Stream::Init(int32 virtualIndex) { TRACE("AVFormatReader::Stream::Init(%ld)\n", virtualIndex); status_t ret = StreamBase::Init(virtualIndex); if (ret != B_OK) return ret; // Get a pointer to the AVCodecContext for the stream at streamIndex. AVCodecContext* codecContext = fStream->codec; #if 0 // stippi: Here I was experimenting with the question if some fields of the // AVCodecContext change (or get filled out at all), if the AVCodec is opened. class CodecOpener { public: CodecOpener(AVCodecContext* context) { fCodecContext = context; AVCodec* codec = avcodec_find_decoder(context->codec_id); fCodecOpen = avcodec_open(context, codec) >= 0; if (!fCodecOpen) TRACE(" failed to open the codec!\n"); } ~CodecOpener() { if (fCodecOpen) avcodec_close(fCodecContext); } private: AVCodecContext* fCodecContext; bool fCodecOpen; } codecOpener(codecContext); #endif // initialize the media_format for this stream media_format* format = &fFormat; memset(format, 0, sizeof(media_format)); media_format_description description; // Set format family and type depending on codec_type of the stream. switch (codecContext->codec_type) { case AVMEDIA_TYPE_AUDIO: if ((codecContext->codec_id >= CODEC_ID_PCM_S16LE) && (codecContext->codec_id <= CODEC_ID_PCM_U8)) { TRACE(" raw audio\n"); format->type = B_MEDIA_RAW_AUDIO; description.family = B_ANY_FORMAT_FAMILY; // This will then apparently be handled by the (built into // BMediaTrack) RawDecoder. } else { TRACE(" encoded audio\n"); format->type = B_MEDIA_ENCODED_AUDIO; description.family = B_MISC_FORMAT_FAMILY; description.u.misc.file_format = 'ffmp'; } break; case AVMEDIA_TYPE_VIDEO: TRACE(" encoded video\n"); format->type = B_MEDIA_ENCODED_VIDEO; description.family = B_MISC_FORMAT_FAMILY; description.u.misc.file_format = 'ffmp'; break; default: TRACE(" unknown type\n"); format->type = B_MEDIA_UNKNOWN_TYPE; return B_ERROR; break; } if (format->type == B_MEDIA_RAW_AUDIO) { // We cannot describe all raw-audio formats, some are unsupported. switch (codecContext->codec_id) { case CODEC_ID_PCM_S16LE: format->u.raw_audio.format = media_raw_audio_format::B_AUDIO_SHORT; format->u.raw_audio.byte_order = B_MEDIA_LITTLE_ENDIAN; break; case CODEC_ID_PCM_S16BE: format->u.raw_audio.format = media_raw_audio_format::B_AUDIO_SHORT; format->u.raw_audio.byte_order = B_MEDIA_BIG_ENDIAN; break; case CODEC_ID_PCM_U16LE: // format->u.raw_audio.format // = media_raw_audio_format::B_AUDIO_USHORT; // format->u.raw_audio.byte_order // = B_MEDIA_LITTLE_ENDIAN; return B_NOT_SUPPORTED; break; case CODEC_ID_PCM_U16BE: // format->u.raw_audio.format // = media_raw_audio_format::B_AUDIO_USHORT; // format->u.raw_audio.byte_order // = B_MEDIA_BIG_ENDIAN; return B_NOT_SUPPORTED; break; case CODEC_ID_PCM_S8: format->u.raw_audio.format = media_raw_audio_format::B_AUDIO_CHAR; break; case CODEC_ID_PCM_U8: format->u.raw_audio.format = media_raw_audio_format::B_AUDIO_UCHAR; break; default: return B_NOT_SUPPORTED; break; } } else { if (description.family == B_MISC_FORMAT_FAMILY) description.u.misc.codec = codecContext->codec_id; BMediaFormats formats; status_t status = formats.GetFormatFor(description, format); if (status < B_OK) TRACE(" formats.GetFormatFor() error: %s\n", strerror(status)); format->user_data_type = B_CODEC_TYPE_INFO; *(uint32*)format->user_data = codecContext->codec_tag; format->user_data[4] = 0; } format->require_flags = 0; format->deny_flags = B_MEDIA_MAUI_UNDEFINED_FLAGS; switch (format->type) { case B_MEDIA_RAW_AUDIO: format->u.raw_audio.frame_rate = (float)codecContext->sample_rate; format->u.raw_audio.channel_count = codecContext->channels; format->u.raw_audio.channel_mask = codecContext->channel_layout; format->u.raw_audio.byte_order = avformat_to_beos_byte_order(codecContext->sample_fmt); format->u.raw_audio.format = avformat_to_beos_format(codecContext->sample_fmt); format->u.raw_audio.buffer_size = 0; // Read one packet and mark it for later re-use. (So our first // GetNextChunk() call does not read another packet.) if (_NextPacket(true) == B_OK) { TRACE(" successfully determined audio buffer size: %d\n", fPacket.size); format->u.raw_audio.buffer_size = fPacket.size; } break; case B_MEDIA_ENCODED_AUDIO: format->u.encoded_audio.bit_rate = codecContext->bit_rate; format->u.encoded_audio.frame_size = codecContext->frame_size; // Fill in some info about possible output format format->u.encoded_audio.output = media_multi_audio_format::wildcard; format->u.encoded_audio.output.frame_rate = (float)codecContext->sample_rate; // Channel layout bits match in Be API and FFmpeg. format->u.encoded_audio.output.channel_count = codecContext->channels; format->u.encoded_audio.multi_info.channel_mask = codecContext->channel_layout; format->u.encoded_audio.output.byte_order = avformat_to_beos_byte_order(codecContext->sample_fmt); format->u.encoded_audio.output.format = avformat_to_beos_format(codecContext->sample_fmt); if (codecContext->block_align > 0) { format->u.encoded_audio.output.buffer_size = codecContext->block_align; } else { format->u.encoded_audio.output.buffer_size = codecContext->frame_size * codecContext->channels * (format->u.encoded_audio.output.format & media_raw_audio_format::B_AUDIO_SIZE_MASK); } break; case B_MEDIA_ENCODED_VIDEO: // TODO: Specifying any of these seems to throw off the format matching // later on. // format->u.encoded_video.avg_bit_rate = codecContext->bit_rate; // format->u.encoded_video.max_bit_rate = codecContext->bit_rate // + codecContext->bit_rate_tolerance; // format->u.encoded_video.encoding // = media_encoded_video_format::B_ANY; // format->u.encoded_video.frame_size = 1; // format->u.encoded_video.forward_history = 0; // format->u.encoded_video.backward_history = 0; format->u.encoded_video.output.field_rate = FrameRate(); format->u.encoded_video.output.interlace = 1; format->u.encoded_video.output.first_active = 0; format->u.encoded_video.output.last_active = codecContext->height - 1; // TODO: Maybe libavformat actually provides that info // somewhere... format->u.encoded_video.output.orientation = B_VIDEO_TOP_LEFT_RIGHT; // Calculate the display aspect ratio AVRational displayAspectRatio; if (codecContext->sample_aspect_ratio.num != 0) { av_reduce(&displayAspectRatio.num, &displayAspectRatio.den, codecContext->width * codecContext->sample_aspect_ratio.num, codecContext->height * codecContext->sample_aspect_ratio.den, 1024 * 1024); TRACE(" pixel aspect ratio: %d/%d, " "display aspect ratio: %d/%d\n", codecContext->sample_aspect_ratio.num, codecContext->sample_aspect_ratio.den, displayAspectRatio.num, displayAspectRatio.den); } else { av_reduce(&displayAspectRatio.num, &displayAspectRatio.den, codecContext->width, codecContext->height, 1024 * 1024); TRACE(" no display aspect ratio (%d/%d)\n", displayAspectRatio.num, displayAspectRatio.den); } format->u.encoded_video.output.pixel_width_aspect = displayAspectRatio.num; format->u.encoded_video.output.pixel_height_aspect = displayAspectRatio.den; format->u.encoded_video.output.display.format = pixfmt_to_colorspace(codecContext->pix_fmt); format->u.encoded_video.output.display.line_width = codecContext->width; format->u.encoded_video.output.display.line_count = codecContext->height; TRACE(" width/height: %d/%d\n", codecContext->width, codecContext->height); format->u.encoded_video.output.display.bytes_per_row = 0; format->u.encoded_video.output.display.pixel_offset = 0; format->u.encoded_video.output.display.line_offset = 0; format->u.encoded_video.output.display.flags = 0; // TODO break; default: // This is an unknown format to us. break; } // Add the meta data, if any if (codecContext->extradata_size > 0) { format->SetMetaData(codecContext->extradata, codecContext->extradata_size); TRACE(" extradata: %p\n", format->MetaData()); } TRACE(" extradata_size: %d\n", codecContext->extradata_size); // TRACE(" intra_matrix: %p\n", codecContext->intra_matrix); // TRACE(" inter_matrix: %p\n", codecContext->inter_matrix); // TRACE(" get_buffer(): %p\n", codecContext->get_buffer); // TRACE(" release_buffer(): %p\n", codecContext->release_buffer); #ifdef TRACE_AVFORMAT_READER char formatString[512]; if (string_for_format(*format, formatString, sizeof(formatString))) TRACE(" format: %s\n", formatString); uint32 encoding = format->Encoding(); TRACE(" encoding '%.4s'\n", (char*)&encoding); #endif return B_OK; }
status_t AVCodecDecoder::Setup(media_format* ioEncodedFormat, const void* infoBuffer, size_t infoSize) { if (ioEncodedFormat->type != B_MEDIA_ENCODED_AUDIO && ioEncodedFormat->type != B_MEDIA_ENCODED_VIDEO) return B_ERROR; fIsAudio = (ioEncodedFormat->type == B_MEDIA_ENCODED_AUDIO); TRACE("[%c] AVCodecDecoder::Setup()\n", fIsAudio?('a'):('v')); #ifdef TRACE_AV_CODEC char buffer[1024]; string_for_format(*ioEncodedFormat, buffer, sizeof(buffer)); TRACE("[%c] input_format = %s\n", fIsAudio?('a'):('v'), buffer); TRACE("[%c] infoSize = %ld\n", fIsAudio?('a'):('v'), infoSize); TRACE("[%c] user_data_type = %08lx\n", fIsAudio?('a'):('v'), ioEncodedFormat->user_data_type); TRACE("[%c] meta_data_size = %ld\n", fIsAudio?('a'):('v'), ioEncodedFormat->MetaDataSize()); #endif media_format_description description; if (BMediaFormats().GetCodeFor(*ioEncodedFormat, B_MISC_FORMAT_FAMILY, &description) == B_OK) { if (description.u.misc.file_format != 'ffmp') return B_NOT_SUPPORTED; fCodec = avcodec_find_decoder(static_cast<CodecID>( description.u.misc.codec)); if (fCodec == NULL) { TRACE(" unable to find the correct FFmpeg " "decoder (id = %lu)\n", description.u.misc.codec); return B_ERROR; } TRACE(" found decoder %s\n", fCodec->name); const void* extraData = infoBuffer; fExtraDataSize = infoSize; if (description.family == B_WAV_FORMAT_FAMILY && infoSize >= sizeof(wave_format_ex)) { TRACE(" trying to use wave_format_ex\n"); // Special case extra data in B_WAV_FORMAT_FAMILY const wave_format_ex* waveFormatData = (const wave_format_ex*)infoBuffer; size_t waveFormatSize = infoSize; if (waveFormatData != NULL && waveFormatSize > 0) { fBlockAlign = waveFormatData->block_align; TRACE(" found block align: %d\n", fBlockAlign); fExtraDataSize = waveFormatData->extra_size; // skip the wave_format_ex from the extra data. extraData = waveFormatData + 1; } } else { if (fIsAudio) { fBlockAlign = ioEncodedFormat->u.encoded_audio.output .buffer_size; TRACE(" using buffer_size as block align: %d\n", fBlockAlign); } } if (extraData != NULL && fExtraDataSize > 0) { TRACE("AVCodecDecoder: extra data size %ld\n", infoSize); delete[] fExtraData; fExtraData = new(std::nothrow) char[fExtraDataSize]; if (fExtraData != NULL) memcpy(fExtraData, infoBuffer, fExtraDataSize); else fExtraDataSize = 0; } fInputFormat = *ioEncodedFormat; return B_OK; } else { TRACE("AVCodecDecoder: BMediaFormats().GetCodeFor() failed.\n"); } printf("AVCodecDecoder::Setup failed!\n"); return B_ERROR; }