summaryrefslogtreecommitdiff
path: root/rotord/libavexporter.cpp
blob: ed69cec6fb3e7314cbd8b51b6cf9b8f08130ceb9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include "libavexporter.h"


bool libav::Exporter::setup(int w,int h, int bitRate, int frameRate, std::string container){
	// Initialize libavcodec, and register all codecs and formats. //
    av_register_all();


    this->w=w;
    this->h=h;
    this->bitRate=bitRate;
    this->frameRate=frameRate;
    this->container=container;

    return true;
}
bool libav::Exporter::record(std::string filename){

    // allocate the output media context //
    avformat_alloc_output_context2(&oc, NULL, NULL, filename.c_str());
    if (!oc) {
        printf("Could not deduce output format from file extension: using MPEG.\n");
        avformat_alloc_output_context2(&oc, NULL, "mpeg", filename.c_str());
    }
    if (!oc) {
        return false;
    }
    fmt = oc->oformat;

    // Add the audio and video streams using the default format codecs
    // * and initialize the codecs. //
    video_st = NULL;
    audio_st = NULL;

    if (fmt->video_codec != AV_CODEC_ID_NONE) {
        video_st = add_stream(oc, &video_codec, fmt->video_codec);
    }
    if (fmt->audio_codec != AV_CODEC_ID_NONE) {
        audio_st = add_stream(oc, &audio_codec, fmt->audio_codec);
    }

    //set initial video params
    video_st->codec->width=w;
    video_st->codec->height=h;
    video_st->codec->time_base.num = 1;//codecCtx->ticks_per_frame;
	video_st->codec->time_base.den = frameRate;
	video_st->time_base = video_st->codec->time_base;
		//audioStream->time_base = codecCtx->time_base; //???has the capability of crashing

	video_st->codec->gop_size = 10; /* emit one intra frame every ten frames */
	video_st->codec->pix_fmt = PIX_FMT_YUV420P;

    // Now that all the parameters are set, we can open the audio and
    // * video codecs and allocate the necessary encode buffers. //
    if (video_st)
        open_video(oc, video_codec, video_st);
    if (audio_st)
        size=open_audio(oc, audio_codec, audio_st);

    std::cerr << "opened audio codec with "<<size<<" frame size"<<std::endl;

    av_dump_format(oc, 0, filename.c_str(), 1);

    // open the output file, if needed //
    if (!(fmt->flags & AVFMT_NOFILE)) {
        int ret = avio_open(&oc->pb, filename.c_str(), AVIO_FLAG_WRITE);
        if (ret < 0) {
            std::cerr <<"Could not open " << filename.c_str() << std::endl;
        	return false;
        }
    }

    // Write the stream header, if any. //
    int ret = avformat_write_header(oc, NULL);
    if (ret < 0) {
        //std::cerr <<"Error occurred when opening output file:" << av_err2str(ret) << std::endl;
        return false;
    }

    if (frame)
        frame->pts = 0;

    outputframe=0;

    return true;
}
bool libav::Exporter::encodeFrame(unsigned char *pixels,uint16_t *samples){
	// Compute current audio and video time. //
    if (audio_st)
        audio_pts = (double)audio_st->pts.val * audio_st->time_base.num / audio_st->time_base.den;
    else
        audio_pts = 0.0;

    if (video_st)
        video_pts = (double)video_st->pts.val * video_st->time_base.num /
                    video_st->time_base.den;
    else
        video_pts = 0.0;

    // write interleaved audio and video frames //
    if (!video_st || (video_st && audio_st && audio_pts < video_pts)) {
        write_audio_frame(oc, audio_st, samples);
    } else {
        write_video_frame(oc, video_st, pixels);

        frame->pts += av_rescale_q(1, video_st->codec->time_base, video_st->time_base);
    }

    //std::cerr << "encoded frame " << outputframe << std::endl;
    outputframe++;

    return true;
}
void libav::Exporter::finishRecord(){

	av_write_trailer(oc);
	// Close each codec. //
    if (video_st)
        close_video(oc, video_st);
    if (audio_st)
        close_audio(oc, audio_st);

    if (!(fmt->flags & AVFMT_NOFILE))
        // Close the output file. //
        avio_close(oc->pb);

    // free the stream //
    avformat_free_context(oc);
}