[Libav-user] 回复: 回复: 回复: just wanna get a decode demo for libav

坚定前行 powerpan at qq.com
Sat May 13 11:46:35 EEST 2017


------------------ 原始邮件 ------------------
发件人: "lingjiujianke";<lingjiujianke at gmail.com>;
发送时间: 2017年5月13日(星期六) 上午6:44
收件人: "This list is about using libavcodec, libavformat, libavutil,libavdevice and libavfilter."<libav-user at ffmpeg.org>; 
抄送: "ggarra13"<ggarra13 at gmail.com>; 
主题: Re: [Libav-user]回复: 回复: just wanna get a decode demo for libav





2017-05-13 0:05 GMT+08:00 Steven Liu <lingjiujianke at gmail.com>:


2017-05-12 21:53 GMT+08:00 坚定前行 <powerpan at qq.com>:
Hi, 


thanks for the reply but your answer didn't help. first of all, i need to register a codec and open it automatically, but decode_audio.c did not show the right way.
second, I copied a third party demo, it works well but still have some warning for the OLD API and decode_audio.c did not use the latest API to demostrate what ffmpeg suggest to do. I need a perfect demo, anybody could help?
1. 别在邮件的最上面回复内容,最好在最下面回复
2. 你是怎么跑的demo代码,全部过程能否详细描述一下
3. decode_audio.c里面是用的最新的API做音频解码的,不包含demux操作,仅仅是解码,而且是音频解码
4. 最好还是把你的全部过程和你的代码贴出来,大伙才好确认问题


除了1,  另外三点应该能得到你想要的答复,这个是api使用的列表,估计能得到你想要的答复的可能性不大,因为大伙不知道你怎么做的,不知道你代码实现,如果能够按照我说的三点做一下,也许有结果。




Best regards,
pp








------------------ 原始邮件 ------------------
发件人: "Gonzalo Garramuño";<ggarra13 at gmail.com>;
发送时间: 2017年5月12日(星期五) 晚上9:15
收件人: "This list is about using libavcodec, libavformat, libavutil, libavdevice and libavfilter."<libav-user at ffmpeg.org>; 

主题: Re: [Libav-user]回复: just wanna get a decode demo for libav



                   

     
     
     El 12/05/17 a las 07:25, 坚定前行 escribió:
     
            Hi, 
                
         
         that's the demo I tried 
                    with warning 'avcodec_decode_audio4'             is deprecated.
           and that demo could not work             with : Codec not found.
         
         
         
         Best regards,
         pp
         
       
          Usually, if you get "codec not found" it means your ffmpeg     compilation was lacking a certain codec.  The audio example uses     mpeg2 audio, so you need to have ffmpeg compiled with mpeg2.
     You can check the codecs you have by doing:
     
     $ ffmpeg -codecs
     
     For it to work, you should have a line like:
     
      DEA.L. mp2                  MP2 (MPEG audio layer 2) (decoders: mp2     mp2float ) (encoders: mp2 mp2fixed )
     
     




_______________________________________________
 Libav-user mailing list
 Libav-user at ffmpeg.org
 http://ffmpeg.org/mailman/listinfo/libav-user
 




 




给你一段diff 参考一下:




diff --git a/doc/examples/demuxing_decoding.c b/doc/examples/demuxing_decoding.c
index b1a216abb4..3c5190c28b 100644
--- a/doc/examples/demuxing_decoding.c
+++ b/doc/examples/demuxing_decoding.c
@@ -60,6 +60,84 @@ static int audio_frame_count = 0;
  * needs. Look for the use of refcount in this example to see what are the
  * differences of API usage between them. */
 static int refcount = 0;
+static void pgm_save(unsigned char *buf, int wrap, int xsize, int ysize,
+                     char *filename)
+{
+    FILE *f;
+    int i;
+
+    f = fopen(filename,"w");
+    fprintf(f, "P5\n%d %d\n%d\n", xsize, ysize, 255);
+    for (i = 0; i < ysize; i++)
+        fwrite(buf + i * wrap, 1, xsize, f);
+    fclose(f);
+}
+
+static void decode_video(AVCodecContext *dec_ctx, AVPacket *pkt, AVFrame *frame,
+                   const char *filename)
+{
+    char buf[1024];
+    int ret;
+
+    ret = avcodec_send_packet(dec_ctx, pkt);
+    if (ret < 0) {
+        fprintf(stderr, "Error sending a packet for decoding\n");
+        exit(1);
+    }
+
+    while (ret >= 0) {
+        ret = avcodec_receive_frame(dec_ctx, frame);
+        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
+            return;
+        else if (ret < 0) {
+            fprintf(stderr, "Error during decoding\n");
+            exit(1);
+        }
+
+        printf("saving frame %3d\n", dec_ctx->frame_number);
+        fflush(stdout);
+
+        /* the picture is allocated by the decoder. no need to
+           free it */
+        snprintf(buf, sizeof(buf), "%s-%d", filename, dec_ctx->frame_number);
+        pgm_save(frame->data[0], frame->linesize[0],
+                 frame->width, frame->height, buf);
+    }
+}
+
+
+static void decode_audio(AVCodecContext *dec_ctx, AVPacket *pkt, AVFrame *frame, FILE *outfile)
+{
+    int i, ch;
+    int ret, data_size;
+
+    /* send the packet with the compressed data to the decoder */
+    ret = avcodec_send_packet(dec_ctx, pkt);
+    if (ret < 0) {
+        fprintf(stderr, "Error submitting the packet to the decoder\n");
+        exit(1);
+    }
+
+    /* read all the output frames (in general there may be any number of them */
+    while (ret >= 0) {
+        ret = avcodec_receive_frame(dec_ctx, frame);
+        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
+            return;
+        else if (ret < 0) {
+            fprintf(stderr, "Error during decoding\n");
+            exit(1);
+        }
+        data_size = av_get_bytes_per_sample(dec_ctx->sample_fmt);
+        if (data_size < 0) {
+            /* This should not occur, checking just for paranoia */
+            fprintf(stderr, "Failed to calculate data size\n");
+            exit(1);
+        }
+        for (i = 0; i < frame->nb_samples; i++)
+            for (ch = 0; ch < dec_ctx->channels; ch++)
+                fwrite(frame->data[ch] + data_size*i, 1, data_size, outfile);
+    }
+}


 static int decode_packet(int *got_frame, int cached)
 {
@@ -69,73 +147,9 @@ static int decode_packet(int *got_frame, int cached)
     *got_frame = 0;


     if (pkt.stream_index == video_stream_idx) {
-        /* decode video frame */
-        ret = avcodec_decode_video2(video_dec_ctx, frame, got_frame, &pkt);
-        if (ret < 0) {
-            fprintf(stderr, "Error decoding video frame (%s)\n", av_err2str(ret));
-            return ret;
-        }
-
-        if (*got_frame) {
-
-            if (frame->width != width || frame->height != height ||
-                frame->format != pix_fmt) {
-                /* To handle this change, one could call av_image_alloc again and
-                 * decode the following frames into another rawvideo file. */
-                fprintf(stderr, "Error: Width, height and pixel format have to be "
-                        "constant in a rawvideo file, but the width, height or "
-                        "pixel format of the input video changed:\n"
-                        "old: width = %d, height = %d, format = %s\n"
-                        "new: width = %d, height = %d, format = %s\n",
-                        width, height, av_get_pix_fmt_name(pix_fmt),
-                        frame->width, frame->height,
-                        av_get_pix_fmt_name(frame->format));
-                return -1;
-            }
-
-            printf("video_frame%s n:%d coded_n:%d\n",
-                   cached ? "(cached)" : "",
-                   video_frame_count++, frame->coded_picture_number);
-
-            /* copy decoded frame to destination buffer:
-             * this is required since rawvideo expects non aligned data */
-            av_image_copy(video_dst_data, video_dst_linesize,
-                          (const uint8_t **)(frame->data), frame->linesize,
-                          pix_fmt, width, height);
-
-            /* write to rawvideo file */
-            fwrite(video_dst_data[0], 1, video_dst_bufsize, video_dst_file);
-        }
+        decode_video(video_dec_ctx, &pkt, frame, video_dst_filename);
     } else if (pkt.stream_index == audio_stream_idx) {
-        /* decode audio frame */
-        ret = avcodec_decode_audio4(audio_dec_ctx, frame, got_frame, &pkt);
-        if (ret < 0) {
-            fprintf(stderr, "Error decoding audio frame (%s)\n", av_err2str(ret));
-            return ret;
-        }
-        /* Some audio decoders decode only part of the packet, and have to be
-         * called again with the remainder of the packet data.
-         * Sample: fate-suite/lossless-audio/luckynight-partial.shn
-         * Also, some decoders might over-read the packet. */
-        decoded = FFMIN(ret, pkt.size);
-
-        if (*got_frame) {
-            size_t unpadded_linesize = frame->nb_samples * av_get_bytes_per_sample(frame->format);
-            printf("audio_frame%s n:%d nb_samples:%d pts:%s\n",
-                   cached ? "(cached)" : "",
-                   audio_frame_count++, frame->nb_samples,
-                   av_ts2timestr(frame->pts, &audio_dec_ctx->time_base));
-
-            /* Write the raw audio data samples of the first plane. This works
-             * fine for packed formats (e.g. AV_SAMPLE_FMT_S16). However,
-             * most audio decoders output planar audio, which uses a separate
-             * plane of audio samples for each channel (e.g. AV_SAMPLE_FMT_S16P).
-             * In other words, this code will write only the first audio channel
-             * in these cases.
-             * You should use libswresample or libavfilter to convert the frame
-             * to packed data. */
-            fwrite(frame->extended_data[0], 1, unpadded_linesize, audio_dst_file);
-        }
+        decode_audio(audio_dec_ctx, &pkt, frame, audio_dst_file);
     }


     /* If we use frame reference counting, we own the data and need


感谢回复。觉得用英文比较通用一点,别人能看明白,开源就是共享嘛。
Will try this later. this solved the “avcodec_decode_audio4” problem.


still have some problem, below code will choose codec automatically, but will have warning like:
decode_demo.c:86:2: warning: 'codec' is deprecated (declared at /work/tools/ffmpeg-3.3/libavformat/avformat.h:893) [-Wdeprecated-declarations]
  pCodecCtx=pFormatCtx->streams[audioStream]->codec;
-----------------------------
decode_demo.c initial code:
	AVFormatContext	*pFormatCtx;
	int				i, audioStream;
	AVCodecContext	*pCodecCtx;
	AVCodec			*pCodec;


       ...........



	av_register_all();
	avformat_network_init();
	pFormatCtx = avformat_alloc_context();
	
	//Open
	if(avformat_open_input(&pFormatCtx,url,NULL,NULL)!=0){
		printf("Couldn't open input stream.\n");
		return -1;
	}
	
	// Retrieve stream information
	if(avformat_find_stream_info(pFormatCtx,NULL)<0){
		printf("Couldn't find stream information.\n");
		return -1;
	}
	
	// Dump valid information onto standard error
	av_dump_format(pFormatCtx, 0, url, 0);


	// Find the first audio stream
	audioStream=-1;
	for(i=0; i < pFormatCtx->nb_streams; i++)
		if(pFormatCtx->streams[i]->codecpar->codec_type==AVMEDIA_TYPE_AUDIO){	
			audioStream=i;
			break;
		}


	if(audioStream==-1){
		printf("Didn't find a audio stream.\n");
		return -1;
	}


	// Get a pointer to the codec context for the audio stream
	pCodecCtx=pFormatCtx->streams[audioStream]->codec;	// by power
	
	// Find the decoder for the audio stream
	//pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
	pCodec=avcodec_find_decoder(pFormatCtx->streams[i]->codecpar->codec_id);
	if(pCodec==NULL){
		printf("Codec not found.\n");
		return -1;
	}
	
	avcodec_register(pCodec);


	// Open codec
	if(avcodec_open2(pCodecCtx, pCodec, NULL)<0){
		printf("Could not open codec.\n");
		return -1;
	}


	packet=(AVPacket *)av_malloc(sizeof(AVPacket));
	av_init_packet(packet);


-------------------------
while running decode_audio.c  (already changed to codec avcodec_find_decoder(AV_CODEC_ID_APE)


./decode_audio ape_c5000.ape dd.pcm
[ape @ 0x1bf1040] Incorrect extradata
Could not open codec
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://ffmpeg.org/pipermail/libav-user/attachments/20170513/08da0a03/attachment.html>


More information about the Libav-user mailing list