| 1 | //
|
|---|
| 2 | // av.c
|
|---|
| 3 | // splayer
|
|---|
| 4 | //
|
|---|
| 5 | // Created by 韩爱东 on 2018/6/25.
|
|---|
| 6 | // Copyright © 2018年 韩爱东. All rights reserved.
|
|---|
| 7 | //
|
|---|
| 8 |
|
|---|
| 9 | #include "av.h"
|
|---|
| 10 | #include <stdio.h>
|
|---|
| 11 | #include <stdlib.h>
|
|---|
| 12 | #include <string.h>
|
|---|
| 13 | #include <pthread.h>
|
|---|
| 14 | #include <unistd.h>
|
|---|
| 15 | #include "libavcodec/avcodec.h"
|
|---|
| 16 | #include "libavformat/avformat.h"
|
|---|
| 17 | #include "libswscale/swscale.h"
|
|---|
| 18 |
|
|---|
| 19 | #define INBUF_SIZE 4096
|
|---|
| 20 | AVFrame *frame;
|
|---|
| 21 | AVCodecContext *codec_ctx;
|
|---|
| 22 | pthread_mutex_t frame_lock = PTHREAD_MUTEX_INITIALIZER;
|
|---|
| 23 | #if 1
|
|---|
| 24 | static void pgm_save(unsigned char *buf, int wrap, int xsize, int ysize, char *filename)
|
|---|
| 25 | {
|
|---|
| 26 | FILE *f;
|
|---|
| 27 | int i;
|
|---|
| 28 | f = fopen(filename,"w");
|
|---|
| 29 | fprintf(f, "P5\n%d %d\n%d\n", xsize, ysize, 255);
|
|---|
| 30 | for (i = 0; i < ysize; i++)
|
|---|
| 31 | fwrite(buf + i * wrap, 1, xsize, f);
|
|---|
| 32 | fclose(f);
|
|---|
| 33 | }
|
|---|
| 34 | #endif
|
|---|
| 35 | static void decode(AVCodecContext *dec_ctx, AVFrame *frame, AVPacket *pkt, const char *filename)
|
|---|
| 36 | {
|
|---|
| 37 | char buf[1024] = {0};
|
|---|
| 38 | int ret;
|
|---|
| 39 |
|
|---|
| 40 | ret = avcodec_send_packet(dec_ctx, pkt);
|
|---|
| 41 | if (ret < 0)
|
|---|
| 42 | {
|
|---|
| 43 | fprintf(stderr, "Error sending a packet for decoding\n");
|
|---|
| 44 | return;
|
|---|
| 45 | }
|
|---|
| 46 |
|
|---|
| 47 | while (ret >= 0)
|
|---|
| 48 | {
|
|---|
| 49 | ret = avcodec_receive_frame(dec_ctx, frame);
|
|---|
| 50 | if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
|
|---|
| 51 | {
|
|---|
| 52 | printf("err ret = %d.%d, %d\n", ret, AVERROR(EAGAIN), AVERROR_EOF);
|
|---|
| 53 | return;
|
|---|
| 54 | }
|
|---|
| 55 | else if (ret < 0)
|
|---|
| 56 | {
|
|---|
| 57 | fprintf(stderr, "Error during decoding\n");
|
|---|
| 58 | return;
|
|---|
| 59 | }
|
|---|
| 60 | //printf("saving frame %3d\n", dec_ctx->frame_number);
|
|---|
| 61 | fflush(stdout);
|
|---|
| 62 | /* the picture is allocated by the decoder. no need to
|
|---|
| 63 | free it */
|
|---|
| 64 | snprintf(buf, sizeof(buf), "%s-%d", filename, dec_ctx->frame_number);
|
|---|
| 65 | pgm_save(frame->data[0], frame->linesize[0], frame->width, frame->height, buf);
|
|---|
| 66 | }
|
|---|
| 67 | }
|
|---|
| 68 |
|
|---|
| 69 | void decode_file(int t)
|
|---|
| 70 | {
|
|---|
| 71 | char *filename = "/Users/lpz/splayer/splayer/splayer/ii.mp4";
|
|---|
| 72 | char *outfilename = "/Users/lpz/splayer/splayer/splayer/test/ee";
|
|---|
| 73 | AVPacket *pkt = NULL;
|
|---|
| 74 | AVCodec *codec = NULL;
|
|---|
| 75 | AVStream *stream = NULL;
|
|---|
| 76 | AVFormatContext *fmt_ctx = NULL;
|
|---|
| 77 |
|
|---|
| 78 | int i = 0;
|
|---|
| 79 | int videoStream = 0;
|
|---|
| 80 |
|
|---|
| 81 | avformat_open_input(&fmt_ctx, filename, NULL, NULL);//打开一个视频
|
|---|
| 82 | avformat_find_stream_info(fmt_ctx, NULL);//读取视频,然后得到流和码率等信息
|
|---|
| 83 | av_dump_format(fmt_ctx, 0, filename, 0);
|
|---|
| 84 | for(i = 0; i < fmt_ctx->nb_streams; ++i)
|
|---|
| 85 | {
|
|---|
| 86 | stream = fmt_ctx->streams[i];
|
|---|
| 87 | if(fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
|
|---|
| 88 | {
|
|---|
| 89 | videoStream=i;
|
|---|
| 90 |
|
|---|
| 91 | break;
|
|---|
| 92 | }
|
|---|
| 93 | }
|
|---|
| 94 | printf("videoStream = %d\n", videoStream);
|
|---|
| 95 |
|
|---|
| 96 | codec = avcodec_find_decoder(stream->codecpar->codec_id);
|
|---|
| 97 | codec_ctx = avcodec_alloc_context3(codec);//需要使用avcodec_free_context释放
|
|---|
| 98 |
|
|---|
| 99 | //事实上codecpar包含了大部分解码器相关的信息,这里是直接从AVCodecParameters复制到AVCodecContext
|
|---|
| 100 | avcodec_parameters_to_context(codec_ctx, stream->codecpar);
|
|---|
| 101 | avcodec_open2(codec_ctx, codec, NULL);
|
|---|
| 102 |
|
|---|
| 103 | pkt = av_packet_alloc();
|
|---|
| 104 | if (!pkt)
|
|---|
| 105 | {
|
|---|
| 106 | return;
|
|---|
| 107 | }
|
|---|
| 108 |
|
|---|
| 109 | frame = av_frame_alloc();
|
|---|
| 110 | if (!frame)
|
|---|
| 111 | {
|
|---|
| 112 | fprintf(stderr, "Could not allocate video frame\n");
|
|---|
| 113 | return;
|
|---|
| 114 | }
|
|---|
| 115 | while(av_read_frame(fmt_ctx, pkt) >= 0)
|
|---|
| 116 | {
|
|---|
| 117 | printf("pkt->size = %d. %d\n", pkt->size, pkt->stream_index);
|
|---|
| 118 | if(pkt->stream_index == videoStream && pkt->size > 0)
|
|---|
| 119 | {
|
|---|
| 120 | //pthread_mutex_lock(&frame_lock);
|
|---|
| 121 | decode(codec_ctx, frame, pkt, outfilename);
|
|---|
| 122 | //printf("frame = %#x, %d, %d.\n", frame->data[0], frame->width, frame->height);
|
|---|
| 123 | //pthread_mutex_unlock(&frame_lock);
|
|---|
| 124 | }
|
|---|
| 125 |
|
|---|
| 126 | usleep(40000);
|
|---|
| 127 | }
|
|---|
| 128 | /* flush the decoder */
|
|---|
| 129 | avcodec_close(codec_ctx);
|
|---|
| 130 | avcodec_free_context(&codec_ctx);
|
|---|
| 131 | av_frame_free(&frame);
|
|---|
| 132 | av_packet_free(&pkt);
|
|---|
| 133 | return;
|
|---|
| 134 | }
|
|---|
| 135 |
|
|---|
| 136 | int main()
|
|---|
| 137 | {
|
|---|
| 138 | pthread_t tid;
|
|---|
| 139 | if(pthread_mutex_init(&frame_lock, NULL) != 0)
|
|---|
| 140 | {
|
|---|
| 141 | return -1;
|
|---|
| 142 | }
|
|---|
| 143 |
|
|---|
| 144 | pthread_create(&tid, NULL, (void *)&decode_file, &tid);
|
|---|
| 145 | sleep(100);
|
|---|
| 146 | return 0;
|
|---|
| 147 | }
|
|---|