Home | History | Annotate | Download | only in filters
      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