diff --git a/src/controls/controls.ts b/src/controls/controls.ts
index 2fa610f3..2e523885 100644
--- a/src/controls/controls.ts
+++ b/src/controls/controls.ts
@@ -12,7 +12,8 @@ import { VgScrubBarCuePoints } from './vg-scrub-bar/vg-scrub-bar-cue-points/vg-s
 import { VgScrubBarCurrentTime } from './vg-scrub-bar/vg-scrub-bar-current-time/vg-scrub-bar-current-time';
 import { VgTimeDisplay, VgUtcPipe } from './vg-time-display/vg-time-display';
 import { VgTrackSelector } from './vg-track-selector/vg-track-selector';
-import { VgControlsHidden } from './../core/services/vg-controls-hidden';
+import { VgControlsHidden } from '../core/services/vg-controls-hidden';
+import { VgQualitySelector } from './vg-quality-selector/vg-quality-selector';
 
 @NgModule({
     imports: [ CommonModule ],
@@ -29,7 +30,8 @@ import { VgControlsHidden } from './../core/services/vg-controls-hidden';
         VgScrubBarCurrentTime,
         VgTimeDisplay,
         VgUtcPipe,
-        VgTrackSelector
+        VgTrackSelector,
+        VgQualitySelector
     ],
     exports: [
         VgControls,
@@ -44,7 +46,8 @@ import { VgControlsHidden } from './../core/services/vg-controls-hidden';
         VgScrubBarCurrentTime,
         VgTimeDisplay,
         VgUtcPipe,
-        VgTrackSelector
+        VgTrackSelector,
+        VgQualitySelector
     ],
     providers: [ VgControlsHidden ]
 })
diff --git a/src/controls/vg-quality-selector/vg-quality-selector.spec.ts b/src/controls/vg-quality-selector/vg-quality-selector.spec.ts
new file mode 100644
index 00000000..ad940292
--- /dev/null
+++ b/src/controls/vg-quality-selector/vg-quality-selector.spec.ts
@@ -0,0 +1,22 @@
+import { VgQualitySelector } from "./vg-quality-selector";
+import { VgAPI } from "../../core/services/vg-api";
+import { ElementRef } from "@angular/core";
+
+describe('Quality Selector control', () => {
+    let vgQualitySelector: VgQualitySelector;
+
+    beforeEach(() => {
+        const ref: ElementRef = {
+            nativeElement: {
+                getAttribute: (name) => {
+                    return name;
+                }
+            }
+        };
+        vgQualitySelector = new VgQualitySelector(ref, new VgAPI());
+    });
+
+    describe('onPlayerReady', () => {
+
+    });
+});
diff --git a/src/controls/vg-quality-selector/vg-quality-selector.ts b/src/controls/vg-quality-selector/vg-quality-selector.ts
new file mode 100644
index 00000000..33ac124a
--- /dev/null
+++ b/src/controls/vg-quality-selector/vg-quality-selector.ts
@@ -0,0 +1,142 @@
+import {
+    Component,
+    ElementRef,
+    OnInit,
+    Input,
+    ViewEncapsulation,
+    OnDestroy,
+    SimpleChanges,
+    OnChanges, Output, EventEmitter
+} from '@angular/core';
+import { VgAPI } from '../../core/services/vg-api';
+import { Subscription } from 'rxjs/Subscription';
+import { BitrateOption } from '../../core/core';
+
+@Component({
+    selector: 'vg-quality-selector',
+    encapsulation: ViewEncapsulation.None,
+    template: `
+        <div class="container">
+            <div class="quality-selected"
+                 [class.vg-icon-closed_caption]="!bitrateSelected">
+                {{ bitrateSelected?.label }}
+            </div>
+            
+            <select class="quality-selector" 
+                    (change)="selectBitrate($event.target.value)"
+                    tabindex="0"
+                    aria-label="quality selector"
+                    [attr.aria-valuetext]="ariaValue">
+                <option 
+                    *ngFor="let bitrate of bitrates"
+                    [value]="bitrate.qualityIndex"
+                    [selected]="bitrate.qualityIndex === bitrateSelected.qualityIndex">
+                    {{ bitrate.label }}
+                </option>
+            </select>
+        </div>
+    `,
+    styles: [ `
+        vg-quality-selector {
+            -webkit-touch-callout: none;
+            -webkit-user-select: none;
+            -moz-user-select: none;
+            -ms-user-select: none;
+            user-select: none;
+            display: flex;
+            justify-content: center;
+            width: 50px;
+            height: 50px;
+            cursor: pointer;
+            color: white;
+            line-height: 50px;
+        }
+        vg-quality-selector .container {
+            position: relative;
+            display: flex;
+            flex-grow: 1;
+            align-items: center;
+            
+            padding: 0;
+            margin: 5px;
+        }
+        vg-quality-selector select.quality-selector {
+            width: 50px;
+            padding: 5px 8px;
+            border: none;
+            background: none;
+            -webkit-appearance: none;
+            -moz-appearance: none;
+            appearance: none;
+            color: transparent;
+            font-size: 16px;
+        }
+        vg-quality-selector select.quality-selector::-ms-expand {
+            display: none;
+        }
+        vg-quality-selector select.quality-selector option {
+            color: #000;
+        }
+        vg-quality-selector .quality-selected {
+            position: absolute;
+            width: 100%;
+            height: 50px;
+            top: -6px;
+            text-align: center;
+            text-transform: uppercase;
+            font-family: Helvetica Neue, Helvetica, Arial, sans-serif;
+            padding-top: 2px;
+            pointer-events: none;
+        }
+        vg-quality-selector .vg-icon-closed_caption:before {
+            width: 100%;
+        }
+    ` ]
+})
+export class VgQualitySelector implements OnInit, OnChanges, OnDestroy {
+    @Input() vgFor: string;
+    @Input() bitrates: BitrateOption[];
+
+    @Output() onBitrateChange: EventEmitter<BitrateOption> = new EventEmitter();
+
+    bitrateSelected: BitrateOption;
+
+    elem: HTMLElement;
+    target: any;
+
+    subscriptions: Subscription[] = [];
+
+    ariaValue: string;
+
+    constructor(ref: ElementRef, public API: VgAPI) {
+        this.elem = ref.nativeElement;
+    }
+
+    ngOnInit() {
+        if (this.API.isPlayerReady) {
+            this.onPlayerReady();
+        }
+        else {
+            this.subscriptions.push(this.API.playerReadyEvent.subscribe(() => this.onPlayerReady()));
+        }
+    }
+
+    ngOnChanges(changes: SimpleChanges) {
+        if (changes['bitrates'].currentValue && changes['bitrates'].currentValue.length) {
+            this.bitrates.forEach(item => item.label = item.label || Math.round(item.bitrate / 1000).toString())
+        }
+    }
+
+    onPlayerReady() {
+        this.target = this.API.getMediaById(this.vgFor);
+    }
+
+    selectBitrate(index: number) {
+        this.bitrateSelected = this.bitrates[index];
+        this.onBitrateChange.emit(this.bitrates[index]);
+    }
+
+    ngOnDestroy() {
+        this.subscriptions.forEach(s => s.unsubscribe());
+    }
+}
diff --git a/src/core/core.ts b/src/core/core.ts
index f65c882f..59bd07fc 100644
--- a/src/core/core.ts
+++ b/src/core/core.ts
@@ -29,6 +29,15 @@ export * from './vg-media/i-media-element';
 // utility classes
 export * from './vg-media/vg-media-element';
 
+export interface BitrateOption {
+    qualityIndex: number;
+    width: number;
+    height: number;
+    bitrate: number;
+    mediaType: string;
+    label?: string;
+}
+
 /**
  * @internal
  */
diff --git a/src/streaming/vg-dash/vg-dash.ts b/src/streaming/vg-dash/vg-dash.ts
index e1e2434d..55f76f12 100644
--- a/src/streaming/vg-dash/vg-dash.ts
+++ b/src/streaming/vg-dash/vg-dash.ts
@@ -1,17 +1,33 @@
-import { Directive, ElementRef, Input, SimpleChanges, OnChanges, OnDestroy, OnInit } from "@angular/core";
+import {
+    Directive,
+    ElementRef,
+    Input,
+    SimpleChanges,
+    OnChanges,
+    OnDestroy,
+    OnInit,
+    Output,
+    EventEmitter
+} from "@angular/core";
 import { VgAPI } from '../../core/services/vg-api';
 import { Subscription } from 'rxjs/Subscription';
 import { IDRMLicenseServer } from '../streaming';
+import { BitrateOption } from '../../core/core';
 
 declare let dashjs;
 
 @Directive({
-    selector: '[vgDash]'
+    selector: '[vgDash]',
+    exportAs: 'vgDash'
 })
 export class VgDASH implements OnInit, OnChanges, OnDestroy {
     @Input() vgDash:string;
     @Input() vgDRMToken:string;
     @Input() vgDRMLicenseServer:IDRMLicenseServer;
+    @Input() vgDashBitrate: BitrateOption;
+    @Input() vgDashAuto = true;
+
+    @Output() onGetBitrates: EventEmitter<BitrateOption[]> = new EventEmitter();
 
     vgFor: string;
     target: any;
@@ -37,12 +53,16 @@ export class VgDASH implements OnInit, OnChanges, OnDestroy {
     }
 
     ngOnChanges(changes:SimpleChanges) {
-        if (changes['vgDash'].currentValue) {
+        if (changes['vgDash'] && changes['vgDash'].currentValue) {
             this.createPlayer();
         }
         else {
             this.destroyPlayer();
         }
+
+        if (changes['vgDashBitrate'] && changes['vgDashBitrate'].currentValue) {
+            this.setBitrate(changes['vgDashBitrate'].currentValue);
+        }
     }
 
     createPlayer() {
@@ -72,6 +92,43 @@ export class VgDASH implements OnInit, OnChanges, OnDestroy {
             this.dash.initialize(this.ref.nativeElement);
             this.dash.setAutoPlay(false);
 
+            this.dash.on(dashjs.MediaPlayer.events.STREAM_INITIALIZED, () => {
+                const audioList = this.dash.getBitrateInfoListFor('audio');
+                const videoList = this.dash.getBitrateInfoListFor('video');
+
+                if (audioList.length > 1) {
+                    if (this.vgDashAuto) {
+                        audioList.forEach(item => item.qualityIndex = ++item.qualityIndex);
+                        audioList.unshift({
+                            qualityIndex: 0,
+                            width: 0,
+                            height: 0,
+                            bitrate: 0,
+                            mediaType: 'video',
+                            label: 'AUTO'
+                        });
+                    }
+
+                    this.onGetBitrates.emit(audioList);
+                }
+
+                if (videoList.length > 1) {
+                    if (this.vgDashAuto) {
+                        videoList.forEach(item => item.qualityIndex = ++item.qualityIndex);
+                        videoList.unshift({
+                            qualityIndex: 0,
+                            width: 0,
+                            height: 0,
+                            bitrate: 0,
+                            mediaType: 'video',
+                            label: 'AUTO'
+                        });
+                    }
+
+                    this.onGetBitrates.emit(videoList);
+                }
+            });
+
             if (drmOptions) {
                 this.dash.setProtectionData(drmOptions);
             }
@@ -87,6 +144,24 @@ export class VgDASH implements OnInit, OnChanges, OnDestroy {
         }
     }
 
+    setBitrate(bitrate: BitrateOption) {
+        if (this.dash) {
+            if (bitrate.qualityIndex > 0) {
+                if (this.dash.getAutoSwitchQualityFor(bitrate.mediaType)) {
+                    this.dash.setAutoSwitchQualityFor(bitrate.mediaType, false);
+                }
+
+                if (this.vgDashAuto) {
+                    this.dash.setQualityFor(bitrate.mediaType, bitrate.qualityIndex - 1);
+                } else {
+                    this.dash.setQualityFor(bitrate.mediaType, bitrate.qualityIndex);
+                }
+            } else {
+                this.dash.setAutoSwitchQualityFor(bitrate.mediaType, true);
+            }
+        }
+    }
+
     destroyPlayer() {
         if (this.dash) {
             this.dash.reset();