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 10 namespace media { 11 12 FFmpegH264ToAnnexBBitstreamConverter::FFmpegH264ToAnnexBBitstreamConverter( 13 AVCodecContext* stream_context) 14 : configuration_processed_(false), 15 stream_context_(stream_context) { 16 CHECK(stream_context_); 17 } 18 19 FFmpegH264ToAnnexBBitstreamConverter::~FFmpegH264ToAnnexBBitstreamConverter() {} 20 21 bool FFmpegH264ToAnnexBBitstreamConverter::ConvertPacket(AVPacket* packet) { 22 uint32 output_packet_size = 0; 23 uint32 configuration_size = 0; 24 uint32 io_size = 0; 25 if (packet == NULL) { 26 return false; 27 } 28 29 // Calculate the needed output buffer size. 30 if (!configuration_processed_) { 31 // FFmpeg's AVCodecContext's extradata field contains the Decoder 32 // Specific Information from MP4 headers that contain the H.264 SPS and 33 // PPS members. See ISO/IEC 14496-15 Chapter 5.2.4 34 // AVCDecoderConfigurationRecord for exact specification. 35 // Extradata must be at least 7 bytes long. 36 if (stream_context_->extradata == NULL || 37 stream_context_->extradata_size <= 7) { 38 return false; // Can't go on with conversion without configuration. 39 } 40 configuration_size += converter_.ParseConfigurationAndCalculateSize( 41 stream_context_->extradata, 42 stream_context_->extradata_size); 43 if (configuration_size == 0) { 44 return false; // Not possible to parse the configuration. 45 } 46 } 47 uint32 output_nal_size = 48 converter_.CalculateNeededOutputBufferSize(packet->data, packet->size); 49 if (output_nal_size == 0) { 50 return false; // Invalid input packet. 51 } 52 output_packet_size = configuration_size + output_nal_size; 53 54 // Allocate new packet for the output. 55 AVPacket dest_packet; 56 if (av_new_packet(&dest_packet, output_packet_size) != 0) { 57 return false; // Memory allocation failure. 58 } 59 // This is a bit tricky: since the interface does not allow us to replace 60 // the pointer of the old packet with a new one, we will initially copy the 61 // metadata from old packet to new bigger packet. 62 dest_packet.pts = packet->pts; 63 dest_packet.dts = packet->dts; 64 dest_packet.pos = packet->pos; 65 dest_packet.duration = packet->duration; 66 dest_packet.convergence_duration = packet->convergence_duration; 67 dest_packet.flags = packet->flags; 68 dest_packet.stream_index = packet->stream_index; 69 70 // Process the configuration if not done earlier. 71 if (!configuration_processed_) { 72 if (!converter_.ConvertAVCDecoderConfigToByteStream( 73 stream_context_->extradata, stream_context_->extradata_size, 74 dest_packet.data, &configuration_size)) { 75 return false; // Failed to convert the buffer. 76 } 77 configuration_processed_ = true; 78 } 79 80 // Proceed with the conversion of the actual in-band NAL units, leave room 81 // for configuration in the beginning. 82 io_size = dest_packet.size - configuration_size; 83 if (!converter_.ConvertNalUnitStreamToByteStream( 84 packet->data, packet->size, 85 dest_packet.data + configuration_size, &io_size)) { 86 return false; 87 } 88 89 // At the end we must destroy the old packet. 90 av_free_packet(packet); 91 *packet = dest_packet; // Finally, replace the values in the input packet. 92 93 return true; 94 } 95 96 } // namespace media 97 98