1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "media/filters/ffmpeg_h264_to_annex_b_bitstream_converter.h" 6 7 #include "base/logging.h" 8 #include "media/ffmpeg/ffmpeg_common.h" 9 #include "media/formats/mp4/box_definitions.h" 10 11 namespace media { 12 13 FFmpegH264ToAnnexBBitstreamConverter::FFmpegH264ToAnnexBBitstreamConverter( 14 AVCodecContext* stream_context) 15 : configuration_processed_(false), 16 stream_context_(stream_context) { 17 CHECK(stream_context_); 18 } 19 20 FFmpegH264ToAnnexBBitstreamConverter::~FFmpegH264ToAnnexBBitstreamConverter() {} 21 22 bool FFmpegH264ToAnnexBBitstreamConverter::ConvertPacket(AVPacket* packet) { 23 scoped_ptr<mp4::AVCDecoderConfigurationRecord> avc_config; 24 25 if (packet == NULL || !packet->data) 26 return false; 27 28 // Calculate the needed output buffer size. 29 if (!configuration_processed_) { 30 if (!stream_context_->extradata || stream_context_->extradata_size <= 0) 31 return false; 32 33 avc_config.reset(new mp4::AVCDecoderConfigurationRecord()); 34 35 if (!converter_.ParseConfiguration( 36 stream_context_->extradata, 37 stream_context_->extradata_size, 38 avc_config.get())) { 39 return false; 40 } 41 } 42 43 uint32 output_packet_size = converter_.CalculateNeededOutputBufferSize( 44 packet->data, packet->size, avc_config.get()); 45 46 if (output_packet_size == 0) 47 return false; // Invalid input packet. 48 49 // Allocate new packet for the output. 50 AVPacket dest_packet; 51 if (av_new_packet(&dest_packet, output_packet_size) != 0) 52 return false; // Memory allocation failure. 53 54 // This is a bit tricky: since the interface does not allow us to replace 55 // the pointer of the old packet with a new one, we will initially copy the 56 // metadata from old packet to new bigger packet. 57 av_packet_copy_props(&dest_packet, packet); 58 59 // Proceed with the conversion of the actual in-band NAL units, leave room 60 // for configuration in the beginning. 61 uint32 io_size = dest_packet.size; 62 if (!converter_.ConvertNalUnitStreamToByteStream( 63 packet->data, packet->size, 64 avc_config.get(), 65 dest_packet.data, &io_size)) { 66 return false; 67 } 68 69 if (avc_config) 70 configuration_processed_ = true; 71 72 // At the end we must destroy the old packet. 73 av_free_packet(packet); 74 *packet = dest_packet; // Finally, replace the values in the input packet. 75 76 return true; 77 } 78 79 } // namespace media 80