Ticket #551: movenc.c.diff

File movenc.c.diff, 7.9 KB (added by ilevin, 15 years ago)
  • movenc.c

    old new  
    2020 * License along with FFmpeg; if not, write to the Free Software
    2121 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
    2222 */
     23//------------------------------------------------------Modifications History
     24// DATE       DESCRIPTION
     25// 06/09/2011 Resolution update for H264 reimplementation.
     26// 05/27/2011 Added writing 'btrt' bitrate info box in H263
     27// 03/07/2011 Write the AVCodecContext image size values to
     28//            output file.
     29// 02/28/2011 added support for max NAL size
     30// 02/17/2011 Fixed handling of no data AMR frames
     31// 02-22-2011 added support for max bitrate
    2332
    2433#include "movenc.h"
    2534#include "avformat.h"
    … …  
    473482    return updateSize(pb, pos);
    474483}
    475484
    476 static int mov_write_d263_tag(ByteIOContext *pb)
     485/* Writes optional H263 specific 'bitr' box */
     486static int mov_write_bitr_tag(ByteIOContext *pb, MOVTrack *track)
    477487{
    478     put_be32(pb, 0xf); /* size */
     488    put_be32(pb, 16);
     489    put_tag(pb, "bitr");
     490
     491    if( (track->enc->rc_max_rate != track->enc->rc_min_rate) ||
     492        (track->enc->rc_min_rate==0) )
     493        put_be32(pb, 0); // vbr
     494    else
     495        put_be32(pb, track->enc->rc_max_rate); // avg bitrate
     496
     497    put_be32(pb, track->enc->rc_max_rate);
     498   
     499    return 16;
     500}
     501
     502static int mov_write_d263_tag(ByteIOContext *pb, MOVTrack *track)
     503{
     504    int64_t pos = url_ftell(pb);
     505
     506    put_be32(pb, 0); /* size placeholder */
    479507    put_tag(pb, "d263");
    480508    put_tag(pb, "FFMP");
    481509    put_byte(pb, 0); /* decoder version */
    482510    /* FIXME use AVCodecContext level/profile, when encoder will set values */
    483511    put_byte(pb, 0xa); /* level */
    484512    put_byte(pb, 0); /* profile */
    485     return 0xf;
     513
     514    /* Write optional H263 specific 'bitr' box, which holds
     515       the bitrate info */
     516    mov_write_bitr_tag(pb, track);
     517
     518    return updateSize(pb, pos);
    486519}
    487520
    488521/* TODO: No idea about these values */
    … …  
    744777    return updateSize(pb, pos);
    745778}
    746779
     780// Write the optional MP4 'btrt' box, in H264 case it comes after avcC
     781// inside avc1. Not suitable for H263, which has its own special 'bitr' box.
     782static int mov_write_btrt_tag(ByteIOContext *pb, MOVTrack *track)
     783{
     784    put_be32(pb, 20);
     785    put_tag(pb, "btrt");
     786    put_be32(pb,  track->enc->rc_buffer_size); // Buffersize DB (32 bits)
     787
     788    put_be32(pb, track->enc->rc_max_rate);
     789    if( (track->enc->rc_max_rate != track->enc->rc_min_rate) ||
     790        (track->enc->rc_min_rate==0) )
     791        put_be32(pb, 0); // vbr
     792    else
     793        put_be32(pb, track->enc->rc_max_rate); // avg bitrate
     794
     795    return 20;
     796}
     797
     798// Write the non-standard 'cmvt' box at "stsd" level
     799static int mov_write_cmvt_tag(ByteIOContext *pb, MOVTrack *track, AVStream *st)
     800{
     801    AVMetadataTag *pAVMetadataTag = NULL;
     802    int nNalSize = 0;
     803    if ( NULL == st )
     804    {
     805        av_log(NULL, AV_LOG_ERROR,
     806             "mov_write_cmvt_tag() st is NULL !!!\n");
     807        return 0;
     808    }
     809    if ( NULL ==st->metadata )
     810    {
     811        av_log(NULL, AV_LOG_ERROR,
     812             "mov_write_cmvt_tag() st->metadata is NULL !!!\n");
     813    }
     814    pAVMetadataTag = av_metadata_get(st->metadata, "NALSize", NULL, 0);
     815
     816    if (!pAVMetadataTag || !strlen(pAVMetadataTag->value))
     817    {
     818        av_log(NULL, AV_LOG_ERROR,
     819            "mov_write_cmvt_tag() pAVMetadataTag is NULL or bad value\n");
     820        return 0;
     821    }
     822    nNalSize = atoi(pAVMetadataTag->value);
     823    put_be32(pb, 20);
     824    put_tag(pb, "cmvt");
     825    put_be32(pb, nNalSize); // NAL size (32 bits)
     826    put_be32(pb, 0); // empty
     827    put_be32(pb, 0); // empty
     828    return 20;
     829}
     830
    747831static int mov_write_video_tag(ByteIOContext *pb, MOVTrack *track)
    748832{
    749833    int64_t pos = url_ftell(pb);
    … …  
    771855        put_be32(pb, 0); /* Reserved */
    772856        put_be32(pb, 0); /* Reserved */
    773857    }
    774     put_be16(pb, track->enc->width); /* Video width */
    775     put_be16(pb, track->height); /* Video height */
     858
     859    put_be16(pb, track->enc->width); /* Video width - for it 'enc' is always used */
     860    /* Video height - in most cases should be the same as 'enc'.
     861       If explicitly updating picture size after mov_write_header,
     862       make sure to call cms_mov_update_dimensions(). */
     863    put_be16(pb, track->height);
     864
    776865    put_be32(pb, 0x00480000); /* Horizontal resolution 72dpi */
    777866    put_be32(pb, 0x00480000); /* Vertical resolution 72dpi */
    778867    put_be32(pb, 0); /* Data size (= 0) */
    … …  
    792881    put_be16(pb, 0xffff); /* Reserved */
    793882    if(track->tag == MKTAG('m','p','4','v'))
    794883        mov_write_esds_tag(pb, track);
    795     else if(track->enc->codec_id == CODEC_ID_H263)
    796         mov_write_d263_tag(pb);
     884    else if (track->enc->codec_id == CODEC_ID_H263)
     885    {
     886        mov_write_d263_tag(pb, track);
     887    }
    797888    else if(track->enc->codec_id == CODEC_ID_SVQ3)
    798889        mov_write_svq3_tag(pb);
    799890    else if(track->enc->codec_id == CODEC_ID_DNXHD)
    800891        mov_write_avid_tag(pb, track);
    801892    else if(track->enc->codec_id == CODEC_ID_H264) {
    802893        mov_write_avcc_tag(pb, track);
     894        mov_write_btrt_tag(pb, track);
    803895        if(track->mode == MODE_IPOD)
    804896            mov_write_uuid_tag_ipod(pb);
    805897    } else if(track->vosLen > 0)
    … …  
    12661358    if (track->tref_tag)
    12671359        mov_write_tref_tag(pb, track);
    12681360    mov_write_mdia_tag(pb, track);
     1361    if ( st && st->codec && CODEC_ID_H264 == st->codec->codec_id)
     1362        mov_write_cmvt_tag(pb, track, st);
    12691363    if (track->mode == MODE_PSP)
    12701364        mov_write_uuid_tag_psp(pb,track);  // PSP Movies require this uuid box
    12711365    if (track->tag == MKTAG('r','t','p',' '))
    … …  
    21802281    return res;
    21812282}
    21822283
     2284/* That function is used to update video resolution after mov_write_header. */
     2285int cms_mov_update_dimensions(AVFormatContext *s, int streamNumber,
     2286                              unsigned int imageWidthInPixels,
     2287                              unsigned int imageHeightInPixels,
     2288                              AVRational *sampleAspectRatio)
     2289{
     2290    MOVMuxContext *mov;
     2291    MOVTrack *track;
     2292
     2293    if ((s == NULL) || (streamNumber >= s->nb_streams))
     2294    {
     2295        // inexistent stream
     2296        av_log(s, AV_LOG_ERROR, "Stream %d does not exist\n",
     2297               streamNumber);
     2298        return -1;
     2299    }
     2300
     2301    if (s->streams[streamNumber]->codec->codec_type != AVMEDIA_TYPE_VIDEO)
     2302    {
     2303        // We only update resolution for video streams
     2304        av_log(s, AV_LOG_ERROR, "Stream %d is not video\n",
     2305               streamNumber);
     2306        return -2;
     2307    }
     2308
     2309    // Internal, .mov specific parts
     2310    mov = s->priv_data;
     2311
     2312    if (!mov)
     2313    {
     2314        av_log(s, AV_LOG_ERROR, "MOV context does not exist\n");
     2315        return -3;
     2316    }
     2317
     2318    track = &mov->tracks[streamNumber];
     2319
     2320    if (!track)
     2321    {
     2322        av_log(s, AV_LOG_ERROR, "MOV track %d does not exist\n",
     2323               streamNumber);
     2324        return -4;
     2325    }
     2326
     2327    /* Special handling for D-10/IMX */
     2328    if (track->tag == MKTAG('m','x','3','p') || track->tag == MKTAG('m','x','3','n') ||
     2329        track->tag == MKTAG('m','x','4','p') || track->tag == MKTAG('m','x','4','n') ||
     2330        track->tag == MKTAG('m','x','5','p') || track->tag == MKTAG('m','x','5','n'))
     2331    {
     2332        if ((imageWidthInPixels != 720) ||
     2333            ((imageHeightInPixels != 608) && (imageHeightInPixels != 512)))
     2334        {
     2335           av_log(s, AV_LOG_ERROR, "D-10/IMX must use 720x608 or 720x512 video resolution\n");
     2336           return -5;
     2337        }
     2338       
     2339        track->height = track->tag>>24 == 'n' ? 486 : 576;
     2340    }
     2341    else
     2342    {
     2343        track->height = imageHeightInPixels;
     2344    }
     2345
     2346    // High level (visible outside) parts
     2347    s->streams[streamNumber]->codec->width = imageWidthInPixels;
     2348    s->streams[streamNumber]->codec->height = imageHeightInPixels;
     2349    s->streams[streamNumber]->sample_aspect_ratio = *sampleAspectRatio;
     2350    s->streams[streamNumber]->codec->sample_aspect_ratio = *sampleAspectRatio;
     2351
     2352    return 0;
     2353}
     2354
    21832355#if CONFIG_MOV_MUXER
    21842356AVOutputFormat mov_muxer = {
    21852357    "mov",