//win32显示
static void Show(HWND hwnd, unsigned char* rgb, int w, int h, bool fill)
{
HDC hdc = GetDC(hwnd);//获取当前的显示设备上下文
RECT rect;
GetClientRect(hwnd, &rect);
int cxClient = rect.right;
int cyClient = rect.bottom;
if (cxClient <= 0 || cyClient <= 0) {
return;
}
HDC hdcsource = CreateCompatibleDC(NULL);//创建存放图象的显示缓冲
HBITMAP bitmap = CreateCompatibleBitmap(hdc, cxClient, cyClient);
SelectObject(hdcsource, bitmap); //将位图资源装入显示缓冲
SetStretchBltMode(hdcsource, COLORONCOLOR);
BITMAPINFO bmi;
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = w;
bmi.bmiHeader.biHeight = -h;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biBitCount = 24;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biClrUsed = 0;
bmi.bmiHeader.biClrImportant = 0;
bmi.bmiHeader.biSizeImage = 0;
if (!fill) {
int des_x = 0;
int des_y = 0;
int des_w = 0;
int des_h = 0;
if (1.0*cxClient / cyClient > 1.0*w / h) {
des_h = cyClient;
des_w = des_h * w / h;
des_x = (cxClient - des_w) / 2;
des_y = 0;
}
else {
des_w = cxClient;
des_h = des_w * h / w;
des_x = 0;
des_y = (cyClient - des_h) / 2;
}
BitBlt(hdcsource, 0, 0, cxClient, cyClient, hdcsource, 0, 0, SRCCOPY);
StretchDIBits(hdcsource, des_x, des_y, des_w, des_h, \
0, 0, w, h, rgb, &bmi, DIB_RGB_COLORS, SRCCOPY);
BitBlt(hdc, 0, 0, cxClient, cyClient, hdcsource, 0, 0, SRCCOPY);
}
else {
StretchDIBits(hdcsource, 0, 0, rect.right - rect.left, rect.bottom - rect.top, \
0, 0, w, h, rgb, &bmi, DIB_RGB_COLORS, SRCCOPY);
BitBlt(hdc, 0, 0, cxClient, cyClient, hdcsource, 0, 0, SRCCOPY);//将图象显示缓冲的内容直接显示到屏幕
}
DeleteObject(bitmap);
DeleteDC(hdcsource);
ReleaseDC(hwnd, hdc);
}
static LRESULT CALLBACK WinProc(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lparam)
{
switch (umsg)
{
case WM_KEYDOWN:
{
if (wparam == VK_SPACE) {
}
}
break;
case WM_LBUTTONDOWN:
{
}
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, umsg, wparam, lparam);
}
static char *dup_wchar_to_utf8(wchar_t *w)
{
char *s = NULL;
int l = WideCharToMultiByte(CP_UTF8, 0, w, -1, 0, 0, 0, 0);
s = (char *)av_malloc(l);
if (s)
WideCharToMultiByte(CP_UTF8, 0, w, -1, s, l, 0, 0);
return s;
}
//
static int write_frame(AVFormatContext *fmt_ctx, const AVRational *time_base, AVStream *st, AVPacket *pkt)
{
/* rescale output packet timestamp values from codec to stream timebase */
av_packet_rescale_ts(pkt, *time_base, st->time_base);
pkt->stream_index = st->index;
/* Write the compressed frame to the media file. */
av_interleaved_write_frame(fmt_ctx, NULL);
//log_packet(fmt_ctx, pkt);
return av_interleaved_write_frame(fmt_ctx, pkt);
}
声音avframe创建
static AVFrame *alloc_audio_frame(enum AVSampleFormat sample_fmt, uint64_t channel_layout, int chnls, int sample_rate, int nb_samples)
{
AVFrame *frame = av_frame_alloc();
int ret;
if (!frame) {
fprintf(stderr, "Error allocating an audio frame\n");
return NULL;
}
frame->format = sample_fmt;
frame->channel_layout = channel_layout;
frame->channels = chnls;
frame->sample_rate = sample_rate;
frame->nb_samples = nb_samples;
if (nb_samples) {
ret = av_frame_get_buffer(frame, 1);
if (ret < 0) {
fprintf(stderr, "Error allocating an audio buffer\n");
return NULL;
}
}
return frame;
}
//图片avframe创建
static AVFrame *alloc_picture(enum AVPixelFormat pix_fmt, int width, int height)
{
AVFrame *picture;
int ret;
picture = av_frame_alloc();
if (!picture)
return NULL;
picture->format = pix_fmt;
picture->width = width;
picture->height = height;
/* allocate the buffers for the frame data */
ret = av_frame_get_buffer(picture, 4);
if (ret < 0) {
fprintf(stderr, "Could not allocate frame data.\n");
return NULL;
}
return picture;
}
//链表队列
static int initFrameList(FrameList **pFrameList, int max) {
int ret = 0;
FrameList* p = NULL;
*pFrameList = (FrameList*)av_mallocz(sizeof(FrameList));
p = *pFrameList;
if (p == NULL) return -1;
ret = pthread_mutex_init(&p->mutex, NULL);
if (ret != 0) {
av_freep(p);
return -1;
}
ret = pthread_cond_init(&p->cond, NULL);
if (ret != 0) {
av_freep(&p);
return -1;
}
ret = pthread_cond_init(&p->wait, NULL);
if (ret != 0) {
av_freep(&p);
return -1;
}
p->max = max;
return 0;
}
static int pushFrame(FrameList *p, AVFrame *avframe, int64_t pts) {
int ret = 0;
Frame *frm = NULL;
if (p == NULL || p->exit) { return 0; }
pthread_mutex_lock(&p->mutex);
while (!p->exit && p->frmSize > p->max) {
pthread_cond_wait(&p->wait, &p->mutex);
}
if (p->exit) {
pthread_mutex_unlock(&p->mutex);
return 0;
}
frm = (Frame*)av_mallocz(sizeof(Frame));
if (frm) {
frm->pts = pts;
frm->avframe = alloc_picture((AVPixelFormat)avframe->format, avframe->width, avframe->height);
av_frame_copy(frm->avframe, avframe);
if (p->end == NULL) {
p->frame = frm;
}
else {
p->end->next = frm;
}
p->end = frm;
p->frmSize++;
ret = 1;
pthread_cond_signal(&p->cond);
}
pthread_mutex_unlock(&p->mutex);
return ret;
}
static int64_t popFrame(FrameList *p, AVFrame **avframe) {
int64_t ret = 0;
if (p == NULL || p->exit) return 0;
pthread_mutex_lock(&p->mutex);
while (!p->exit && p->frmSize < 1) {
pthread_cond_wait(&p->cond, &p->mutex);
}
if (p->exit) {
pthread_mutex_unlock(&p->mutex);
return -1;
}
if (p->frame == p->end) {
ret = p->frame->pts;
*avframe = alloc_picture((AVPixelFormat)p->frame->avframe->format, p->frame->avframe->width, p->frame->avframe->height);
av_frame_copy(*avframe, p->frame->avframe);
av_frame_free(&p->frame->avframe);
av_freep(&p->frame);
p->frame = NULL;
p->end = NULL;
}
else {
Frame *temp = p->frame;
p->frame = temp->next;
ret = temp->pts;
if (temp->avframe != NULL) {
*avframe = alloc_picture((AVPixelFormat)temp->avframe->format, temp->avframe->width, temp->avframe->height);
av_frame_copy(*avframe, temp->avframe);
av_frame_free(&temp->avframe);
}
av_freep(&temp);
}
p->frmSize--;
pthread_cond_signal(&p->wait);
pthread_mutex_unlock(&p->mutex);
return ret;
}
static void destoryFrameList(FrameList *pFrameList) {
if (pFrameList == NULL) return;
{
Frame *frm = NULL;
FrameList *p = pFrameList;
pthread_mutex_lock(&p->mutex);
p->exit = 1;
frm = p->frame;
while (frm) {
Frame *temp = frm->next;
if (temp != NULL) {
av_frame_unref(temp->avframe);
}
frm = temp;
}
pthread_mutex_unlock(&p->mutex);
}
}
static void clearFrameList(FrameList *pFrameList) {
if (pFrameList == NULL) return;
{
Frame *frm = NULL;
FrameList *p = pFrameList;
if (p->frmSize < 1) {
return;
}
pthread_mutex_lock(&p->mutex);
frm = p->frame;
while (frm) {
Frame *temp = frm->next;
if (temp != NULL) {
av_frame_free(&temp->avframe);
}
frm = temp;
}
p->frmSize = 0;
pthread_mutex_unlock(&p->mutex);
}
}