Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1165908
  • 博文数量: 173
  • 博客积分: 4048
  • 博客等级:
  • 技术积分: 2679
  • 用 户 组: 普通用户
  • 注册时间: 2010-09-12 18:53
文章分类

全部博文(173)

文章存档

2018年(1)

2016年(1)

2013年(1)

2012年(118)

2011年(52)

分类: 嵌入式

2012-04-12 10:45:39

编译totorial03.c的命令为:
gcc -o tutorial03 tutorial03.c -lavformat -lavcodec -lz -lm -lswscale `sdl-config --cflags --libs`

点击(此处)折叠或打开

  1. #include <libavcodec/avcodec.h>
  2.     #include <libavformat/avformat.h>
  3.     #include <libswscale/swscale.h>
  4.       
  5.     #include <SDL/SDL.h>
  6.     #include <SDL/SDL_thread.h>
  7.       
  8.     #include <stdio.h>
  9.       
  10.     #define SDL_AUDIO_BUFFER_SIZE 1024
  11.       
  12.       
  13.     typedef struct PacketQueue {
  14.         AVPacketList *first_pkt, *last_pkt;
  15.         int nb_packets;
  16.         int size;
  17.         SDL_mutex *mutex;
  18.         SDL_cond *cond;
  19.     } PacketQueue;
  20.       
  21.     PacketQueue audioq;
  22.       
  23.     int quit = 0;
  24.       
  25.     void packet_queue_init(PacketQueue *q) {
  26.         memset(q, 0, sizeof(PacketQueue));
  27.         q->mutex = SDL_CreateMutex();
  28.         q->cond = SDL_CreateCond();
  29.     }
  30.       
  31.     int packet_queue_put(PacketQueue *q, AVPacket *pkt) {
  32.         AVPacketList *pkt1;
  33.         if (av_dup_packet(pkt) < 0) {
  34.             return -1;
  35.         }
  36.         pkt1 = av_malloc(sizeof(AVPacketList));
  37.         if (!pkt1) {
  38.             return -1;
  39.         }
  40.         pkt1->pkt = *pkt;
  41.         pkt1->next = NULL;
  42.       
  43.         SDL_LockMutex(q->mutex);
  44.       
  45.         if (!q->last_pkt) {
  46.             q->first_pkt pkt1;
  47.         } else {
  48.             q->last_pkt->next = pkt1;
  49.         }
  50.         q->last_pkt = pkt1;
  51.         q->nb_packets++;
  52.         q->size += pkt1->pkt.size;
  53.         SDL_CondSignal(q->cond);
  54.       
  55.         SDL_UnlockMutex(q->mutex);
  56.         return 0;
  57.     }
  58.       
  59.     static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)
  60.     {
  61.         AVPacketList *pkt1;
  62.         int ret;
  63.       
  64.         SDL_LockMutex(q->mutex);
  65.       
  66.         for (;;) {
  67.             if (quit) {
  68.                 ret = -1;
  69.                 break;
  70.             }
  71.       
  72.             pkt1 = q->first_pkt;
  73.             if (pkt1) {
  74.                 q->first_pkt = pkt1->next;
  75.                 if (!q->first_pkt) {
  76.                     q->last_pkt = NULL;
  77.                 }
  78.                 q->nb_packets--;
  79.                 q->size -= pkt1->pkt.size;
  80.                 *pkt = pkt1->pkt;
  81.                 av_free(pkt1);
  82.                 ret = 1;
  83.                 break;
  84.             } else if (!block) {
  85.                 ret = 0;
  86.                 break;
  87.             } else {
  88.                 SDL_CondWait(q->cond, q->mutex);
  89.             }
  90.         }
  91.         SDL_UnlockMutex(q->mutex);
  92.         return ret;
  93.     }
  94.       
  95.     int audio_decode_frame(AVCodecContext *aCodecCtx, uint8_t *audio_buf, int buf_size)
  96.     {
  97.         static AVPacket pkt;
  98.         static uint8_t *audio_pkt_data = NULL;
  99.         static int audio_pkt_size = 0;
  100.       
  101.         int len1, data_size;
  102.       
  103.         for (;;) {
  104.             while(audio_pkt_size > 0) {
  105.                 data_size = buf_size;
  106.                 len1 = avcodec_decode_audio2(aCodecCtx, (int16_t*)audio_buf, &data_size, audio_pkt_data, audio_pkt_size);
  107.                 if (len1 < 0) {
  108.                     audio_pkt_size = 0;
  109.                     break;
  110.                 }
  111.                 audio_pkt_data += len1;
  112.                 audio_pkt_size -= len1;
  113.                 if (data_size <= 0) {
  114.                     continue;
  115.                 }
  116.                 return data_size;
  117.             }
  118.             if (pkt.data) {
  119.                 av_free_packet(&pkt);
  120.             }
  121.             if (quit) {
  122.                 return -1;
  123.             }
  124.       
  125.             if (packet_queue_get(&audioq, &pkt, 1) < 0) {
  126.                 return -1;
  127.             }
  128.             audio_pkt_data = pkt.data;
  129.             audio_pkt_size = pkt.size;
  130.         }
  131.     }
  132.       
  133.     void audio_callback(void *userdata, Uint8 *stream, int len)
  134.     {
  135.         AVCodecContext *aCodecCtx = (AVCodecContext *)userdata;
  136.         int len1, audio_size;
  137.       
  138.         static uint8_t audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];
  139.         static unsigned int audio_buf_size = 0;
  140.         static unsigned int audio_buf_index = 0;
  141.       
  142.         while (len > 0) {
  143.             if (audio_buf_index >= audio_buf_size) {
  144.                 audio_size = audio_decode_frame(aCodecCtx, audio_buf, sizeof(audio_buf));
  145.                 if (audio_size < 0) {
  146.                     audio_buf_size = 1024;
  147.                     memset(audio_buf, 0, audio_buf_size);
  148.                 } else {
  149.                     audio_buf_size = audio_size;
  150.                 }
  151.                 audio_buf_index = 0;
  152.             }
  153.             len1 = audio_buf_size - audio_buf_index;
  154.             if (len1 > len) {
  155.                 len1 = len;
  156.             }
  157.             memcpy(stream, (uint8_t*)audio_buf + audio_buf_index, len1);
  158.             len -= len1;
  159.             stream += len1;
  160.             audio_buf_index += len1;
  161.         }
  162.     }
  163.       
  164.     int main(int argc, char *argv[]) {
  165.         AVFormatContext *pFormatCtx;
  166.         int i, videoStream, audioStream;
  167.         AVCodecContext *pCodecCtx;
  168.         AVCodec *pCodec;
  169.         AVFrame *pFrame;
  170.         AVPacket packet;
  171.         int frameFinished;
  172.         float aspect_ratio;
  173.         struct SwsContext *img_convert_ctx;
  174.       
  175.         AVCodecContext *aCodecCtx;
  176.         AVCodec *aCodec;
  177.       
  178.         SDL_Overlay *bmp;
  179.         SDL_Surface *screen;
  180.         SDL_Rect rect;
  181.         SDL_Event event;
  182.         SDL_AudioSpec wanted_spec, spec;
  183.       
  184.         if (argc < 2) {
  185.             fprintf(stderr, "Usage: test \n");
  186.             exit(1);
  187.         }
  188.         av_register_all();
  189.       
  190.         if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {
  191.             fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
  192.             exit(1);
  193.         }
  194.       
  195.         if (av_open_input_file(&pFormatCtx, argv[1], NULL, 0, NULL) != 0) {
  196.             return -1;
  197.         }
  198.       
  199.         if (av_find_stream_info(pFormatCtx) < 0) {
  200.             return -1;
  201.         }
  202.       
  203.         dump_format(pFormatCtx, 0, argv[1], 0);
  204.       
  205.         videoStream = -1;
  206.         audioStream = -1;
  207.         for (i=0; i<pFormatCtx->nb_streams; i++) {
  208.             if (pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO && videoStream < 0) {
  209.                 videoStream = i;
  210.             }
  211.             if (pFormatCtx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO && audioStream < 0) {
  212.                 audioStream = i;
  213.             }
  214.         }
  215.       
  216.         if (videoStream == -1) {
  217.             return -1;
  218.         }
  219.         if (audioStream == -1) {
  220.             return -1;
  221.         }
  222.       
  223.         aCodecCtx = pFormatCtx->streams[audioStream]->codec;
  224.       
  225.         wanted_spec.freq = aCodecCtx->sample_rate;
  226.         wanted_spec.format = AUDIO_S16SYS;
  227.         wanted_spec.channels = aCodecCtx->channels;
  228.         wanted_spec.silence = 0;
  229.         wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
  230.         wanted_spec.callback = audio_callback;
  231.         wanted_spec.userdata = aCodecCtx;
  232.       
  233.         if (SDL_OpenAudio(&wanted_spec, &spec) < 0) {
  234.             fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError());
  235.             return -1;
  236.         }
  237.         aCodec = avcodec_find_decoder(aCodecCtx->codec_id);
  238.         if (!aCodec) {
  239.             fprintf(stderr, "Unsupported codec!\n");
  240.             return -1;
  241.         }
  242.         avcodec_open(aCodecCtx, aCodec);
  243.       
  244.         packet_queue_init(&audioq);
  245.         SDL_PauseAudio(0);
  246.       
  247.         pCodecCtx=pFormatCtx->streams[videoStream]->codec;
  248.         img_convert_ctx = sws_getContext(pCodecCtx->width,
  249.                 pCodecCtx->height,
  250.                 pCodecCtx->pix_fmt,
  251.                 pCodecCtx->width,
  252.                 pCodecCtx->height,
  253.                 PIX_FMT_YUV420P,
  254.                 SWS_BICUBIC,
  255.                 NULL, NULL, NULL);
  256.       
  257.       
  258.         pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
  259.         if (pCodec == NULL) {
  260.             fprintf(stderr, "Unsupported codec!\n");
  261.             return -1;
  262.         }
  263.         if (avcodec_open(pCodecCtx, pCodec) < 0) {
  264.             return -1;
  265.         }
  266.       
  267.         pFrame = avcodec_alloc_frame();
  268.       
  269.         screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 24, 0);
  270.       
  271.         if (!screen) {
  272.             fprintf(stderr, "SDL : could not set video mode - exiting\n");
  273.             exit(1);
  274.         }
  275.       
  276.         bmp = SDL_CreateYUVOverlay(pCodecCtx->width,
  277.                            pCodecCtx->height,
  278.                        SDL_YV12_OVERLAY,
  279.                        screen);
  280.         i = 0;
  281.         while(av_read_frame(pFormatCtx, &packet) >= 0) {
  282.             if (packet.stream_index == videoStream) {
  283.                 avcodec_decode_video(pCodecCtx, pFrame, &frameFinished,
  284.                         packet.data, packet.size);
  285.       
  286.                 if (frameFinished) {
  287.                     SDL_LockYUVOverlay(bmp);
  288.       
  289.                     AVPicture pict;
  290.                     pict.data[0] = bmp->pixels[0];
  291.                     pict.data[1] = bmp->pixels[2];
  292.                     pict.data[2] = bmp->pixels[1];
  293.       
  294.                     pict.linesize[0] = bmp->pitches[0];
  295.                     pict.linesize[1] = bmp->pitches[2];
  296.                     pict.linesize[2] = bmp->pitches[1];
  297.       
  298.                     sws_scale(img_convert_ctx,
  299.                             pFrame->data,
  300.                             pFrame->linesize, 0,
  301.                             pCodecCtx->height,
  302.                             pict.data,
  303.                             pict.linesize);
  304.       
  305.                     SDL_UnlockYUVOverlay(bmp);
  306.       
  307.                     rect.x = 0;
  308.                     rect.y = 0;
  309.                     rect.w = pCodecCtx->width;
  310.                     rect.h = pCodecCtx->height;
  311.                     SDL_DisplayYUVOverlay(bmp, &rect);
  312.                     av_free_packet(&packet);
  313.                 }
  314.             } else if (packet.stream_index == audioStream) {
  315.                 packet_queue_put(&audioq, &packet);
  316.             } else {
  317.                 av_free_packet(&packet);
  318.             }
  319.       
  320.             SDL_PollEvent(&event);
  321.             switch(event.type) {
  322.                 case SDL_QUIT:
  323.                     quit = 1;
  324.                     SDL_Quit();
  325.                     exit(0);
  326.                     break;
  327.                 default:
  328.                     break;
  329.             }
  330.         }
  331.       
  332.         av_free(pFrame);
  333.       
  334.         avcodec_close(pCodecCtx);
  335.       
  336.         av_close_input_file(pFormatCtx);
  337.       
  338.         return 0;
  339.     }


阅读(1329) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~