| 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 | |
| | 502 | static 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 */ |
| | 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. |
| | 782 | static 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 |
| | 799 | static 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 | |
| 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 | |
| | 2284 | /* That function is used to update video resolution after mov_write_header. */ |
| | 2285 | int 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 | |