LCOV - code coverage report
Current view: top level - src/tests/api - api-codec-param-test.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 106 130 81.5 %
Date: 2017-01-28 02:43:52 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2015 Matthieu Bouron <matthieu.bouron stupeflix.com>
       3             :  *
       4             :  * Permission is hereby granted, free of charge, to any person obtaining a copy
       5             :  * of this software and associated documentation files (the "Software"), to deal
       6             :  * in the Software without restriction, including without limitation the rights
       7             :  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       8             :  * copies of the Software, and to permit persons to whom the Software is
       9             :  * furnished to do so, subject to the following conditions:
      10             :  *
      11             :  * The above copyright notice and this permission notice shall be included in
      12             :  * all copies or substantial portions of the Software.
      13             :  *
      14             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      15             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      16             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      17             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      18             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      19             :  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      20             :  * THE SOFTWARE.
      21             :  */
      22             : 
      23             : #include <stdio.h>
      24             : #include "libavformat/avformat.h"
      25             : #include "libavutil/pixdesc.h"
      26             : #include "libavcodec/internal.h"
      27             : #include "libavutil/avassert.h"
      28             : #include "libavutil/opt.h"
      29             : 
      30           4 : static int try_decode_video_frame(AVCodecContext *codec_ctx, AVPacket *pkt, int decode)
      31             : {
      32           4 :     int ret = 0;
      33           4 :     int got_frame = 0;
      34           4 :     AVFrame *frame = NULL;
      35           4 :     int skip_frame = codec_ctx->skip_frame;
      36             : 
      37           4 :     if (!avcodec_is_open(codec_ctx)) {
      38           4 :         const AVCodec *codec = avcodec_find_decoder(codec_ctx->codec_id);
      39             : 
      40           4 :         ret = avcodec_open2(codec_ctx, codec, NULL);
      41           4 :         if (ret < 0) {
      42           0 :             av_log(codec_ctx, AV_LOG_ERROR, "Failed to open codec\n");
      43           0 :             goto end;
      44             :         }
      45             :     }
      46             : 
      47           4 :     frame = av_frame_alloc();
      48           4 :     if (!frame) {
      49           0 :         av_log(NULL, AV_LOG_ERROR, "Failed to allocate frame\n");
      50           0 :         goto end;
      51             :     }
      52             : 
      53           4 :     if (!decode && avpriv_codec_get_cap_skip_frame_fill_param(codec_ctx->codec)) {
      54           2 :         codec_ctx->skip_frame = AVDISCARD_ALL;
      55             :     }
      56             : 
      57             :     do {
      58           4 :         ret = avcodec_decode_video2(codec_ctx, frame, &got_frame, pkt);
      59           4 :         av_assert0(decode || (!decode && !got_frame));
      60           4 :         if (ret < 0)
      61           0 :             break;
      62           4 :         pkt->data += ret;
      63           4 :         pkt->size -= ret;
      64             : 
      65           4 :         if (got_frame) {
      66           2 :             break;
      67             :         }
      68           2 :     } while (pkt->size > 0);
      69             : 
      70             : end:
      71           4 :     codec_ctx->skip_frame = skip_frame;
      72             : 
      73           4 :     av_frame_free(&frame);
      74           4 :     return ret;
      75             : }
      76             : 
      77           4 : static int find_video_stream_info(AVFormatContext *fmt_ctx, int decode)
      78             : {
      79           4 :     int ret = 0;
      80           4 :     int i, done = 0;
      81             :     AVPacket pkt;
      82             : 
      83           4 :     av_init_packet(&pkt);
      84             : 
      85          12 :     while (!done) {
      86           4 :         AVCodecContext *codec_ctx = NULL;
      87             :         AVStream *st;
      88             : 
      89           4 :         if ((ret = av_read_frame(fmt_ctx, &pkt)) < 0) {
      90           0 :             av_log(fmt_ctx, AV_LOG_ERROR, "Failed to read frame\n");
      91           0 :             goto end;
      92             :         }
      93             : 
      94           4 :         st = fmt_ctx->streams[pkt.stream_index];
      95           4 :         codec_ctx = st->codec;
      96             : 
      97             :         /* Writing to AVStream.codec_info_nb_frames must not be done by
      98             :          * user applications. It is done here for testing purposing as
      99             :          * find_video_stream_info tries to mimic avformat_find_stream_info
     100             :          * which writes to this field.
     101             :          * */
     102           8 :         if (codec_ctx->codec_type != AVMEDIA_TYPE_VIDEO ||
     103           4 :             st->codec_info_nb_frames++ > 0) {
     104           0 :             av_packet_unref(&pkt);
     105           0 :             continue;
     106             :         }
     107             : 
     108           4 :         ret = try_decode_video_frame(codec_ctx, &pkt, decode);
     109           4 :         if (ret < 0) {
     110           0 :             av_log(fmt_ctx, AV_LOG_ERROR, "Failed to decode video frame\n");
     111           0 :             goto end;
     112             :         }
     113             : 
     114           4 :         av_packet_unref(&pkt);
     115             : 
     116             :         /* check if all video streams have demuxed a packet */
     117           4 :         done = 1;
     118           8 :         for (i = 0; i < fmt_ctx->nb_streams; i++) {
     119           4 :             st = fmt_ctx->streams[i];
     120           4 :             codec_ctx = st->codec;
     121             : 
     122           4 :             if (codec_ctx->codec_type != AVMEDIA_TYPE_VIDEO)
     123           0 :                 continue;
     124             : 
     125           4 :             done &= st->codec_info_nb_frames > 0;
     126             :         }
     127             :     }
     128             : 
     129             : end:
     130           4 :     av_packet_unref(&pkt);
     131             : 
     132             :     /* close all codecs opened in try_decode_video_frame */
     133           8 :     for (i = 0; i < fmt_ctx->nb_streams; i++) {
     134           4 :         AVStream *st = fmt_ctx->streams[i];
     135           4 :         avcodec_close(st->codec);
     136             :     }
     137             : 
     138           4 :     return ret < 0;
     139             : }
     140             : 
     141           4 : static void dump_video_streams(const AVFormatContext *fmt_ctx, int decode)
     142             : {
     143             :     int i;
     144             : 
     145           8 :     for (i = 0; i < fmt_ctx->nb_streams; i++) {
     146           4 :         const AVOption *opt = NULL;
     147           4 :         const AVStream *st = fmt_ctx->streams[i];
     148           4 :         AVCodecContext *codec_ctx = st->codec;
     149             : 
     150           4 :         printf("stream=%d, decode=%d\n", i, decode);
     151        1708 :         while (opt = av_opt_next(codec_ctx, opt)) {
     152             :             uint8_t *str;
     153             : 
     154        1700 :             if (opt->type == AV_OPT_TYPE_CONST)
     155        2140 :                 continue;
     156             : 
     157         632 :             if (!strcmp(opt->name, "frame_number"))
     158           4 :                 continue;
     159             : 
     160         628 :             if (av_opt_get(codec_ctx, opt->name, 0, &str) >= 0) {
     161         628 :                 printf("    %s=%s\n", opt->name, str);
     162         628 :                 av_free(str);
     163             :             }
     164             :         }
     165             :     }
     166           4 : }
     167             : 
     168           4 : static int open_and_probe_video_streams(AVFormatContext **fmt_ctx, const char *filename, int decode)
     169             : {
     170           4 :     int ret = 0;
     171             : 
     172           4 :     ret = avformat_open_input(fmt_ctx, filename, NULL, NULL);
     173           4 :     if (ret < 0) {
     174           0 :         av_log(NULL, AV_LOG_ERROR, "Failed to open input '%s'", filename);
     175           0 :         goto end;
     176             :     }
     177             : 
     178           4 :     ret = find_video_stream_info(*fmt_ctx, decode);
     179           4 :     if (ret < 0) {
     180           0 :         goto end;
     181             :     }
     182             : 
     183           4 :     dump_video_streams(*fmt_ctx, decode);
     184             : 
     185             : end:
     186           4 :     return ret;
     187             : }
     188             : 
     189           2 : static int check_video_streams(const AVFormatContext *fmt_ctx1, const AVFormatContext *fmt_ctx2)
     190             : {
     191             :     int i;
     192           2 :     int ret = 0;
     193             : 
     194           2 :     av_assert0(fmt_ctx1->nb_streams == fmt_ctx2->nb_streams);
     195           4 :     for (i = 0; i < fmt_ctx1->nb_streams; i++) {
     196           2 :         const AVOption *opt = NULL;
     197           2 :         const AVStream *st1 = fmt_ctx1->streams[i];
     198           2 :         const AVStream *st2 = fmt_ctx2->streams[i];
     199           2 :         AVCodecContext *codec_ctx1 = st1->codec;
     200           2 :         AVCodecContext *codec_ctx2 = st2->codec;
     201             : 
     202           2 :         if (codec_ctx1->codec_type != AVMEDIA_TYPE_VIDEO)
     203           0 :             continue;
     204             : 
     205         854 :         while (opt = av_opt_next(codec_ctx1, opt)) {
     206         850 :             uint8_t *str1 = NULL, *str2 = NULL;
     207             : 
     208         850 :             if (opt->type == AV_OPT_TYPE_CONST)
     209        1070 :                 continue;
     210             : 
     211         316 :             if (!strcmp(opt->name, "frame_number"))
     212           2 :                 continue;
     213             : 
     214         314 :             av_assert0(av_opt_get(codec_ctx1, opt->name, 0, &str1) >= 0);
     215         314 :             av_assert0(av_opt_get(codec_ctx2, opt->name, 0, &str2) >= 0);
     216         314 :             if (strcmp(str1, str2)) {
     217           0 :                 av_log(NULL, AV_LOG_ERROR, "Field %s differs: %s %s", opt->name, str1, str2);
     218           0 :                 ret = AVERROR(EINVAL);
     219             :             }
     220         314 :             av_free(str1);
     221         314 :             av_free(str2);
     222             :         }
     223             :     }
     224             : 
     225           2 :     return ret;
     226             : }
     227             : 
     228           2 : int main(int argc, char* argv[])
     229             : {
     230           2 :     int ret = 0;
     231           2 :     AVFormatContext *fmt_ctx = NULL;
     232           2 :     AVFormatContext *fmt_ctx_no_decode = NULL;
     233             : 
     234           2 :     av_register_all();
     235             : 
     236           2 :     if (argc < 2) {
     237           0 :         av_log(NULL, AV_LOG_ERROR, "Usage: %s <input>\n", argv[0]);
     238           0 :         return -1;
     239             :     }
     240             : 
     241           2 :     if ((ret = open_and_probe_video_streams(&fmt_ctx_no_decode, argv[1], 0)) < 0) {
     242           0 :         av_log(NULL, AV_LOG_ERROR, "Failed to probe '%s' without frame decoding\n", argv[1]);
     243           0 :         goto end;
     244             :     }
     245             : 
     246           2 :     if ((ret = open_and_probe_video_streams(&fmt_ctx, argv[1], 1)) < 0) {
     247           0 :         av_log(NULL, AV_LOG_ERROR, "Failed to probe '%s' with frame decoding\n", argv[1]);
     248           0 :         goto end;
     249             :     }
     250             : 
     251           2 :     ret = check_video_streams(fmt_ctx, fmt_ctx_no_decode);
     252             : 
     253             : end:
     254           2 :     avformat_close_input(&fmt_ctx);
     255           2 :     avformat_close_input(&fmt_ctx_no_decode);
     256             : 
     257           2 :     return ret;
     258             : }

Generated by: LCOV version 1.12