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 
     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